------------------------------------------------------------
-- Copyright: 2010 Integrated Sytems Laboratory, ETH Zurich
--            http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use work.hamsipkg.all;

entity hamsi is

  port (
    ClkxCI      : in  std_logic;
    RstxRBI     : in  std_logic;
    FinBlockxSI : in  std_logic;
    INENxEI     : in  std_logic;
    OUTENxEO    : out std_logic;
    DxDI        : in  std_logic_vector(31 downto 0);
    DxDO        : out std_logic_vector(HWIDTH-1 downto 0));

end hamsi;

architecture rtl of hamsi is

  
  component controller
    port (
      ClkxCI          : in  std_logic;
      RstxRBI         : in  std_logic;
      FinBlockxSI     : in  std_logic;
      INENxEI         : in  std_logic;
      OUTENxEO        : out std_logic;
      TruncENxEO      : out std_logic;
      LastIterxSO     : out std_logic;
      PermInputSelxSO : out std_logic;
      ChainValSelxSO  : out std_logic;
      RcntxDO         : out unsigned(2 downto 0);
      CntxDO          : out unsigned(2 downto 0));
  end component;

  component diff256
    port (
      AxDI : in  std_logic_vector(31 downto 0);
      BxDI : in  std_logic_vector(31 downto 0);
      CxDI : in  std_logic_vector(31 downto 0);
      DxDI : in  std_logic_vector(31 downto 0);
      AxDO : out std_logic_vector(31 downto 0);
      BxDO : out std_logic_vector(31 downto 0);
      CxDO : out std_logic_vector(31 downto 0);
      DxDO : out std_logic_vector(31 downto 0));
  end component;

  component subst256
    port (
      AxDI : in  std_logic_vector(31 downto 0);
      BxDI : in  std_logic_vector(31 downto 0);
      CxDI : in  std_logic_vector(31 downto 0);
      DxDI : in  std_logic_vector(31 downto 0);
      AxDO : out std_logic_vector(31 downto 0);
      BxDO : out std_logic_vector(31 downto 0);
      CxDO : out std_logic_vector(31 downto 0);
      DxDO : out std_logic_vector(31 downto 0));
  end component;
   
  signal PermInputSelxS   : std_logic;
  signal LastIterxS       : std_logic;
  signal ChainValSelxS    : std_logic;
  signal InChainvalxD     : halfstate;
  signal OutChainValxD    : halfstate;
  signal OldChainValxD    : halfstate;
  signal SBOXOutxD        : sbox;
  signal SBOXxDN, SBOXxDP : sbox;
  signal SBOXxD           : sbox;
  signal SBOXOutAlphaxD   : sbox;
  signal SBOXInDiffxD     : sboxrow;
  signal SBOXOutDiffxD    : sboxrow;
  signal RcntxD           : unsigned(2 downto 0);
  signal CntxD            : unsigned(2 downto 0);
  signal SBOXOutXorCntxD  : sbox;
  signal SBOXOutSubstxD   : sboxrow;
  signal SBOXInSubstxD    : sboxrow;
  signal DINxD            : data;

--  signal T1xD, T2xD, T3xD, T4xD, T5xD, T6xD, T7xD                       : sboxrow;
--  signal TxD                                                            : std_logic_vector(31 downto 0);
  signal Td01xD, Td02xD, Td03xD, Td04xD, Td05xD, Td06xD, Td07xD, Td08xD : std_logic_vector(31 downto 0);
  signal Td11xD, Td12xD, Td13xD, Td14xD, Td15xD, Td16xD, Td17xD, Td18xD : std_logic_vector(31 downto 0);
  signal Td21xD, Td22xD, Td23xD, Td24xD, Td25xD, Td26xD, Td27xD, Td28xD : std_logic_vector(31 downto 0);
  signal Td31xD, Td32xD, Td33xD, Td34xD, Td35xD, Td36xD, Td37xD, Td38xD : std_logic_vector(31 downto 0);
  signal TruncENxE                                                      : std_logic;

  signal TT0xD, TT1xD, TT2xD, TT3xD : std_logic_vector(255 downto 0);      
  
