------------------------------------------------------------
-- 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;