------------------------------------------------------------
-- Copyright: 2011 George Mason University, Virginia USA
-- http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
-- =====================================================================
-- Copyright © 2010-11 by Cryptographic Engineering Research Group (CERG),
-- ECE Department, George Mason University
-- Fairfax, VA, U.S.A.
-- =====================================================================
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use work.sha2_pkg.all;
entity gmu_sha2_control is
generic (
a : integer := LOG_2_64
);
port(
clk :in std_logic;
rst :in std_logic;
-- to datpath
sel2 :out std_logic;
sel :out std_logic;
sel_gh :out std_logic;
sel_gh2 :out std_logic;
wr_data :out std_logic;
kw_wr :out std_logic;
wr_state :out std_logic;
wr_result :out std_logic;
init_reg :out std_logic;
init_block :out std_logic;
rd_num :out std_logic_vector(a-1 downto 0);
-- external
InWrEnxSI : in std_logic;
FinBlockxSI : in std_logic;
OutWrEnxSO : out std_logic;
PenUltCyclexSO : out std_logic
);
end gmu_sha2_control;
architecture asic_controller of gmu_sha2_control is
type state_type is (
prep_data,
wr_get_data,
kw_compute,
data,
data_end,
dummy,
computation,
computation_end,
result_delay,
result_delay2,
result_delay3,
result,
mux_gh,
send_data,
done);
signal next_state, current_state: state_type;
attribute enum_encoding : string;
signal roundCtr : std_logic_vector(a-1 downto 0);
signal incRoundCtr, loadRoundCtr : std_logic;
signal lastBlockFlag, lastBlockSet, lastBlockClr : std_logic;
signal nextBlockIsLastFlag, nextBlockIsLastSet : std_logic;
signal loadFinFlagReg, computedFinFlagReg : std_logic;
signal loadFinFlag, computedFinFlag : std_logic;
begin
roundCtrProc:
process( rst, clk )
begin
if (rst = '0') then
roundCtr <= (others => '0');
elsif rising_edge( clk ) then
if loadRoundCtr = '1' then
roundCtr <= (others => '0');
elsif incRoundCtr = '1' then
roundCtr <= roundCtr + 1;
end if;
end if;
end process;
rd_num <= roundCtr;
state_reg: process(clk, rst)
begin
if (rst='0') then
current_state <= done; -- set to done to reset all the flags
elsif (clk'event and clk='1') then
current_state <= next_state;
end if;
end process;
roundCompareRegister : process( clk, rst )
begin
if (rst='0') then
loadFinFlagReg <= '0';
computedFinFlagReg <= '0';
elsif (clk'event and clk='1') then
loadFinFlagReg <= loadFinFlag;
computedFinFlagReg <= computedFinFlag;
end if;
end process;
loadFinFlag <= '1' when roundCtr = 11 else '0';
computedFinFlag <= '1' when roundCtr = 59 else '0';
comb_logic: process(current_state, InWrEnxSI, loadFinFlagReg, computedFinFlagReg, lastBlockFlag)
begin
case current_state is
when prep_data =>
if InWrEnxSI = '1' then
next_state <= wr_get_data;
else
next_state <= prep_data;
end if;
when wr_get_data =>
next_state <= kw_compute;
when kw_compute =>
next_state <= data;
when data =>
if loadFinFlagReg='1' then
next_state <= data_end;
else
next_state <= data;
end if;
when data_end =>
next_state <= dummy;
when dummy =>
next_state <= computation;
when computation =>
if computedFinFlagReg='1' then
next_state <= computation_end;
else
next_state <= computation;
end if;
when computation_end=>
next_state <= result_delay;
when result_delay=>
next_state <= result_delay2;
when result_delay2=>
next_state <= result_delay3;
when result_delay3=>
if InWrEnxSI='1' or lastBlockFlag = '1' then
next_state <= result;
else
next_state <= result_delay3;
end if;
when result =>
if lastBlockFlag='1' then
next_state <= send_data;
else
next_state <= mux_gh;
end if;
when mux_gh => -- if message not done
next_state <= data;
when send_data =>
next_state <= done;
when done =>
next_state <= prep_data;
end case;
end process;
wr_data <= '1' when
(InWrEnxSI = '1' and
((current_state=prep_data)
or (current_state=result_delay3 and lastBlockFlag = '0'))
)
or (current_state=dummy)
or (current_state=result)
or (current_state=mux_gh)
or (current_state=result)
or (current_state=wr_get_data) or (current_state=kw_compute) or (current_state=data) or (current_state=data_end)
or (current_state=computation) or (current_state=computation_end) or (current_state=result_delay) or (current_state=result_delay2)
else '0';
wr_result<= '1' when (current_state= result_delay)
or (current_state= result_delay2)
or (current_state= result_delay3 and (InWrEnxSI='1' or lastBlockFlag = '1'))
or (current_state=result)
or current_state=send_data else '0';
wr_state <= '1' when
((InWrEnxSI = '1' or lastBlockFlag = '1') and (current_state=result_delay3))
or (current_state=data_end)
or (current_state=dummy)
or (current_state = kw_compute)
or (current_state = data)
or (current_state=result)
or (current_state=mux_gh)
or (current_state=computation or current_state=computation_end or current_state=result_delay or current_state=result_delay2)
else '0';
incRoundCtr <= '1' when
(current_state=wr_get_data)
or (current_state=kw_compute)
or (current_state=data)
or (current_state=data_end)
or (current_state=dummy)
or (current_state=mux_gh)
or (current_state=result and lastBlockFlag = '0')
or (current_state=computation) or (current_state=computation_end) or (current_state=result_delay) or (current_state=result_delay2)
else '0';
loadRoundCtr <= '1' when (current_state=done) else '0';
init_reg <= loadRoundCtr;
kw_wr <='1' when
(current_state=kw_compute)
or (current_state = wr_get_data)
or (current_state=data)
or (current_state=data_end)
or (current_state=dummy)
or ((current_state=result or current_state=mux_gh) and lastBlockFlag = '0')
or (current_state=computation) or (current_state=computation_end) or (current_state=result_delay) or (current_state=result_delay2)
else '0';
sel <= '1' when (current_state=result) else '0';
init_block <= '1' when (current_state=result_delay3) or (current_state=prep_data) else '0';
sel2 <='1' when (current_state=computation) or (current_state=computation_end) or (current_state=result_delay) else '0';
sel_gh <= '1' when (current_state=wr_get_data) or (current_state=result) else '0';
sel_gh2 <= '1' when (current_state=result) else '0';
OutWrEnxSO <= '1' when (current_state=send_data) else '0';
lastBlockInst:
entity work.sr_rega(struct)
port map ( rst => rst, clk => clk, set => lastBlockSet, clr => lastBlockClr, output => lastBlockFlag );
lastBlockSet <= '1' when ((current_state = prep_data ) and (FinBlockxSI = '1' and InWrEnxSI = '1')) or
(current_state = mux_gh and nextBlockIsLastFlag = '1') else '0';
lastBlockClr <= '1' when (current_state = send_data) else '0';
nextBlockIslastInst:
entity work.sr_rega(struct)
port map ( rst => rst, clk => clk, set => nextBlockIsLastSet, clr => lastBlockClr, output => nextBlockIsLastFlag );
nextBlockIsLastSet <= '1' when (current_state = result_delay3 and (FinBlockxSI = '1' and InWrEnxSI = '1')) else '0';
PenUltCyclexSO <= '1' when (current_state = result_delay2 and lastBlockFlag = '0') or (current_state = done) else '0';
end asic_controller;