begin  -- rtl

  p_inputstruct: for i in 0 to 3 generate
    DINxD(i) <= DxDI((4-i)*8-1 downto (3-i)*8);
  end generate p_inputstruct;

  u_controller : controller
    port map (
      ClkxCI          => ClkxCI,
      RstxRBI         => RstxRBI,
      FinBlockxSI     => FinBlockxSI,
      INENxEI         => INENxEI,
      OUTENxEO        => OUTENxEO,
      TruncENxEO      => TruncENxE,
      PermInputSelxSO => PermInputSelxS,
      LastIterxSO     => LastIterxS,
      ChainValSelxSO  => ChainValSelxS,
      RcntxDO         => RcntxD,
      CntxDO          => CntxD);

  u_diff256_0: diff256
    port map (
      AxDI => SBOXInDiffxD(0),
      BxDI => SBOXInDiffxD(1),
      CxDI => SBOXInDiffxD(2),
      DxDI => SBOXInDiffxD(3),
      AxDO => SBOXOutDiffxD(0),
      BxDO => SBOXOutDiffxD(1),
      CxDO => SBOXOutDiffxD(2),
      DxDO => SBOXOutDiffxD(3));

   u_subst256_0: subst256
    port map (
      AxDI => SBOXInSubstxD(0),
      BxDI => SBOXInSubstxD(1),
      CxDI => SBOXInSubstxD(2),
      DxDI => SBOXInSubstxD(3),
      AxDO => SBOXOutSubstxD(0),
      BxDO => SBOXOutSubstxD(1),
      CxDO => SBOXOutSubstxD(2),
      DxDO => SBOXOutSubstxD(3));

  

  -- Expansion and Concatenation
  -----------------------------------------------------------------------------
  TT0xD <= T256(0, to_integer(unsigned(DINxD(0))));
  TT1xD <= T256(1, to_integer(unsigned(DINxD(1))));
  TT2xD <= T256(2, to_integer(unsigned(DINxD(2))));
  TT3xD <= T256(3, to_integer(unsigned(DINxD(3))));

  SBOXxD(0,0) <= TT0xD(255 downto 224) xor TT1xD(255 downto 224) xor TT2xD(255 downto 224) xor TT3xD(255 downto 224);
  SBOXxD(0,1) <= TT0xD(223 downto 192) xor TT1xD(223 downto 192) xor TT2xD(223 downto 192) xor TT3xD(223 downto 192);
  SBOXxD(1,2) <= TT0xD(191 downto 160) xor TT1xD(191 downto 160) xor TT2xD(191 downto 160) xor TT3xD(191 downto 160);
  SBOXxD(1,3) <= TT0xD(159 downto 128) xor TT1xD(159 downto 128) xor TT2xD(159 downto 128) xor TT3xD(159 downto 128);
  SBOXxD(2,0) <= TT0xD(127 downto  96) xor TT1xD(127 downto  96) xor TT2xD(127 downto  96) xor TT3xD(127 downto  96);
  SBOXxD(2,1) <= TT0xD( 95 downto  64) xor TT1xD( 95 downto  64) xor TT2xD( 95 downto  64) xor TT3xD( 95 downto  64);
  SBOXxD(3,2) <= TT0xD( 63 downto  32) xor TT1xD( 63 downto  32) xor TT2xD( 63 downto  32) xor TT3xD( 63 downto  32);
  SBOXxD(3,3) <= TT0xD( 31 downto   0) xor TT1xD( 31 downto   0) xor TT2xD( 31 downto   0) xor TT3xD( 31 downto   0);
  
  SBOXxD(0, 2) <= InChainValxD(0);
  SBOXxD(0, 3) <= InChainValxD(1);
  SBOXxD(1, 0) <= InChainValxD(2);
  SBOXxD(1, 1) <= InChainValxD(3);
  SBOXxD(2, 2) <= InChainValxD(4);
  SBOXxD(2, 3) <= InChainValxD(5);
  SBOXxD(3, 0) <= InChainValxD(6);
  SBOXxD(3, 1) <= InChainValxD(7);

  -- Permutation
  -----------------------------------------------------------------------------
  p_permutation : process (CntxD, LastIterxS, RcntxD, SBOXxDP)

    variable LASTITER : integer := 0;
    variable IndAlg   : integer;
    
  begin  -- process p_round

    -- Addition of Constant and Counter

      if LastIterxS = '1' then
        LASTITER := 1;
      
      else
        LASTITER := 0;
          
      end if;

      IndAlg := to_integer(CntxD);
      
            
      case IndAlg is
        when 0 => SBOXOutXorCntxD(0, 0) <= SBOXxDP(0, 0) xor ALPHA(LASTITER, 0, 0);
                  SBOXOutXorCntxD(0, 1) <= SBOXxDP(0, 1);
                  SBOXOutXorCntxD(0, 2) <= SBOXxDP(0, 2);
                  SBOXOutXorCntxD(0, 3) <= SBOXxDP(0, 3);
                  SBOXOutXorCntxD(1, 0) <= SBOXxDP(1, 0) xor ALPHA(LASTITER, 1, 0);
                  SBOXOutXorCntxD(1, 1) <= SBOXxDP(1, 1);
                  SBOXOutXorCntxD(1, 2) <= SBOXxDP(1, 2);
                  SBOXOutXorCntxD(1, 3) <= SBOXxDP(1, 3);
                  SBOXOutXorCntxD(2, 0) <= SBOXxDP(2, 0) xor ALPHA(LASTITER, 2, 0);
                  SBOXOutXorCntxD(2, 1) <= SBOXxDP(2, 1);
                  SBOXOutXorCntxD(2, 2) <= SBOXxDP(2, 2);
                  SBOXOutXorCntxD(2, 3) <= SBOXxDP(2, 3);
                  SBOXOutXorCntxD(3, 0) <= SBOXxDP(3, 0) xor ALPHA(LASTITER, 3, 0);
                  SBOXOutXorCntxD(3, 1) <= SBOXxDP(3, 1);
                  SBOXOutXorCntxD(3, 2) <= SBOXxDP(3, 2);
                  SBOXOutXorCntxD(3, 3) <= SBOXxDP(3, 3);
                                                    
        when 1 => SBOXOutXorCntxD(0, 0) <= SBOXxDP(0, 0);
