------------------------------------------------------------
-- 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 (256 bit for Shabal-256)
ValidOutxSO : out std_logic
);
end perm;
architecture rtl of perm is
component fsm
port (
ClkxCI : in std_logic;
RstxRBI : in std_logic;
NewBlockxSI : in std_logic;
StatexDO : out integer range 0 to 6;
CntxDO : out integer range 0 to 48;
ValidOutxSO : out std_logic);
end component;
signal AxDN, AxDP : blockA;
signal MxDN, MxDP, BxDN, BxDP, CxDN, CxDP : blockB;
signal WxDN, WxDP : blockW;
signal StatexD : integer range 0 to 6;
signal CntxD : integer range 0 to 48;
begin -- rtl
u_fsm : fsm
port map (
ClkxCI => ClkxCI,
RstxRBI => RstxRBI,
NewBlockxSI => NewBlockxSI,
StatexDO => StatexD,
CntxDO => CntxD,
ValidOutxSO => ValidOutxSO);
p_update : process (AxDP, BxDP, CntxD, CxDP, MxDI, MxDP, NewBlockxSI,
StartxSI, StatexD, WxDP)
variable Aperm, Inperm1, Inperm2, In1, In2, AddOut, XorOut, XorIn, XorIn2 : std_logic_vector(31 downto 0) := (others => '0');
variable winc : unsigned(63 downto 0);
variable Wnew : blockW := (others => (others => '0'));
begin -- process p_update
AxDN <= AxDP;
BxDN <= BxDP;
CxDN <= CxDP;
MxDN <= MxDP;
WxDN <= WxDP;
In1 := (others => '0');
In2 := (others => '0');
XorIn := (others => '0');
XorIn2 := (others => '0');
winc := unsigned(unsigned(WxDP(1)) & unsigned(WxDP(0)))+1;
case StatexD is
--when 1 =>
when 2 =>
In1 := BxDP(CntxD);
In2 := MxDP(CntxD);
when 3 =>
Inperm1 := Rotl(AxDP(11), 15);
In1 := Inperm1;
In2 := Inperm1(29 downto 0) & '0' & '0';
XorIn := AxDP(0);
XorIn2 := CxDP(8);
when 4 =>
Inperm2 := AxDP(0);
In1 := Inperm2;
In2 := Inperm2(30 downto 0) & '0';
XorIn := BxDP(o1);
XorIn2 := MxDP(0);
when 5 | 6 | 1 =>
In1 := AxDP(0);
In2 := CxDP(3);
--when 6 =>
--In1 := CxDP(CntxD);
--In2 := std_logic_vector(unsigned(not MxDP(CntxD))+1);
--In2 := not MxDP(CntxD);
when others => null;
end case;
AddOut := std_logic_vector(unsigned(In1) + unsigned(In2));
XorOut := AddOut xor XorIn xor XorIn2;
case StatexD is
when 1 =>
Wnew := WxDP;
if NewBlockxSI = '1' then
-- initialize W
for i in 0 to 15 loop
MxDN(i) <= MxDI((16-i)*WWIDTH-1 downto (15-i)*WWIDTH);
end loop; -- i
Wnew(1) := std_logic_vector(winc(63 downto 32));
Wnew(0) := std_logic_vector(winc(31 downto 0));
end if;
WxDN <= Wnew;
AxDN(0) <= AxDP(0) xor Wnew(0);
AxDN(1) <= AxDP(1) xor Wnew(1);
if StartxSI = '1' then
AxDN <= Ainit;
BxDN <= Binit;
CxDN <= Cinit;
WxDN(1) <= x"00000000";
WxDN(0) <= x"00000001";
end if;
when 2 =>
--BxDN(CntxD) <= Rotl(AddOut,17);
BxDN(CntxD) <= Rotl(XorOut,17);
when 3 =>
AxDN(0) <= XorOut;
when 4 =>
Aperm := XorOut xor (BxDP(o2) and not(BxDP(o3)));
for i in 0 to 10 loop
AxDN(i) <= AxDP(i+1);
end loop; -- i
AxDN(11) <= Aperm;
CxDN(0) <= CxDP(15);
MxDN(0) <= MxDP(1);
for i in 1 to 14 loop
CxDN(i) <= CxDP(i-1);
MxDN(i) <= MxDP(i+1);
end loop; -- i
CxDN(15) <= CxDP(14);
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 5 =>
for i in 0 to 10 loop
AxDN(i) <= AxDP(i+1);
end loop;
--AxDN(11) <= AddOut;
AxDN(11) <= XorOut;
CxDN(15) <= CxDP(0);
for i in 0 to 14 loop
CxDN(i) <= CxDP(i+1);
end loop;
if CntxD = 35 then
CxDN(0) <= CxDP(13);
CxDN(1) <= CxDP(14);
CxDN(2) <= CxDP(15);
for i in 3 to 15 loop
CxDN(i) <= CxDP(i-3);
end loop;
end if;
when 6 =>
--BxDN(CntxD) <= std_logic_vector(unsigned(AddOut)+1);
--BxDN(CntxD) <= AddOut;
BxDN(CntxD) <= std_logic_vector(unsigned(CxDP(CntxD))- unsigned(MxDP(CntxD)));
CxDN(CntxD) <= BxDP(CntxD);
when others => null;
end case;
end process p_update;
-----------------------------------------------------------------------------
-- 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;