------------------------------------------------------------ -- Copyright: 2011 Integrated Sytems Laboratory, ETH Zurich -- http://www.iis.ee.ethz.ch/~sha3 ------------------------------------------------------------ ------------------------------------------------------------------------------- -- Title : The P round of Groestl -- Project : ------------------------------------------------------------------------------- -- File : greostl_p.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 Corrected many bugs -- 2011-09-05 1.2 kgf Moved the register after the roundconstants to -- reduce the input timing ------------------------------------------------------------------------------- library ieee; use ieee.numeric_std.all; use ieee.std_logic_1164.all; entity groestl_p 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_p; architecture rtl of groestl_p 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 PxDP, PxDN, P1xD : statematrix; signal RPxD : std_logic_vector(63 downto 0); -- selected column signal SPxD : std_logic_vector(63 downto 0); -- after Subbytes signal MPxD : statearray; -- after MixBytes signal M1xD : minputtype; signal PStartxD : std_logic_vector(511 downto 0); -- start of the Calculation signal PFinxD : std_logic_vector(511 downto 0); -- end of the calculation constant INCP : incconsttype := (0, 1, 2, 3, 4, 5, 6, 7); -- shift amounts for P begin -- rtl ------------------------------------------------------------------------------- -- New start either a fresh vector or a state round ------------------------------------------------------------------------------- PStartxD <= InxDI when RndxSI = "00000000" else PFinxD; p_new : process (SubRndxSI, RndxSI, P1xD, PStartxD) variable varp : statematrix; begin -- process p_new varp := P1xD; if SubRndxSI = 0 then -- Add round constant varp(0, 0) := PStartxD(511 downto 504) xor x"00" xor RndxSI; varp(1, 0) := PStartxD(447 downto 440) xor x"10" xor RndxSI; varp(2, 0) := PStartxD(383 downto 376) xor x"20" xor RndxSI; varp(3, 0) := PStartxD(319 downto 312) xor x"30" xor RndxSI; varp(4, 0) := PStartxD(255 downto 248) xor x"40" xor RndxSI; varp(5, 0) := PStartxD(191 downto 184) xor x"50" xor RndxSI; varp(6, 0) := PStartxD(127 downto 120) xor x"60" xor RndxSI; varp(7, 0) := PStartxD( 63 downto 56) xor x"70" xor RndxSI; for y in 1 to 7 loop for x in 0 to 7 loop varp(x,y) := PStartxD((((7-x) * 64) + ((7-y) *8) + 7) downto ((7-x) * 64) + ((7-y) *8)); end loop; -- x end loop; -- y end if; PxDN <= varp; end process p_new; ------------------------------------------------------------------------------- -- Register is here PxDP PxDN ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -- Select a vector to operate on. The shift is implicit in here ------------------------------------------------------------------------------- -- note that the SubRndxSI is one cycle behind, the register is before this p_selp: process (PxDP, SubRndxSI) begin -- process p_selp case SubRndxSI is when 1 => RPxD <= PxDP(0,0) & PxDP(1,1) & PxDP(2,2) & PxDP(3,3) & PxDP(4,4) & PxDP(5,5) & PxDP(6,6) & PxDP(7,7); when 2 => RPxD <= PxDP(1,0) & PxDP(2,1) & PxDP(3,2) & PxDP(4,3) & PxDP(5,4) & PxDP(6,5) & PxDP(7,6) & PxDP(0,7); when 3 => RPxD <= PxDP(2,0) & PxDP(3,1) & PxDP(4,2) & PxDP(5,3) & PxDP(6,4) & PxDP(7,5) & PxDP(0,6) & PxDP(1,7); when 4 => RPxD <= PxDP(3,0) & PxDP(4,1) & PxDP(5,2) & PxDP(6,3) & PxDP(7,4) & PxDP(0,5) & PxDP(1,6) & PxDP(2,7); when 5 => RPxD <= PxDP(4,0) & PxDP(5,1) & PxDP(6,2) & PxDP(7,3) & PxDP(0,4) & PxDP(1,5) & PxDP(2,6) & PxDP(3,7); when 6 => RPxD <= PxDP(5,0) & PxDP(6,1) & PxDP(7,2) & PxDP(0,3) & PxDP(1,4) & PxDP(2,5) & PxDP(3,6) & PxDP(4,7); when 7 => RPxD <= PxDP(6,0) & PxDP(7,1) & PxDP(0,2) & PxDP(1,3) & PxDP(2,4) & PxDP(3,5) & PxDP(4,6) & PxDP(5,7); when others => RPxD <= PxDP(7,0) & PxDP(0,1) & PxDP(1,2) & PxDP(2,3) & PxDP(3,4) & PxDP(4,5) & PxDP(5,6) & PxDP(6,7); end case; end process p_selp; ------------------------------------------------------------------------------- -- 8 x Sub bytes on this vector ------------------------------------------------------------------------------- gen_p_sub: for i in 0 to 7 generate i_subbytes: groestl_subbytes port map (DxDI => RPxD( (i*8) +7 downto i*8), DxDO => SPxD( (i*8) +7 downto i*8)); end generate gen_p_sub; ------------------------------------------------------------------------------- -- We have a fixed MixBytes function. Normally the function is shifted, we will -- shift the input data instead ------------------------------------------------------------------------------- -- M1xD(0) SPxD; -- M1xD(1) SPxD( 7 downto 0) & SPxD(63 downto 8); -- M1xD(2) SPxD(15 downto 0) & SPxD(63 downto 16); -- M1xD(3) SPxD(23 downto 0) & SPxD(63 downto 24); -- M1xD(4) SPxD(31 downto 0) & SPxD(63 downto 32); -- M1xD(5) SPxD(39 downto 0) & SPxD(63 downto 40); -- M1xD(6) SPxD(47 downto 0) & SPxD(63 downto 48); -- M1xD(7) SPxD(55 downto 0) & SPxD(63 downto 56); M1xD(0) <= SPxD; M1xD(1) <= SPxD(55 downto 0) & SPxD(63 downto 56); M1xD(2) <= SPxD(47 downto 0) & SPxD(63 downto 48); M1xD(3) <= SPxD(39 downto 0) & SPxD(63 downto 40); M1xD(4) <= SPxD(31 downto 0) & SPxD(63 downto 32); M1xD(5) <= SPxD(23 downto 0) & SPxD(63 downto 24); M1xD(6) <= SPxD(15 downto 0) & SPxD(63 downto 16); M1xD(7) <= SPxD( 7 downto 0) & SPxD(63 downto 8); gen_p_mix: for i in 0 to 7 generate i_mixbytes: g_mixbytes port map ( InxDI => M1xD(i), OutxDO => MPxD(i)); end generate gen_p_mix; ------------------------------------------------------------------------------- -- Write back P ------------------------------------------------------------------------------- p_shiftp: process (PxDP, SubRndxSI, MPxD) variable varb: statematrix; begin -- process p_selp -- default varb := PxDP; -- do not shift for the first 7 cycles; -- note that the SubRndxSI is one cycle behind, the register is before this case SubRndxSI is when 1 => varb(0,0) := MPxD(0); varb(1,1) := MPxD(1); varb(2,2) := MPxD(2); varb(3,3) := MPxD(3); varb(4,4) := MPxD(4); varb(5,5) := MPxD(5); varb(6,6) := MPxD(6); varb(7,7) := MPxD(7); when 2 => varb(1,0) := MPxD(0); varb(2,1) := MPxD(1); varb(3,2) := MPxD(2); varb(4,3) := MPxD(3); varb(5,4) := MPxD(4); varb(6,5) := MPxD(5); varb(7,6) := MPxD(6); varb(0,7) := MPxD(7); when 3 => varb(2,0) := MPxD(0); varb(3,1) := MPxD(1); varb(4,2) := MPxD(2); varb(5,3) := MPxD(3); varb(6,4) := MPxD(4); varb(7,5) := MPxD(5); varb(0,6) := MPxD(6); varb(1,7) := MPxD(7); when 4 => varb(3,0) := MPxD(0); varb(4,1) := MPxD(1); varb(5,2) := MPxD(2); varb(6,3) := MPxD(3); varb(7,4) := MPxD(4); varb(0,5) := MPxD(5); varb(1,6) := MPxD(6); varb(2,7) := MPxD(7); when 5 => varb(4,0) := MPxD(0); varb(5,1) := MPxD(1); varb(6,2) := MPxD(2); varb(7,3) := MPxD(3); varb(0,4) := MPxD(4); varb(1,5) := MPxD(5); varb(2,6) := MPxD(6); varb(3,7) := MPxD(7); when 6 => varb(5,0) := MPxD(0); varb(6,1) := MPxD(1); varb(7,2) := MPxD(2); varb(0,3) := MPxD(3); varb(1,4) := MPxD(4); varb(2,5) := MPxD(5); varb(3,6) := MPxD(6); varb(4,7) := MPxD(7); when 7 => varb(6,0) := MPxD(0); varb(7,1) := MPxD(1); varb(0,2) := MPxD(2); varb(1,3) := MPxD(3); varb(2,4) := MPxD(4); varb(3,5) := MPxD(5); varb(4,6) := MPxD(6); varb(5,7) := MPxD(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 varb(x,y) := PxDP((x+INCP(y)) mod 8 , y); end loop; -- x varb(7,y) := MPxD(y); end loop; -- y end case; P1xD <= varb; end process p_shiftp; ------------------------------------------------------------------------------- -- Output ------------------------------------------------------------------------------- p_out: process (P1xD) 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) ) := P1xD(x,y); end loop; -- x end loop; -- y PFinxD <= vout; end process p_out; OutxDO <= PFinxD; -- Memory ----------------------------------------------------------------------------- p_mem : process (ClkxCI, RstxRBI) begin -- process p_mem if RstxRBI = '0' then -- asynchronous reset (active low) PxDP <= (others => (others => (others => '0'))); elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge PxDP <= PxDN; end if; end process p_mem; end rtl;