------------------------------------------------------------
-- Copyright: 2010 Integrated Sytems Laboratory, ETH Zurich
-- http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
entity subkey is
port (
KxDI : in std_logic_vector(255 downto 0);
SxSI : in std_logic_vector(4 downto 0);
KenablexSI : in std_logic;
KinitxSI : in std_logic;
CntxDI : in unsigned(2 downto 0);
RstxRBI : in std_logic;
ClkxCI : in std_logic;
TxDI : in std_logic_vector(127 downto 0);
KsxDO : out std_logic_vector(127 downto 0));
end subkey;
architecture rtl of subkey is
type karray is array (0 to 4) of unsigned(63 downto 0);
signal KexDP, KexDN : karray;
type tarray is array (0 to 2) of unsigned(63 downto 0);
signal TexDP, TexDN : tarray;
signal AddAxD, AddBxD : unsigned(63 downto 0);
signal AddCxD : std_logic_vector(63 downto 0);
signal AddAAxD, AddBBxD : unsigned(63 downto 0);
signal AddCCxD : std_logic_vector(63 downto 0);
signal TempxD : unsigned(63 downto 0);
begin -- rtl
TempxD <= x"5555555555555555" xor KexDP(0) xor KexDP(1) xor
unsigned(KxDI(127 downto 64)) xor unsigned(KxDI(63 downto 0));
-- KexDN(0) KexDP(0) when (CntxDI and KenablexSI = '0') else KexDP(1) when KenablexSI = '0' else unsigned(KxDI(255 downto 192));
-- KexDN(1) KexDP(1) when (CntxDI and KenablexSI = '0') else KexDP(2) when KenablexSI = '0' else unsigned(KxDI(191 downto 128));
-- KexDN(2) KexDP(2) when (CntxDI and KenablexSI = '0') else KexDP(3) when KenablexSI = '0' else unsigned(KxDI(127 downto 64));
-- KexDN(3) KexDP(3) when (CntxDI and KenablexSI = '0') else KexDP(4) when KenablexSI = '0' else unsigned(KxDI(63 downto 0));
-- KexDN(4) KexDP(4) when (CntxDI and KenablexSI = '0') else KexDP(0) when KenablexSI = '0' else x"5555555555555555" xor
-- unsigned(KxDI(255 downto 192)) xor unsigned(KxDI(191 downto 128)) xor
-- unsigned(KxDI(127 downto 64)) xor unsigned(KxDI(63 downto 0));
KexDN(0) <= unsigned(KxDI(255 downto 192)) when (CntxDI = 0 and KenablexSI = '1') else KexDP(1) when (CntxDI = 7 and KenablexSI = '0') else KexDP(0);
KexDN(1) <= unsigned(KxDI(191 downto 128)) when (CntxDI = 0 and KenablexSI = '1') else KexDP(2) when (CntxDI = 7 and KenablexSI = '0') else KexDP(1);
KexDN(2) <= unsigned(KxDI(127 downto 64)) when (CntxDI = 1 and KenablexSI = '1') else KexDP(3) when (CntxDI = 7 and KenablexSI = '0') else KexDP(2);
KexDN(3) <= unsigned(KxDI(63 downto 0)) when (CntxDI = 1 and KenablexSI = '1') else KexDP(4) when (CntxDI = 7 and KenablexSI = '0') else KexDP(3);
KexDN(4) <= TempxD when (CntxDI = 1 and KenablexSI = '1') else KexDP(0) when (CntxDI = 7 and KenablexSI = '0') else KexDP(4);
TexDN(0) <= unsigned(TxDI(127 downto 64)) when ((CntxDI = 0 and KenablexSI = '1') or (KinitxSI = '1' and KenablexSI = '1')) else TexDP(1) when (CntxDI = 7 and KenablexSI = '0') else TexDP(0);
TexDN(1) <= unsigned(TxDI(63 downto 0)) when ((CntxDI = 1 and KenablexSI = '1') or (KinitxSI = '1' and KenablexSI = '1')) else TexDP(2) when (CntxDI = 7 and KenablexSI = '0') else TexDP(1);
TexDN(2) <= unsigned(TxDI(127 downto 64)) xor unsigned(TxDI(63 downto 0)) when ((CntxDI = 1 and KenablexSI = '1') or (KinitxSI = '1' and KenablexSI = '1')) else TexDP(0) when (CntxDI = 7 and KenablexSI = '0') else TexDP(2);
k_shiftreg : process (ClkxCI, RstxRBI)
begin -- process k_shiftreg
if RstxRBI = '0' then -- asynchronous reset (active low)
KexDP(0) <= (others => '0');
KexDP(1) <= (others => '0');
KexDP(2) <= (others => '0');
KexDP(3) <= (others => '0');
KexDP(4) <= (others => '0');
elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge
if KinitxSI = '1' then
KexDP(0) <= X"388512680E660046";
KexDP(1) <= X"4B72D5DEC5A8FF01";
KexDP(2) <= X"281A9298CA5EB3A5";
KexDP(3) <= X"54CA5249F46070C4";
KexDP(4) <= X"5555555555555555" xor KexDP(0) xor KexDP(1) xor KexDP(2) xor KexDP(3);
else
KexDP <= KexDN;
end if;
end if;
end process k_shiftreg;
t_shiftreg : process (ClkxCI, RstxRBI)
begin -- process t_shiftreg
if RstxRBI = '0' then -- asynchronous reset (active low)
TexDP(0) <= (others => '0');
TexDP(1) <= (others => '0');
TexDP(2) <= (others => '0');
elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge
--if KenablexSI = '1' then
TexDP <= TexDN;
--end if;
end if;
end process t_shiftreg;
-- KsxDO(255 downto 192) KexDP(0));
-- KsxDO(191 downto 128) KexDP(1) + TexDP(0));
-- KsxDO(127 downto 64) KexDP(2) + TexDP(1));
-- KsxDO(63 downto 0) KexDP(3) + unsigned(SxSI));
AddAxD <= KexDP(2) when CntxDI = 1 else KexDP(0);
AddBxD <= TexDP(1);
AddAAxD <= KexDP(1) when CntxDI = 0 else KexDP(3);
AddBBxD <= TexDP(0) when CntxDI = 0 else x"00000000000000" & "000" & unsigned(SxSI);
AddCxD <= std_logic_vector(AddAxD + AddBxD);
AddCCxD <= std_logic_vector(AddAAxD + AddBBxD);
KsxDO(127 downto 64) <= AddCxD when CntxDI = 1 else std_logic_vector(KexDP(0)) when CntxDI = 0 else (others => '0');
KsxDO(63 downto 0) <= AddCCxD when CntxDI < 2 else (others => '0');
end rtl;