------------------------------------------------------------
-- 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.fuguepkg.all;

entity fugue is

  port (
    ClkxCI      : in  std_logic;
    RstxRBI     : in  std_logic;
    InputEnxEI  : in  std_logic;
    OutputEnxEO : out std_logic;
    DxDI        : in  std_logic_vector(31 downto 0);
    HashxDO     : out std_logic_vector(255 downto 0));

end fugue;

architecture rtl of fugue is

  component subbytes is
    port (
      ClkxCI  : in  std_logic;
      RstxRBI : in  std_logic;
      DxDI    : in  std_logic_vector(7 downto 0);
      DxDO    : out std_logic_vector(7 downto 0));
  end component;

  -- FSM state (0...5)
  signal StatexDP, StatexDN                                 : unsigned(2 downto 0);
  signal StateMatxDP, StateMatxDN                           : statematrix;
  signal CXOR_1_27xD, CXOR_2_28xD, CXOR_3_29xD, CXOR_8_DxD  : std_logic_vector(31 downto 0);
  signal CXOR_0_10xD, CXOR_1_12xD, CXOR_2_13xD, CXOR_3_14xD : std_logic_vector(31 downto 0);
  signal CXOR_0_4xD, CXOR_1_24xD, CXOR_0_15xD               : std_logic_vector(31 downto 0);
  signal CXOR_0_16xD, CXOR_1_24_27xD, CXOR_1_12_24xD        : std_logic_vector(31 downto 0);
  signal CcountxDP, CcountxDN                               : unsigned(3 downto 0);
  signal DcountxDP, DcountxDN                               : unsigned(3 downto 0);
  signal SMixInxD                                           : smixstatemat;  -- Signal after the mux, before SMIX is applied
  signal SMixedxD                                           : smixstate;
  signal Shift2xD                                           : smixstate;
  signal Shift1xD                                           : smixstate;
  signal Mult7xD                                            : smixstate;
  signal SBoxedxD                                           : smixstate;


