------------------------------------------------------------ -- Copyright: 2011 Integrated Sytems Laboratory, ETH Zurich -- http://www.iis.ee.ethz.ch/~sha3 ------------------------------------------------------------ ------------------------------------------------------------------------------- -- Title : The Q round of Groestl -- Project : ------------------------------------------------------------------------------- -- File : groestl_q.vhd -- Author : Frank K. Guerkaynak -- Company : Integrated Systems Laboratory, ETH Zurich -- Created : 2011-08-21 -- Last update: 2011-09-05 -- Platform : ModelSim (simulation), Synopsys (synthesis) -- Standard : VHDL'87 ------------------------------------------------------------------------------- -- Description: 1/8 of the round ------------------------------------------------------------------------------- -- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2011-08-21 1.0 kgf Created -- 2011-09-04 1.1 kgf Major corrections -- 2011-09-05 1.2 kgf Moved the register between Addroundcons and -- SubBytes ------------------------------------------------------------------------------- library ieee; use ieee.numeric_std.all; use ieee.std_logic_1164.all; entity groestl_q is 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 groestl_q; architecture rtl of groestl_q is component g_mixbytes port ( InxDI : in std_logic_vector(63 downto 0); OutxDO : out std_logic_vector(7 downto 0)); end component; component groestl_subbytes port ( DxDI : in std_logic_vector(7 downto 0); DxDO : out std_logic_vector(7 downto 0)); end component; type statematrix is array (0 to 7, 0 to 7) of std_logic_vector (7 downto 0); type statearray is array (0 to 7) of std_logic_vector (7 downto 0); type incconsttype is array (0 to 7) of integer range 0 to 7; type minputtype is array (0 to 7) of std_logic_vector(63 downto 0); -- KGF states signal QxDP, QxDN, Q1xD : statematrix; signal RQxD : std_logic_vector(63 downto 0); -- selected column signal SQxD : std_logic_vector(63 downto 0); -- after Subbytes signal MQxD : statearray; -- after MixBytes signal M1xD : minputtype; signal QStartxD, QFinxD : std_logic_vector(511 downto 0); constant INCQ : incconsttype := (1,3,5,7,0,2,4,6); -- shift amounts for Q begin -- rtl ------------------------------------------------------------------------------- -- New start either a fresh vector or a state round ------------------------------------------------------------------------------- QStartxD <= InxDI when RndxSI = "00000000" else QFinxD; p_new : process (QStartxD, SubRndxSI, RndxSI, Q1xD) variable varq : statematrix; begin -- process p_new varq := Q1xD; if SubRndxSI = 0 then -- Add round constant varq(0,7) := QStartxD(455 downto 448) xor x"ff" xor RndxSI; varq(1,7) := QStartxD(391 downto 384) xor x"ef" xor RndxSI; varq(2,7) := QStartxD(327 downto 320) xor x"df" xor RndxSI; varq(3,7) := QStartxD(263 downto 256) xor x"cf" xor RndxSI; varq(4,7) := QStartxD(199 downto 192) xor x"bf" xor RndxSI; varq(5,7) := QStartxD(135 downto 128) xor x"af" xor RndxSI; varq(6,7) := QStartxD( 71 downto 64) xor x"9f" xor RndxSI; varq(7,7) := QStartxD( 7 downto 0) xor x"8f" xor RndxSI; for y in 0 to 6 loop for x in 0 to 7 loop varq(x,y) := QStartxD((((7-x) * 64) + ((7-y) *8) + 7) downto ((7-x) * 64) + ((7-y) *8)) xor x"ff"; end loop; -- x end loop; -- y end if; QxDN <= varq; end process p_new; ------------------------------------------------------------------------------- -- Register is here now QxDP QxDN ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -- Select a vector to operate on. The shift is implicit in here ------------------------------------------------------------------------------- p_selq: process (QxDP, SubRndxSI) begin -- process p_selp -- we have to change the numbering here, since it is after the register 0 -- became 1 etc. case SubRndxSI is when 1 => RQxD <= QxDP(1,0) & QxDP(3,1) & QxDP(5,2) & QxDP(7,3) & QxDP(0,4) & QxDP(2,5) & QxDP(4,6) & QxDP(6,7); when 2 => RQxD <= QxDP(2,0) & QxDP(4,1) & QxDP(6,2) & QxDP(0,3) & QxDP(1,4) & QxDP(3,5) & QxDP(5,6) & QxDP(7,7); when 3 => RQxD <= QxDP(3,0) & QxDP(5,1) & QxDP(7,2) & QxDP(1,3) & QxDP(2,4) & QxDP(4,5) & QxDP(6,6) & QxDP(0,7); when 4 => RQxD <= QxDP(4,0) & QxDP(6,1) & QxDP(0,2) & QxDP(2,3) & QxDP(3,4) & QxDP(5,5) & QxDP(7,6) & QxDP(1,7); when 5 => RQxD <= QxDP(5,0) & QxDP(7,1) & QxDP(1,2) & QxDP(3,3) & QxDP(4,4) & QxDP(6,5) & QxDP(0,6) & QxDP(2,7); when 6 => RQxD <= QxDP(6,0) & QxDP(0,1) & QxDP(2,2) & QxDP(4,3) & QxDP(5,4) & QxDP(7,5) & QxDP(1,6) & QxDP(3,7); when 7 => RQxD <= QxDP(7,0) & QxDP(1,1) & QxDP(3,2) & QxDP(5,3) & QxDP(6,4) & QxDP(0,5) & QxDP(2,6) & QxDP(4,7); when others => RQxD <= QxDP(0,0) & QxDP(2,1) & QxDP(4,2) & QxDP(6,3) & QxDP(7,4) & QxDP(1,5) & QxDP(3,6) & QxDP(5,7); end case; end process p_selq; ------------------------------------------------------------------------------- -- 8 x Sub bytes on this vector ------------------------------------------------------------------------------- gen_q_sub: for i in 0 to 7 generate i_subbytes: groestl_subbytes port map (DxDI => RQxD( (i*8) +7 downto i*8), DxDO => SQxD( (i*8) +7 downto i*8)); end generate gen_q_sub; ------------------------------------------------------------------------------- -- We have a fixed MixBytes function. Normally the function is shifted, we will -- shift the input data instead ------------------------------------------------------------------------------- -- M1xD(0) SQxD; -- M1xD(1) SQxD( 7 downto 0) & SQxD(63 downto 8); -- M1xD(2) SQxD(15 downto 0) & SQxD(63 downto 16); -- M1xD(3) SQxD(23 downto 0) & SQxD(63 downto 24); -- M1xD(4) SQxD(31 downto 0) & SQxD(63 downto 32); -- M1xD(5) SQxD(39 downto 0) & SQxD(63 downto 40); -- M1xD(6) SQxD(47 downto 0) & SQxD(63 downto 48); -- M1xD(7) SQxD(55 downto 0) & SQxD(63 downto 56); M1xD(0) <= SQxD; M1xD(1) <= SQxD(55 downto 0) & SQxD(63 downto 56); M1xD(2) <= SQxD(47 downto 0) & SQxD(63 downto 48); M1xD(3) <= SQxD(39 downto 0) & SQxD(63 downto 40); M1xD(4) <= SQxD(31 downto 0) & SQxD(63 downto 32); M1xD(5) <= SQxD(23 downto 0) & SQxD(63 downto 24); M1xD(6) <= SQxD(15 downto 0) & SQxD(63 downto 16); M1xD(7) <= SQxD( 7 downto 0) & SQxD(63 downto 8); gen_q_mix: for i in 0 to 7 generate i_mixbytes: g_mixbytes port map ( InxDI => M1xD(i), OutxDO => MQxD(i)); end generate gen_q_mix; ------------------------------------------------------------------------------- -- Write back Q ------------------------------------------------------------------------------- p_shiftq: process (QxDP, SubRndxSI, MQxD) variable varq : statematrix; begin -- process p_selp -- default varq := QxDP; -- do not shift for the first 7 cycles; -- changed the numbering here. This is after the register, SubRndxSI is 1 -- ahead here case SubRndxSI is when 1 => varq(1,0) := MQxD(0); varq(3,1) := MQxD(1); varq(5,2) := MQxD(2); varq(7,3) := MQxD(3); varq(0,4) := MQxD(4); varq(2,5) := MQxD(5); varq(4,6) := MQxD(6); varq(6,7) := MQxD(7); when 2 => varq(2,0) := MQxD(0); varq(4,1) := MQxD(1); varq(6,2) := MQxD(2); varq(0,3) := MQxD(3); varq(1,4) := MQxD(4); varq(3,5) := MQxD(5); varq(5,6) := MQxD(6); varq(7,7) := MQxD(7); when 3 => varq(3,0) := MQxD(0); varq(5,1) := MQxD(1); varq(7,2) := MQxD(2); varq(1,3) := MQxD(3); varq(2,4) := MQxD(4); varq(4,5) := MQxD(5); varq(6,6) := MQxD(6); varq(0,7) := MQxD(7); when 4 => varq(4,0) := MQxD(0); varq(6,1) := MQxD(1); varq(0,2) := MQxD(2); varq(2,3) := MQxD(3); varq(3,4) := MQxD(4); varq(5,5) := MQxD(5); varq(7,6) := MQxD(6); varq(1,7) := MQxD(7); when 5 => varq(5,0) := MQxD(0); varq(7,1) := MQxD(1); varq(1,2) := MQxD(2); varq(3,3) := MQxD(3); varq(4,4) := MQxD(4); varq(6,5) := MQxD(5); varq(0,6) := MQxD(6); varq(2,7) := MQxD(7); when 6 => varq(6,0) := MQxD(0); varq(0,1) := MQxD(1); varq(2,2) := MQxD(2); varq(4,3) := MQxD(3); varq(5,4) := MQxD(4); varq(7,5) := MQxD(5); varq(1,6) := MQxD(6); varq(3,7) := MQxD(7); when 7 => varq(7,0) := MQxD(0); varq(1,1) := MQxD(1); varq(3,2) := MQxD(2); varq(5,3) := MQxD(3); varq(6,4) := MQxD(4); varq(0,5) := MQxD(5); varq(2,6) := MQxD(6); varq(4,7) := MQxD(7); when others => -- We wait for the shift until the last -- cycle. Now it iis time to shift all -- values for y in 0 to 7 loop for x in 0 to 6 loop varq(x,y) := QxDP((x+INCQ(y)) mod 8 , y); end loop; -- x varq(7,y) := MQxD(y); end loop; -- y end case; Q1xD <= varq; end process p_shiftq; ------------------------------------------------------------------------------- -- Output ------------------------------------------------------------------------------- p_out: process (Q1xD) variable vout : std_logic_vector(511 downto 0); begin -- process p_out for y in 0 to 7 loop for x in 0 to 7 loop vout( ((7-x)*64) + ((7-y) * 8) + 7 downto ((7-x)*64) + ((7-y)*8) ) := Q1xD(x,y); end loop; -- x end loop; -- y QFinxD <= vout; end process p_out; OutxDO <= QFinxD; -- Memory ----------------------------------------------------------------------------- p_mem : process (ClkxCI, RstxRBI) begin -- process p_mem if RstxRBI = '0' then -- asynchronous reset (active low) QxDP <= (others => (others => (others => '0'))); elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge QxDP <= QxDN; end if; end process p_mem; end rtl;