------------------------------------------------------------
-- Copyright: 2010 Integrated Sytems Laboratory, ETH Zurich
-- http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.shabalPkg.all;
entity perm is
port (
ClkxCI : in std_logic;
RstxRBI : in std_logic;
NewBlockxSI : in std_logic;
StartxSI : in std_logic;
MxDI : in std_logic_vector(WWIDTH*16-1 downto 0);
1 downto 0); -- hash output
-- (Shabal-256:8, Shabal-512:16)
ValidOutxSO : out std_logic
);
end perm;
architecture rtl of perm is
component controller
port (
ClkxCI : in std_logic;
RstxRBI : in std_logic;
NewBlockxSI : in std_logic;
StatexDO : out std_logic_vector(1 downto 0);
CntxDO : out unsigned(1 downto 0);
LastxSO : out std_logic;
ValidOutxSO : out std_logic);
end component;
signal AxDN, AxDP : blockA;
signal MxDN, MxDP, BxDN, BxDP, CxDN, CxDP : blockB;
signal WxDN, WxDP : blockW;
signal StatexD : std_logic_vector(1 downto 0);
signal CntxD : unsigned(1 downto 0);
signal LastxS : std_logic;
begin -- rtl
u_controller : controller
port map (
ClkxCI => ClkxCI,
RstxRBI => RstxRBI,
NewBlockxSI => NewBlockxSI,
StatexDO => StatexD,
CntxDO => CntxD,
LastxSO => LastxS,
ValidOutxSO => ValidOutxSO);
p_update : process (AxDP, BxDP, CntxD, CxDP, LastxS, MxDI, MxDP, NewBlockxSI,
StartxSI, StatexD, WxDP)
variable Aperm, Wnew0, Wnew1, Anew0, Anew1 : std_logic_vector(31 downto 0);
variable Marray, Bnew : blockB;
begin -- process p_update
AxDN <= AxDP;
BxDN <= BxDP;
CxDN <= CxDP;
MxDN <= MxDP;
WxDN <= WxDP;
case StatexD is
when "11" =>
-- initialize M
for i in 0 to 15 loop
Marray(i) := MxDI((16-i)*WWIDTH-1 downto (15-i)*WWIDTH);
end loop; -- i
if NewBlockxSI = '1' then
MxDN <= Marray;
end if;
if StartxSI = '1' then
-- initialize last 10 words of A
AxDN(2 to 11) <= Ainit(2 to 11);
Anew0 := Ainit(0);
Anew1 := Ainit(1);
Bnew := Binit;
-- initialize C
CxDN <= Cinit;
Wnew0 := x"00000001";
Wnew1 := (others => '0');
else
Anew0 := AxDP(0);
Anew1 := AxDP(1);
Bnew := BxDP;
-- increment W unless the final block is processed
if NewBlockxSI = '0' then
Wnew0 := WxDP(0);
Wnew1 := WxDP(1);
else
Wnew0 := std_logic_vector(unsigned(WxDP(0)) + 1);
Wnew1 := WxDP(1);
if Wnew0 = x"00000000" then
Wnew1 := std_logic_vector(unsigned(WxDP(1)) + 1);
end if;
end if;
end if;
-- update/initialize W and first 2 words of A
WxDN(0) <= Wnew0;
WxDN(1) <= Wnew1;
AxDN(0) <= Anew0 xor Wnew0;
AxDN(1) <= Anew1 xor Wnew1;
-- initialize B, add input block and rotate
for i in 0 to 15 loop
if LastxS = '0' then
BxDN(i) <= Rotl(std_logic_vector(unsigned(Bnew(i)) + unsigned(Marray(i))),17);
else
BxDN(i) <= Rotl(std_logic_vector(unsigned(Bnew(i)) + unsigned(MxDP(i))),17);
end if;
end loop;
-------------------------------------------------------------------------
when "01" =>
for i in 0 to 10 loop
AxDN(i) <= AxDP(i+1);
end loop; -- i
Aperm := Ufun(AxDP(0) xor Vfun(Rotl(AxDP(11),15)) xor CxDP(8)) xor BxDP(o1) xor (BxDP(o2) and not(BxDP(o3))) xor MxDP(0);
AxDN(11) <= Aperm; -- A(i+16*j mod r) computation
-- for i in 0 to 15 loop
-- CxDN(i) CxDP(i-1 mod 16);
-- MxDN(i) MxDP(i+1 mod 16);
-- end loop; -- i
for i in 1 to 15 loop
CxDN(i) <= CxDP(i-1);
end loop; -- i
CxDN(0) <= CxDP(15);
for i in 0 to 14 loop
MxDN(i) <= MxDP(i+1);
end loop; -- i
MxDN(15) <= MxDP(0);
for i in 0 to 14 loop
BxDN(i) <= BxDP(i+1);
end loop; -- i
BxDN(15) <= Rotl(BxDP(0),1) xor not(Aperm);
-------------------------------------------------------------------------
when "10" =>
for i in 0 to 11 loop
AxDN(i) <= std_logic_vector(unsigned(AxDP(i)) + unsigned(CxDP(APCMATRIX(to_integer(CntxD),i))));
end loop; -- i
-- after finishing the permutation, subtract the message block from C
-- and swap B and C
if CntxD = 2 then
for i in 0 to 15 loop
BxDN(i) <= std_logic_vector(unsigned(CxDP(i)) - unsigned(MxDP(i)));
CxDN(i) <= BxDP(i);
end loop; -- i
end if;
-------------------------------------------------------------------------
when others => null;
end case;
end process p_update;
-----------------------------------------------------------------------------
-- OUTPUT
-----------------------------------------------------------------------------
-- HashxDO(16*WWIDTH-1 downto 15*WWIDTH) CxDP(0);
-- HashxDO(15*WWIDTH-1 downto 14*WWIDTH) CxDP(1);
-- HashxDO(14*WWIDTH-1 downto 13*WWIDTH) CxDP(2);
-- HashxDO(13*WWIDTH-1 downto 12*WWIDTH) CxDP(3);
-- HashxDO(12*WWIDTH-1 downto 11*WWIDTH) CxDP(4);
-- HashxDO(11*WWIDTH-1 downto 10*WWIDTH) CxDP(5);
-- HashxDO(10*WWIDTH-1 downto 9*WWIDTH) CxDP(6);
-- HashxDO(9*WWIDTH-1 downto 8*WWIDTH) CxDP(7);
-- Shabal-256 output:
HashxDO(8*WWIDTH-1 downto 7*WWIDTH) <= CxDP(8);
HashxDO(7*WWIDTH-1 downto 6*WWIDTH) <= CxDP(9);
HashxDO(6*WWIDTH-1 downto 5*WWIDTH) <= CxDP(10);
HashxDO(5*WWIDTH-1 downto 4*WWIDTH) <= CxDP(11);
HashxDO(4*WWIDTH-1 downto 3*WWIDTH) <= CxDP(12);
HashxDO(3*WWIDTH-1 downto 2*WWIDTH) <= CxDP(13);
HashxDO(2*WWIDTH-1 downto WWIDTH) <= CxDP(14);
HashxDO(WWIDTH-1 downto 0) <= CxDP(15);
-----------------------------------------------------------------------------
-- MEMORY
-----------------------------------------------------------------------------
p_mem: process (ClkxCI, RstxRBI)
begin -- process p_mem
if RstxRBI = '0' then -- asynchronous reset (active low)
AxDP <= (others => (others => '0'));
BxDP <= (others => (others => '0'));
CxDP <= (others => (others => '0'));
WxDP <= (others => (others => '0'));
MxDP <= (others => (others => '0'));
elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge
AxDP <= AxDN;
BxDP <= BxDN;
CxDP <= CxDN;
WxDP <= WxDN;
MxDP <= MxDN;
end if;
end process p_mem;
end rtl;