begin  -- rtl
  

  -- Column XORs (including a XOR with the input data)
  -- Used by the FSM
  CXOR_1_27xD    <= StateMatxDP(1) xor StateMatxDP(27);
  CXOR_1_12_24xD <= StateMatxDP(1) xor StateMatxDP(12) xor StateMatxDP(24);
  CXOR_1_24_27xD <= StateMatxDP(1) xor StateMatxDP(24) xor StateMatxDP(27);
  CXOR_2_28xD    <= StateMatxDP(2) xor StateMatxDP(28);
  CXOR_3_29xD    <= StateMatxDP(3) xor StateMatxDP(29);
  CXOR_8_DxD     <= StateMatxDP(8) xor DxDI;
  CXOR_0_10xD    <= StateMatxDP(0) xor StateMatxDP(10);
  CXOR_1_12xD    <= StateMatxDP(1) xor StateMatxDP(12);
  CXOR_2_13xD    <= StateMatxDP(2) xor StateMatxDP(13);
  CXOR_3_14xD    <= StateMatxDP(3) xor StateMatxDP(14);
  CXOR_0_4xD     <= StateMatxDP(0) xor StateMatxDP(4);
  CXOR_1_24xD    <= StateMatxDP(1) xor StateMatxDP(24);
  CXOR_0_15xD    <= StateMatxDP(0) xor StateMatxDP(15);
  CXOR_0_16xD    <= StateMatxDP(0) xor StateMatxDP(16);


  -- purpose: Calculates bit-shifted signals needed for SMIX
  -- type   : combinational
  -- inputs : SBoxedxD, Shift1xD, Shift2xD
  -- outputs: Shift1xD, Shift2xD
  p_bitshift : process (SBoxedxD, Shift1xD)
  begin  -- process p_bitshift
    for i in 0 to 15 loop
      if SBoxedxD(i)(7) = '1' then
        Shift1xD(i) <= (SBoxedxD(i)(6 downto 0) & '0') xor X"1b";
      else
        Shift1xD(i) <= SBoxedxD(i)(6 downto 0) & '0';
      end if;

      if Shift1xD(i)(7) = '1' then
        Shift2xD(i) <= (Shift1xD(i)(6 downto 0) & '0') xor X"1b";
      else
        Shift2xD(i) <= Shift1xD(i)(6 downto 0) & '0';
      end if;
    end loop;
  end process p_bitshift;
  
  -- Multiply SBoxedxD by seven, using the signals generated above
  -- Result is used for SMIX calculation below
  multseven : for i in 0 to 15 generate
    Mult7xD(i) <= SBoxedxD(i) xor Shift1xD(i) xor Shift2xD(i);
  end generate;

  -- Apply the SMIX (multiplication by matrix N) to SBoxedxD
  -- The result is used by the FSM
  -- 1 4 7 1 1 0 0 0 1 0 0 0 1 0 0 0
  SMixedxD(0)  <= SBoxedxD(0) xor Shift2xD(1) xor Mult7xD(2) xor SBoxedxD(3) xor SBoxedxD(4) xor SBoxedxD(8) xor SBoxedxD(12);
  -- 0 1 0 0 1 1 4 7 0 1 0 0 0 1 0 0
  SMixedxD(1)  <= SBoxedxD(1) xor SBoxedxD(4) xor SBoxedxD(5) xor Shift2xD(6) xor Mult7xD(7) xor SBoxedxD(9) xor SBoxedxD(13);
  -- 0 0 1 0 0 0 1 0 7 1 1 4 0 0 1 0
  SMixedxD(2)  <= SBoxedxD(2) xor SBoxedxD(6) xor Mult7xD(8) xor SBoxedxD(9) xor SBoxedxD(10) xor Shift2xD(11) xor SBoxedxD(14);
  -- 0 0 0 1 0 0 0 1 0 0 0 1 4 7 1 1
  SMixedxD(3)  <= SBoxedxD(3) xor SBoxedxD(7) xor SBoxedxD(11) xor Shift2xD(12) xor Mult7xD(13) xor SBoxedxD(14) xor SBoxedxD(15);
  -- 0 0 0 0 0 4 7 1 1 0 0 0 1 0 0 0
  SMixedxD(4)  <= Shift2xD(5) xor Mult7xD(6) xor SBoxedxD(7) xor SBoxedxD(8) xor SBoxedxD(12);
  -- 0 1 0 0 0 0 0 0 1 0 4 7 0 1 0 0
  SMixedxD(5)  <= SBoxedxD(1) xor SBoxedxD(8) xor Shift2xD(10) xor Mult7xD(11) xor SBoxedxD(13);
  -- 0 0 1 0 0 0 1 0 0 0 0 0 7 1 0 4
  SMixedxD(6)  <= SBoxedxD(2) xor SBoxedxD(6) xor Mult7xD(12) xor SBoxedxD(13) xor Shift2xD(15);
  -- 4 7 1 0 0 0 0 1 0 0 0 1 0 0 0 0
  SMixedxD(7)  <= Shift2xD(0) xor Mult7xD(1) xor SBoxedxD(2) xor SBoxedxD(7) xor SBoxedxD(11);
  -- 0 0 0 0 7 0 0 0 6 4 7 1 7 0 0 0
  SMixedxD(8)  <= Mult7xD(4) xor Shift2xD(8) xor Shift1xD(8) xor Shift2xD(9) xor Mult7xD(10) xor SBoxedxD(11) xor Mult7xD(12);
  -- 0 7 0 0 0 0 0 0 0 7 0 0 1 6 4 7
  SMixedxD(9)  <= Mult7xD(1) xor Mult7xD(9) xor SBoxedxD(12) xor Shift2xD(13) xor Shift1xD(13) xor Shift2xD(14) xor Mult7xD(15);
  -- 7 1 6 4 0 0 7 0 0 0 0 0 0 0 7 0
  SMixedxD(10) <= Mult7xD(0) xor SBoxedxD(1) xor Shift2xD(2) xor Shift1xD(2) xor Shift2xD(3) xor Mult7xD(6) xor Mult7xD(14);
  -- 0 0 0 7 4 7 1 6 0 0 0 7 0 0 0 0
  SMixedxD(11) <= Mult7xD(3) xor Shift2xD(4) xor Mult7xD(5) xor SBoxedxD(6) xor Shift2xD(7) xor Shift1xD(7) xor Mult7xD(11);
  -- 0 0 0 0 4 0 0 0 4 0 0 0 5 4 7 1
  SMixedxD(12) <= Shift2xD(4) xor Shift2xD(8) xor Shift2xD(12) xor SBoxedxD(12) xor Shift2xD(13) xor Mult7xD(14) xor SBoxedxD(15);
  -- 1 5 4 7 0 0 0 0 0 4 0 0 0 4 0 0
  SMixedxD(13) <= SBoxedxD(0) xor Shift2xD(1) xor SBoxedxD(1) xor Shift2xD(2) xor Mult7xD(3) xor Shift2xD(9) xor Shift2xD(13);
  -- 0 0 4 0 7 1 5 4 0 0 0 0 0 0 4 0
  SMixedxD(14) <= Shift2xD(2) xor Mult7xD(4) xor SBoxedxD(5) xor Shift2xD(6) xor SBoxedxD(6) xor Shift2xD(7) xor Shift2xD(14);
  -- 0 0 0 4 0 0 0 4 4 7 1 5 0 0 0 0
  SMixedxD(15) <= Shift2xD(3) xor Shift2xD(7) xor Shift2xD(8) xor Mult7xD(9) xor SBoxedxD(10) xor Shift2xD(11) xor SBoxedxD(11);


  sboxi : for i in 3 downto 0 generate  -- SBox components added by Patrice
    sboxj : for j in 3 downto 0 generate
      sbox : subbytes
        port map (
          ClkxCI  => ClkxCI,
          RstxRBI => RstxRBI,
          DxDI    => SMixInxD(i)(8*j+7 downto 8*j),
          DxDO    => SBoxedxD(i*4+3-j));
    end generate sboxj;
  end generate sboxi;


  
  -- purpose: Controls the data flow
  -- type   : combinational
  -- inputs : StatexDP, StateMatxDP, CcountxDP, DcountxDP, InputEnxEI, SMixedxD, DxDI and all the CXOR signals
  -- outputs: StatexDN, StateMatxDN, CcountxDN, DcountxDN, OutputEnxEO, SMixInxD
  p_fsm : process (StatexDP, StateMatxDP, CcountxDP, DcountxDP, InputEnxEI, SMixedxD, DxDI, CXOR_1_12_24xD, CXOR_1_24_27xD, CXOR_1_27xD, CXOR_2_28xD, CXOR_3_29xD, CXOR_8_DxD, CXOR_0_10xD, CXOR_1_12xD, CXOR_2_13xD, CXOR_3_14xD, CXOR_0_4xD, CXOR_1_24xD, CXOR_0_15xD, CXOR_0_16xD)

  begin  -- process p_fsm

  
    StatexDN    <= StatexDP;
    StateMatxDN <= StateMatxDP;
    CcountxDN   <= CcountxDP;
    DcountxDN   <= DcountxDP;
    SMixInxD    <= (others => (others => '0'));
    OutputEnxEO <= '0';

    case to_integer(StatexDP) is

       when 0 | 1 | 2 =>

        -- (0) see below
        SMixInxD(1)     <= CXOR_2_28xD;
        SMixInxD(2)     <= CXOR_3_29xD;
        -- (3) see below
        -- (4) see below
        StateMatxDN(5)  <= StateMatxDP(2);
        StateMatxDN(6)  <= StateMatxDP(3);
        StateMatxDN(7)  <= StateMatxDP(4);
        StateMatxDN(8)  <= StateMatxDP(5);
        StateMatxDN(9)  <= StateMatxDP(6);
        StateMatxDN(10) <= StateMatxDP(7);
        -- (11) see below
        StateMatxDN(12) <= StateMatxDP(9);
        -- (13) see below
        StateMatxDN(14) <= StateMatxDP(11);
        -- (15) see below
        StateMatxDN(16) <= CXOR_2_13xD;
        StateMatxDN(17) <= CXOR_3_14xD;
        StateMatxDN(18) <= StateMatxDP(15);
        StateMatxDN(19) <= StateMatxDP(16);
        StateMatxDN(20) <= StateMatxDP(17);
        StateMatxDN(21) <= StateMatxDP(18);
        StateMatxDN(22) <= StateMatxDP(19);
        StateMatxDN(23) <= StateMatxDP(20);
        StateMatxDN(24) <= StateMatxDP(21);
        StateMatxDN(25) <= StateMatxDP(22);
        StateMatxDN(26) <= StateMatxDP(23);
        StateMatxDN(27) <= StateMatxDP(24);
        StateMatxDN(28) <= StateMatxDP(25);
        StateMatxDN(29) <= StateMatxDP(26);
        DcountxDN       <= (others => '0');


        -- TODO: write the following code more nicely

        -- state 0: only continue to state 1 if InputEn is 1
        if to_integer(StatexDP) = 0 then
          if InputEnxEI = '0' then
            StateMatxDN <= INITSTATE;
          else
            SMixInxD(0)     <= CXOR_1_24_27xD;
            SMixInxD(3)     <= DxDI;
            StateMatxDN(4)  <= CXOR_1_24xD;
            StateMatxDN(11) <= CXOR_8_DxD;
            StateMatxDN(13) <= StateMatxDP(10);
            StateMatxDN(15) <= CXOR_1_12_24xD;
            StatexDN        <= StatexDP+1;
          end if;
        elsif to_integer(StatexDP) = 1 then
          --state 1: apply ROR3/CMIX/SMIX, continue to state 2
          CcountxDN       <= (others => '0');
          SMixInxD(0)     <= CXOR_1_27xD;
          StateMatxDN(4)  <= StateMatxDP(1);
          SMixInxD(3)     <= StateMatxDP(0);
          StateMatxDN(11) <= StateMatxDP(8);
          StateMatxDN(13) <= StateMatxDP(10);
          StateMatxDN(15) <= CXOR_1_12xD;
          StatexDN        <= StatexDP+1;
        else
          -- state 2: start counting final rounds when input ends
          if InputEnxEI = '0' then
            SMixInxD(0)     <= CXOR_1_27xD;
            SMixInxD(3)     <= StateMatxDP(0);
            StateMatxDN(4)  <= StateMatxDP(1);
            StateMatxDN(11) <= StateMatxDP(8);
            StateMatxDN(13) <= StateMatxDP(10);
            StateMatxDN(15) <= CXOR_1_12xD;
            CcountxDN       <= CcountxDP+1;
            if CcountxDP = 9 then
              StatexDN <= StatexDP+1;
            end if;
          else
            SMixInxD(0)     <= CXOR_1_24_27xD;
            SMixInxD(3)     <= DxDI;
            StateMatxDN(4)  <= CXOR_1_24xD;
            StateMatxDN(11) <= CXOR_8_DxD;
            StateMatxDN(13) <= CXOR_0_10xD;
            StateMatxDN(15) <= CXOR_1_12_24xD;
            StatexDN        <= "001";
          end if;
        end if;


      when 3 =>
        SMixInxD(0)     <= CXOR_0_15xD;
        SMixInxD(1)     <= StateMatxDP(16);
        SMixInxD(2)     <= StateMatxDP(17);
        SMixInxD(3)     <= StateMatxDP(18);
        StateMatxDN(4)  <= StateMatxDP(19);
        StateMatxDN(5)  <= StateMatxDP(20);
        StateMatxDN(6)  <= StateMatxDP(21);
        StateMatxDN(7)  <= StateMatxDP(22);
        StateMatxDN(8)  <= StateMatxDP(23);
        StateMatxDN(9)  <= StateMatxDP(24);
        StateMatxDN(10) <= StateMatxDP(25);
        StateMatxDN(11) <= StateMatxDP(26);
        StateMatxDN(12) <= StateMatxDP(27);
        StateMatxDN(13) <= StateMatxDP(28);
        StateMatxDN(14) <= StateMatxDP(29);
        StateMatxDN(15) <= StateMatxDP(0);
        StateMatxDN(16) <= StateMatxDP(1);
        StateMatxDN(17) <= StateMatxDP(2);
        StateMatxDN(18) <= StateMatxDP(3);
        StateMatxDN(19) <= CXOR_0_4xD;
        StateMatxDN(20) <= StateMatxDP(5);
        StateMatxDN(21) <= StateMatxDP(6);
        StateMatxDN(22) <= StateMatxDP(7);
        StateMatxDN(23) <= StateMatxDP(8);
        StateMatxDN(24) <= StateMatxDP(9);
        StateMatxDN(25) <= StateMatxDP(10);
        StateMatxDN(26) <= StateMatxDP(11);
        StateMatxDN(27) <= StateMatxDP(12);
        StateMatxDN(28) <= StateMatxDP(13);
        StateMatxDN(29) <= StateMatxDP(14);
        StatexDN        <= StatexDP+1;



      when 4 =>
        SMixInxD(0)     <= CXOR_0_16xD;
        SMixInxD(1)     <= StateMatxDP(17);
        SMixInxD(2)     <= StateMatxDP(18);
        SMixInxD(3)     <= StateMatxDP(19);
        StateMatxDN(4)  <= StateMatxDP(20);
        StateMatxDN(5)  <= StateMatxDP(21);
        StateMatxDN(6)  <= StateMatxDP(22);
        StateMatxDN(7)  <= StateMatxDP(23);
        StateMatxDN(8)  <= StateMatxDP(24);
        StateMatxDN(9)  <= StateMatxDP(25);
        StateMatxDN(10) <= StateMatxDP(26);
        StateMatxDN(11) <= StateMatxDP(27);
        StateMatxDN(12) <= StateMatxDP(28);
        StateMatxDN(13) <= StateMatxDP(29);
        StateMatxDN(14) <= StateMatxDP(0);
        StateMatxDN(15) <= StateMatxDP(1);
        StateMatxDN(16) <= StateMatxDP(2);
        StateMatxDN(17) <= StateMatxDP(3);
        StateMatxDN(18) <= CXOR_0_4xD;
        StateMatxDN(19) <= StateMatxDP(5);
        StateMatxDN(20) <= StateMatxDP(6);
        StateMatxDN(21) <= StateMatxDP(7);
        StateMatxDN(22) <= StateMatxDP(8);
        StateMatxDN(23) <= StateMatxDP(9);
        StateMatxDN(24) <= StateMatxDP(10);
        StateMatxDN(25) <= StateMatxDP(11);
        StateMatxDN(26) <= StateMatxDP(12);
        StateMatxDN(27) <= StateMatxDP(13);
        StateMatxDN(28) <= StateMatxDP(14);
        StateMatxDN(29) <= StateMatxDP(15);

        DcountxDN <= DcountxDP+1;
        if DcountxDP = 12 then
          StatexDN <= StatexDP+1;
        else
          StatexDN <= "011";            --3
        end if;


      when 5 =>
        StateMatxDN <= INITSTATE;
        StatexDN    <= (others => '0');
        OutputEnxEO <= '1';

      when others => null;

    end case;

    --apply SMIX if the matrix is not going to be initialized
    --(the following could be written as "if StatexDN /= "000" then" but we
    --don't want this process to be sensitive on StatexDN)
    if not((StatexDP = "000" and InputEnxEI = '0') or StatexDP = "101") then
      for i in 0 to 3 loop
        for j in 0 to 3 loop
          StateMatxDN(i)(j*8+7 downto j*8) <= std_logic_vector(SMixedxD(4*i+3-j)(7 downto 0));
        end loop;  -- j
      end loop;  -- i
    end if;
    
  end process p_fsm;


  -- Generate the hash from the current state
  output : for i in 31 downto 0 generate
    HashxDO(i+224) <= StateMatxDP(1)(i);
    HashxDO(i+192) <= StateMatxDP(2)(i);
    HashxDO(i+160) <= StateMatxDP(3)(i);
    HashxDO(i+128) <= CXOR_0_4xD(i);
    HashxDO(i+96)  <= CXOR_0_15xD(i);
    HashxDO(i+64)  <= StateMatxDP(16)(i);
    HashxDO(i+32)  <= StateMatxDP(17)(i);
    HashxDO(i)     <= StateMatxDP(18)(i);
  end generate output;

  -- Memory
  -----------------------------------------------------------------------------
  p_mem : process (ClkxCI, RstxRBI)
  begin  -- process p_mem
    if RstxRBI = '0' then               -- asynchronous reset (active low)
      StatexDP    <= (others => '0');
      StateMatxDP <= (others => (others => '0'));
      CcountxDP   <= (others => '0');
      DcountxDP   <= (others => '0');
      
    elsif ClkxCI'event and ClkxCI = '1' then  -- rising clock edge
      StatexDP    <= StatexDN;
      StateMatxDP <= StateMatxDN;
      CcountxDP   <= CcountxDN;
      DcountxDP   <= DcountxDN;
    end if;
  end process p_mem;
  

end rtl;

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