--                  TxD                               SBOXxDP(0, 1) xor ALPHA(LASTITER, 0, 1);
--                  SBOXOutXorCntxD(0, 1)             TxD;
--                  SBOXOutXorCntxD(0, 1)(2 downto 0) TxD(2 downto 0) xor std_logic_vector(RcntxD);
                  SBOXOutXorCntxD(0, 1) <= SBOXxDP(0, 1) xor ALPHA(LASTITER, 0, 1) xor ("00000000000000000000000000000" & std_logic_vector(RcntxD));
                  SBOXOutXorCntxD(0, 2) <= SBOXxDP(0, 2);
                  SBOXOutXorCntxD(0, 3) <= SBOXxDP(0, 3);
                  SBOXOutXorCntxD(1, 0) <= SBOXxDP(1, 0);
                  SBOXOutXorCntxD(1, 1) <= SBOXxDP(1, 1) xor ALPHA(LASTITER, 1, 1);
                  SBOXOutXorCntxD(1, 2) <= SBOXxDP(1, 2);
                  SBOXOutXorCntxD(1, 3) <= SBOXxDP(1, 3);
                  SBOXOutXorCntxD(2, 0) <= SBOXxDP(2, 0);
                  SBOXOutXorCntxD(2, 1) <= SBOXxDP(2, 1) xor ALPHA(LASTITER, 2, 1);
                  SBOXOutXorCntxD(2, 2) <= SBOXxDP(2, 2);
                  SBOXOutXorCntxD(2, 3) <= SBOXxDP(2, 3);
                  SBOXOutXorCntxD(3, 0) <= SBOXxDP(3, 0);
                  SBOXOutXorCntxD(3, 1) <= SBOXxDP(3, 1) xor ALPHA(LASTITER, 3, 1);
                  SBOXOutXorCntxD(3, 2) <= SBOXxDP(3, 2);
                  SBOXOutXorCntxD(3, 3) <= SBOXxDP(3, 3);
                                                    
        when 2 => SBOXOutXorCntxD(0, 0) <= SBOXxDP(0, 0);
                  SBOXOutXorCntxD(0, 1) <= SBOXxDP(0, 1);
                  SBOXOutXorCntxD(0, 2) <= SBOXxDP(0, 2) xor ALPHA(LASTITER, 0, 2);
                  SBOXOutXorCntxD(0, 3) <= SBOXxDP(0, 3);
                  SBOXOutXorCntxD(1, 0) <= SBOXxDP(1, 0);
                  SBOXOutXorCntxD(1, 1) <= SBOXxDP(1, 1);
                  SBOXOutXorCntxD(1, 2) <= SBOXxDP(1, 2) xor ALPHA(LASTITER, 1, 2);
                  SBOXOutXorCntxD(1, 3) <= SBOXxDP(1, 3);
                  SBOXOutXorCntxD(2, 0) <= SBOXxDP(2, 0);
                  SBOXOutXorCntxD(2, 1) <= SBOXxDP(2, 1);
                  SBOXOutXorCntxD(2, 2) <= SBOXxDP(2, 2) xor ALPHA(LASTITER, 2, 2);
                  SBOXOutXorCntxD(2, 3) <= SBOXxDP(2, 3);
                  SBOXOutXorCntxD(3, 0) <= SBOXxDP(3, 0);
                  SBOXOutXorCntxD(3, 1) <= SBOXxDP(3, 1);
                  SBOXOutXorCntxD(3, 2) <= SBOXxDP(3, 2) xor ALPHA(LASTITER, 3, 2);
                  SBOXOutXorCntxD(3, 3) <= SBOXxDP(3, 3);
                                      
        when 3 => SBOXOutXorCntxD(0, 0) <= SBOXxDP(0, 0);
                  SBOXOutXorCntxD(0, 1) <= SBOXxDP(0, 1);
                  SBOXOutXorCntxD(0, 2) <= SBOXxDP(0, 2);
                  SBOXOutXorCntxD(0, 3) <= SBOXxDP(0, 3) xor ALPHA(LASTITER, 0, 3);
                  SBOXOutXorCntxD(1, 0) <= SBOXxDP(1, 0);
                  SBOXOutXorCntxD(1, 1) <= SBOXxDP(1, 1);
                  SBOXOutXorCntxD(1, 2) <= SBOXxDP(1, 2);
                  SBOXOutXorCntxD(1, 3) <= SBOXxDP(1, 3) xor ALPHA(LASTITER, 1, 3);
                  SBOXOutXorCntxD(2, 0) <= SBOXxDP(2, 0);
                  SBOXOutXorCntxD(2, 1) <= SBOXxDP(2, 1);
                  SBOXOutXorCntxD(2, 2) <= SBOXxDP(2, 2);
                  SBOXOutXorCntxD(2, 3) <= SBOXxDP(2, 3) xor ALPHA(LASTITER, 2, 3);
                  SBOXOutXorCntxD(3, 0) <= SBOXxDP(3, 0);
                  SBOXOutXorCntxD(3, 1) <= SBOXxDP(3, 1);
                  SBOXOutXorCntxD(3, 2) <= SBOXxDP(3, 2);
                  SBOXOutXorCntxD(3, 3) <= SBOXxDP(3, 3) xor ALPHA(LASTITER, 3, 3);
                
        when others => SBOXOutXorCntxD <= (others => (others => (others => '0')));
      end case;

  end process p_permutation;
      

   subst : process (CntxD, SBOXOutDiffxD, SBOXOutSubstxD, SBOXxDP)
    variable IndAlg : integer;
  begin
    IndAlg := to_integer(CntxD);
       
    case IndAlg is
      when 0 => SBOXOutxD(0, 0) <= SBOXOutSubstxD(0);
                SBOXOutxD(0, 1) <= SBOXxDP(0, 1);
                SBOXOutxD(0, 2) <= SBOXxDP(0, 2);
                SBOXOutxD(0, 3) <= SBOXxDP(0, 3);
                SBOXOutxD(1, 0) <= SBOXOutSubstxD(1);
                SBOXOutxD(1, 1) <= SBOXxDP(1, 1);
                SBOXOutxD(1, 2) <= SBOXxDP(1, 2);
                SBOXOutxD(1, 3) <= SBOXxDP(1, 3);
                SBOXOutxD(2, 0) <= SBOXOutSubstxD(2);
                SBOXOutxD(2, 1) <= SBOXxDP(2, 1);
                SBOXOutxD(2, 2) <= SBOXxDP(2, 2);
                SBOXOutxD(2, 3) <= SBOXxDP(2, 3);
                SBOXOutxD(3, 0) <= SBOXOutSubstxD(3);
                SBOXOutxD(3, 1) <= SBOXxDP(3, 1);
                SBOXOutxD(3, 2) <= SBOXxDP(3, 2);
                SBOXOutxD(3, 3) <= SBOXxDP(3, 3);
                
      when 1 => SBOXOutxD(0, 0) <= SBOXxDP(0, 0);
                SBOXOutxD(0, 1) <= SBOXOutSubstxD(0);
                SBOXOutxD(0, 2) <= SBOXxDP(0, 2);
                SBOXOutxD(0, 3) <= SBOXxDP(0, 3);
                SBOXOutxD(1, 0) <= SBOXxDP(1, 0);
                SBOXOutxD(1, 1) <= SBOXOutSubstxD(1);
                SBOXOutxD(1, 2) <= SBOXxDP(1, 2);
                SBOXOutxD(1, 3) <= SBOXxDP(1, 3);
                SBOXOutxD(2, 0) <= SBOXxDP(2, 0);
                SBOXOutxD(2, 1) <= SBOXOutSubstxD(2);
                SBOXOutxD(2, 2) <= SBOXxDP(2, 2);
                SBOXOutxD(2, 3) <= SBOXxDP(2, 3);
                SBOXOutxD(3, 0) <= SBOXxDP(3, 0);
                SBOXOutxD(3, 1) <= SBOXOutSubstxD(3);
                SBOXOutxD(3, 2) <= SBOXxDP(3, 2);
                SBOXOutxD(3, 3) <= SBOXxDP(3, 3);
                
      when 2 => SBOXOutxD(0, 0) <= SBOXxDP(0, 0);
                SBOXOutxD(0, 1) <= SBOXxDP(0, 1);
                SBOXOutxD(0, 2) <= SBOXOutSubstxD(0);
                SBOXOutxD(0, 3) <= SBOXxDP(0, 3);
                SBOXOutxD(1, 0) <= SBOXxDP(1, 0);
                SBOXOutxD(1, 1) <= SBOXxDP(1, 1);
                SBOXOutxD(1, 2) <= SBOXOutSubstxD(1);
                SBOXOutxD(1, 3) <= SBOXxDP(1, 3);
                SBOXOutxD(2, 0) <= SBOXxDP(2, 0);
                SBOXOutxD(2, 1) <= SBOXxDP(2, 1);
                SBOXOutxD(2, 2) <= SBOXOutSubstxD(2);
                SBOXOutxD(2, 3) <= SBOXxDP(2, 3);
                SBOXOutxD(3, 0) <= SBOXxDP(3, 0);
                SBOXOutxD(3, 1) <= SBOXxDP(3, 1);
                SBOXOutxD(3, 2) <= SBOXOutSubstxD(3);
                SBOXOutxD(3, 3) <= SBOXxDP(3, 3);
                
      when 3 => SBOXOutxD(0, 0) <= SBOXxDP(0, 0);
                SBOXOutxD(0, 1) <= SBOXxDP(0, 1);
                SBOXOutxD(0, 2) <= SBOXxDP(0, 2);
                SBOXOutxD(0, 3) <= SBOXOutSubstxD(0);
                SBOXOutxD(1, 0) <= SBOXxDP(1, 0);
                SBOXOutxD(1, 1) <= SBOXxDP(1, 1);
                SBOXOutxD(1, 2) <= SBOXxDP(1, 2);
                SBOXOutxD(1, 3) <= SBOXOutSubstxD(1);
                SBOXOutxD(2, 0) <= SBOXxDP(2, 0);
                SBOXOutxD(2, 1) <= SBOXxDP(2, 1);
                SBOXOutxD(2, 2) <= SBOXxDP(2, 2);
                SBOXOutxD(2, 3) <= SBOXOutSubstxD(2);
                SBOXOutxD(3, 0) <= SBOXxDP(3, 0);
                SBOXOutxD(3, 1) <= SBOXxDP(3, 1);
                SBOXOutxD(3, 2) <= SBOXxDP(3, 2);
                SBOXOutxD(3, 3) <= SBOXOutSubstxD(3);
                
      when 4 => SBOXOutxD(0, 0) <= SBOXOutDiffxD(0);
                SBOXOutxD(0, 1) <= SBOXxDP(0, 1);
                SBOXOutxD(0, 2) <= SBOXxDP(0, 2);
                SBOXOutxD(0, 3) <= SBOXxDP(0, 3);
                SBOXOutxD(1, 0) <= SBOXxDP(1, 0);
                SBOXOutxD(1, 1) <= SBOXOutDiffxD(1);
                SBOXOutxD(1, 2) <= SBOXxDP(1, 2);
                SBOXOutxD(1, 3) <= SBOXxDP(1, 3);
                SBOXOutxD(2, 0) <= SBOXxDP(2, 0);
                SBOXOutxD(2, 1) <= SBOXxDP(2, 1);
                SBOXOutxD(2, 2) <= SBOXOutDiffxD(2);
                SBOXOutxD(2, 3) <= SBOXxDP(2, 3);
                SBOXOutxD(3, 0) <= SBOXxDP(3, 0);
                SBOXOutxD(3, 1) <= SBOXxDP(3, 1);
                SBOXOutxD(3, 2) <= SBOXxDP(3, 2);
                SBOXOutxD(3, 3) <= SBOXOutDiffxD(3);
                
      when 5 => SBOXOutxD(0, 0) <= SBOXxDP(0, 0);
                SBOXOutxD(0, 1) <= SBOXOutDiffxD(0);
                SBOXOutxD(0, 2) <= SBOXxDP(0, 2);
                SBOXOutxD(0, 3) <= SBOXxDP(0, 3);
                SBOXOutxD(1, 0) <= SBOXxDP(1, 0);
                SBOXOutxD(1, 1) <= SBOXxDP(1, 1);
                SBOXOutxD(1, 2) <= SBOXOutDiffxD(1);
                SBOXOutxD(1, 3) <= SBOXxDP(1, 3);
                SBOXOutxD(2, 0) <= SBOXxDP(2, 0);
                SBOXOutxD(2, 1) <= SBOXxDP(2, 1);
                SBOXOutxD(2, 2) <= SBOXxDP(2, 2);
                SBOXOutxD(2, 3) <= SBOXOutDiffxD(2);
                SBOXOutxD(3, 0) <= SBOXOutDiffxD(3);
                SBOXOutxD(3, 1) <= SBOXxDP(3, 1);
                SBOXOutxD(3, 2) <= SBOXxDP(3, 2);
                SBOXOutxD(3, 3) <= SBOXxDP(3, 3);
                
      when 6 => SBOXOutxD(0, 0) <= SBOXxDP(0, 0);
                SBOXOutxD(0, 1) <= SBOXxDP(0, 1);
                SBOXOutxD(0, 2) <= SBOXOutDiffxD(0);
                SBOXOutxD(0, 3) <= SBOXxDP(0, 3);
                SBOXOutxD(1, 0) <= SBOXxDP(1, 0);
                SBOXOutxD(1, 1) <= SBOXxDP(1, 1);
                SBOXOutxD(1, 2) <= SBOXxDP(1, 2);
                SBOXOutxD(1, 3) <= SBOXOutDiffxD(1);
                SBOXOutxD(2, 0) <= SBOXOutDiffxD(2);
                SBOXOutxD(2, 1) <= SBOXxDP(2, 1);
                SBOXOutxD(2, 2) <= SBOXxDP(2, 2);
                SBOXOutxD(2, 3) <= SBOXxDP(2, 3);
                SBOXOutxD(3, 0) <= SBOXxDP(3, 0);
                SBOXOutxD(3, 1) <= SBOXOutDiffxD(3);
                SBOXOutxD(3, 2) <= SBOXxDP(3, 2);
                SBOXOutxD(3, 3) <= SBOXxDP(3, 3);
                
      when 7 => SBOXOutxD(0, 0) <= SBOXxDP(0, 0);
                SBOXOutxD(0, 1) <= SBOXxDP(0, 1);
                SBOXOutxD(0, 2) <= SBOXxDP(0, 2);
                SBOXOutxD(0, 3) <= SBOXOutDiffxD(0);
                SBOXOutxD(1, 0) <= SBOXOutDiffxD(1);
                SBOXOutxD(1, 1) <= SBOXxDP(1, 1);
                SBOXOutxD(1, 2) <= SBOXxDP(1, 2);
                SBOXOutxD(1, 3) <= SBOXxDP(1, 3);
                SBOXOutxD(2, 0) <= SBOXxDP(2, 0);
                SBOXOutxD(2, 1) <= SBOXOutDiffxD(2);
                SBOXOutxD(2, 2) <= SBOXxDP(2, 2);
                SBOXOutxD(2, 3) <= SBOXxDP(2, 3);
                SBOXOutxD(3, 0) <= SBOXxDP(3, 0);
                SBOXOutxD(3, 1) <= SBOXxDP(3, 1);
                SBOXOutxD(3, 2) <= SBOXOutDiffxD(3);
                SBOXOutxD(3, 3) <= SBOXxDP(3, 3);          
     when others => SBOXOutxD <= (others => (others => (others => '0')));
    end case;
    
  end process subst;

  -- Diffusion
  -----------------------------------------------------------------------------



   diffin : process (CntxD, SBOXOutXorCntxD, SBOXxDP)
    variable IndAlg : integer;
  begin
    IndAlg := to_integer(CntxD);
    
    case IndAlg is
      when 0 => SBOXInSubstxD(0) <= SBOXOutXorCntxD(0, 0);
                SBOXInSubstxD(1) <= SBOXOutXorCntxD(1, 0);
                SBOXInSubstxD(2) <= SBOXOutXorCntxD(2, 0);
                SBOXInSubstxD(3) <= SBOXOutXorCntxD(3, 0);
                SBOXInDiffxD <= (others => (others => '0'));
      when 1 => SBOXInSubstxD(0) <= SBOXOutXorCntxD(0, 1);
                SBOXInSubstxD(1) <= SBOXOutXorCntxD(1, 1);
                SBOXInSubstxD(2) <= SBOXOutXorCntxD(2, 1);
                SBOXInSubstxD(3) <= SBOXOutXorCntxD(3, 1);
                SBOXInDiffxD <= (others => (others => '0'));
      when 2 => SBOXInSubstxD(0) <= SBOXOutXorCntxD(0, 2);
                SBOXInSubstxD(1) <= SBOXOutXorCntxD(1, 2);
                SBOXInSubstxD(2) <= SBOXOutXorCntxD(2, 2);
                SBOXInSubstxD(3) <= SBOXOutXorCntxD(3, 2);
                SBOXInDiffxD <= (others => (others => '0'));
      when 3 => SBOXInSubstxD(0) <= SBOXOutXorCntxD(0, 3);
                SBOXInSubstxD(1) <= SBOXOutXorCntxD(1, 3);
                SBOXInSubstxD(2) <= SBOXOutXorCntxD(2, 3);
                SBOXInSubstxD(3) <= SBOXOutXorCntxD(3, 3);
                SBOXInDiffxD <= (others => (others => '0'));
      when 4 => SBOXInDiffxD(0) <= SBOXxDP(0, 0);
                SBOXInDiffxD(1) <= SBOXxDP(1, 1);
                SBOXInDiffxD(2) <= SBOXxDP(2, 2);
                SBOXInDiffxD(3) <= SBOXxDP(3, 3);
                SBOXInSubstxD <= (others => (others => '0'));
      when 5 => SBOXInDiffxD(0) <= SBOXxDP(0, 1);
                SBOXInDiffxD(1) <= SBOXxDP(1, 2);
                SBOXInDiffxD(2) <= SBOXxDP(2, 3);
                SBOXInDiffxD(3) <= SBOXxDP(3, 0);
                SBOXInSubstxD <= (others => (others => '0'));
      when 6 => SBOXInDiffxD(0) <= SBOXxDP(0, 2);
                SBOXInDiffxD(1) <= SBOXxDP(1, 3);
                SBOXInDiffxD(2) <= SBOXxDP(2, 0);
                SBOXInDiffxD(3) <= SBOXxDP(3, 1);
                SBOXInSubstxD <= (others => (others => '0'));
      when 7 => SBOXInDiffxD(0) <= SBOXxDP(0, 3);
                SBOXInDiffxD(1) <= SBOXxDP(1, 0);
                SBOXInDiffxD(2) <= SBOXxDP(2, 1);
                SBOXInDiffxD(3) <= SBOXxDP(3, 2);
                SBOXInSubstxD <= (others => (others => '0'));
      when others => SBOXInDiffxD <= (others => (others => '0'));
                     SBOXInSubstxD <= (others => (others => '0'));
    end case;
    
    
  end process diffin;


  -- Truncation
  -------------------------------------------------------------------------------
  p_truncation: process (OldChainValxD, SBOXOutxD, TruncENxE)
    variable CHAINVAL : halfstate;
  begin  -- process p_truncation

    if TruncENxE = '1' then
      for i in 0 to ArrLen-1 loop
        OutChainValxD(i)   <= OldChainValxD(i) xor SBOXOutxD(0, i);
        OutChainValxD(i+4) <= OldChainValxD(i+ArrLen) xor SBOXOutxD(2, i);
      end loop;  -- i
    else
      for i in 0 to 7 loop
        OutChainValxD(i)   <= OldChainValxD(i);
      end loop;  -- i
    end if;
    
  end process p_truncation;

  
  -- Chain value select
  -----------------------------------------------------------------------------
  InChainValxD <= IV256 when ChainValSelxS = '0' else OutChainValxD;


  -- Permutation chain value select
  -----------------------------------------------------------------------------
  SBOXxDN <= SBOXxD when PermInputSelxS = '0' else SBOXOutxD;


  -- Output Unform
  -----------------------------------------------------------------------------
  p_outext: for i in 0 to 7 generate
    DxDO((HWIDTH/8)*(8-i)-1 downto (HWIDTH/8)*(8-i)-32) <= OutChainValxD(i)(31 downto 0);
    
  end generate p_outext;
  

  -- Memory
  -----------------------------------------------------------------------------
  p_mem : process (ClkxCI, RstxRBI)
  begin  -- process p_mem
    if RstxRBI = '0' then               -- asynchronous reset (active low)
      SBOXxDP       <= (others => (others => (others => '0')));
      OldChainValxD <= (others => (others => '0'));
      
    elsif ClkxCI'event and ClkxCI = '1' then  -- rising clock edge
      SBOXxDP       <= SBOXxDN;
      OldChainValxD <= InChainValxD;
      
      
    end if;
  end process p_mem;
  

end rtl;

Generated on Fri Sep 24 10:39:12 CEST 2010
Home