------------------------------------------------------------ -- Copyright: 2011 Integrated Sytems Laboratory, ETH Zurich -- http://www.iis.ee.ethz.ch/~sha3 ------------------------------------------------------------ ------------------------------------------------------------------------------- -- Title : Groestl implementation -- Project : shabziger ------------------------------------------------------------------------------- -- File : ethz_groestl.vhd -- Author : Frank K. Guerkaynak -- Company : Integrated Systems Laboratory, ETH Zurich -- Created : 2011-08-17 -- Last update: 2011-09-05 -- Platform : ModelSim (simulation), Synopsys (synthesis) -- Standard : VHDL'87 ------------------------------------------------------------------------------- -- Description: Original code from sha3 r2 paper ------------------------------------------------------------------------------- -- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2011-08-17 1.0 kgf Created -- 2011-09-02 2.0 kgf Complete re-write -- 2011-09-04 2.1 kgf Corrections ------------------------------------------------------------------------------- library ieee; use ieee.numeric_std.all; use ieee.std_logic_1164.all; entity ethz_groestl is port ( ClkxCI : in std_logic; RstxRBI : in std_logic; ScanInxTI : in std_logic; ScanOutxTO : out std_logic; ScanEnxTI : in std_logic; InWrEnxSI : in std_logic; FinBlockxSI : in std_logic; OutWrEnxSO : out std_logic; PenUltCyclexSO : out std_logic; MsgInxDI : in std_logic_vector(511 downto 0); HashOutxDO : out std_logic_vector(255 downto 0)); end ethz_groestl; architecture rtl of ethz_groestl is component groestl_p port ( ClkxCI : in std_logic; RstxRBI : in std_logic; RndxSI : in std_logic_vector(7 downto 0); SubRndxSI : in integer range 0 to 7; InxDI : in std_logic_vector(511 downto 0); OutxDO : out std_logic_vector(511 downto 0)); end component; component groestl_q port ( ClkxCI : in std_logic; RstxRBI : in std_logic; RndxSI : in std_logic_vector(7 downto 0); SubRndxSI : in integer range 0 to 7; InxDI : in std_logic_vector(511 downto 0); OutxDO : out std_logic_vector(511 downto 0)); end component; -- state type statetype is (init, first, round, lastround, final, lastfinal); signal StatexDN, StatexDP : statetype; signal FinBlockxSN, FinBlockxSP : std_logic; signal UseIVxS : std_logic; -- 1: use IV; 0: use Hout -- counters signal RndxSN, RndxSP : unsigned(3 downto 0); -- 8 bit representation of the Groestl round 1..11 signal RndxS : std_logic_vector(7 downto 0); signal SubRndxS : integer range 0 to 7; -- each block is completed in 8 cycles; signal CntxDN, CntxDP : unsigned(7 downto 0); -- The counter signal IntCntxS : integer range 0 to 255; -- Integer version -- interconnect signal HxDN, HxDP : std_logic_vector(511 downto 0); signal HinxD, HoutxD : std_logic_vector(511 downto 0); signal PxD, QxD : std_logic_vector(511 downto 0); signal PinxD, PHxD, PQHxD : std_logic_vector(511 downto 0); constant IV : std_logic_vector(511 downto 0) := (8 => '1', others => '0'); -- saving power signal BlockOutEnxS : std_logic; -- 1:when the output is needed begin ------------------------------------------------------------------------------- -- State Machine ------------------------------------------------------------------------------- p_fsm : process (StatexDP, InWrEnxSI, FinBlockxSI, CntxDP, IntCntxS, FinBlockxSP) begin -- process p_fsm -- defaults StatexDN <= StatexDP; OutWrEnxSO <= '0'; PenUltCyclexSO <= '0'; CntxDN <= CntxDP + 1; -- count by default FinBlockxSN <= FinBlockxSP; UseIVxS <= '0'; BlockOutEnxS <= '0'; case StatexDP is when init => -- Use IV CntxDN <= (others => '0'); UseIVxS <= '1'; -- Set the IV if InWrEnxSI = '1' then StatexDN <= round; FinBlockxSN <= FinBlockxSI; -- sample the FinBlockxSI end if; -------------------------------------------------------------------------- when first => -- chain use old value, no IV is set CntxDN <= (others => '0'); if InWrEnxSI = '1' then -- wait till we have something StatexDN <= round; -- go to round FinBlockxSN <= FinBlockxSI; -- sample FinBlockxSI end if; -------------------------------------------------------------------------- when round => if IntCntxS = 79 then if FinBlockxSP = '1' then -- are we finished ? StatexDN <= final; -- go to final else StatexDN <= lastround; -- separate state PenUltCyclexSO <= '1'; -- this is the PenUlt end if; end if; -------------------------------------------------------------------------- when lastround => CntxDN <= (others => '0'); -- reset the counter StatexDN <= first; -- wait for the new input BlockOutEnxS <= '1'; if InWrEnxSI = '1' then -- if the new input is here StatexDN <= round; -- jump directly to round FinBlockxSN <= FinBlockxSI; -- sample FinBlockxSI end if; -------------------------------------------------------------------------- when final => if IntCntxS = 159 then -- penult cycle PenUltCyclexSO <= '1'; StatexDN <= lastfinal; -- go to the last final (160) end if; -------------------------------------------------------------------------- when lastfinal => OutWrEnxSO <= '1'; -- set the output StatexDN <= init; -- wait for new input CntxDN <= (others => '0'); -- reset the counter BlockOutEnxS <= '1'; if InWrEnxSI = '1' then -- if new input is here UseIVxS <= '1'; -- Take IV StatexDN <= round; -- continue directly FinBlockxSN <= FinBlockxSI; -- sample the FinBlockxSI end if; -------------------------------------------------------------------------- when others => null; end case; end process p_fsm; ------------------------------------------------------------------------------- -- Derive the counters ------------------------------------------------------------------------------- SubRndxS <= to_integer(CntxDP(2 downto 0)); RndxS <= "0000" & std_logic_vector(RndxSP); IntCntxS <= to_integer(unsigned(CntxDP)); -- The round counter needs to be determined depending on -- whether or not we are in the final round p_cnt: process (RndxSP, IntCntxS) begin -- process p_cnt RndxSN <= RndxSP; if (IntCntxS = 79) then RndxSN <= (others => '0'); elsif (IntCntxS = 159) then RndxSN <= (others => '0'); elsif (IntCntxS mod 8 = 7) then RndxSN <= RndxSP + 1; end if; end process p_cnt; ------------------------------------------------------------------------------- -- Interconnections ------------------------------------------------------------------------------- HinxD <= IV when UseIVxS = '1' else HoutxD; -- add IV in the first round PinxD <= HxDN when StatexDP = final else MsgInxDI xor HxDN; -- input of P p_storeH : process (HxDP, StatexDP, HinxD, IntCntxS) begin -- process p_storeH HxDN <= HxDP; -- keep H value constant if IntCntxS = 80 then HxDN <= HinxD; -- end of the block elsif IntCntxS = 160 then -- technically also at 159.. HxDN <= HinxD; -- end of final elsif StatexDP = init then -- change at Init (IV) HxDN <= HinxD; -- Sample the output end if; end process p_storeH; PHxD <= PxD xor HxDP; -- XOR the output with H PQHxD <= PHxD xor QxD; -- XOR P H and Q HoutxD <= PQHxD when IntCntxS = 80 else PHxD; -- on round 80 we will sample -- P xor Q xor H HashOutxDO <= HoutxD(255 downto 0); -- take the LSB ------------------------------------------------------------------------------- -- Instantiate P and Q ------------------------------------------------------------------------------- i_p : groestl_p port map ( ClkxCI => ClkxCI, RstxRBI => RstxRBI, RndxSI => RndxS, SubRndxSI => SubRndxS, InxDI => PinxD, OutxDO => PxD); i_q : groestl_q port map ( ClkxCI => ClkxCI, RstxRBI => RstxRBI, RndxSI => RndxS, SubRndxSI => SubRndxS, InxDI => MsgInxDI, OutxDO => QxD); ----------------------------------------------------------------------------- -- Memory ----------------------------------------------------------------------------- p_mem : process (ClkxCI, RstxRBI) begin -- process p_mem if RstxRBI = '0' then -- asynchronous reset (active low) StatexDP <= init; CntxDP <= (others => '0'); HxDP <= (others => '0'); FinBlockxSP <= '0'; RndxSP <= (others => '0'); elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge StatexDP <= StatexDN; CntxDP <= CntxDN; HxDP <= HxDN; FinBlockxSP <= FinBlockxSN; RndxSP <= RndxSN; end if; end process p_mem; end rtl;