------------------------------------------------------------ -- 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;