-- ================================================================================================ -- Hash Function Wrapper - Control Unit - Register = 2*W -- ================================================================================================ -- Claude Shannon Institute for Discrete Mathematics, Coding, Cryptography and Information Security -- Department of Electrical and Electronic Engineering -- University College Cork -- Cork -- Ireland -- http://www.ucc.ie/en/crypto/ -- http://shannoninstitute.ie/ --{neilh,brianb,markh,liam}@eleceng.ucc.ie -- -- January 2010 -- ver 2a - 11/03/10 -- ================================================================================================ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; library work; use work.wrapper_pkg.all; -- entity declaration entity ctrl_hamsi64 is generic ( DIG : natural -- message digest size ); port ( -- i/o to outside world clk : in std_logic; rst : in std_logic; ack_in : out std_logic; -- data present on input bus has been read dp_in : in std_logic; -- data present on input bus lb_in : in std_logic; -- data present on input bus is the last block ack_out : in std_logic; -- data present on output bus has been read dp_out : out std_logic; -- data present on output bus lb_out : out std_logic; -- data present on output bus is the last block -- padding control ctr_en : out std_logic; -- counter enable ctr_cl : out std_logic; -- counter clear sel_in : out std_logic_vector(2 downto 0); -- input select line -- hash unit control ack_h_in : in std_logic; -- data input to hash function has been read dp_h_in : out std_logic; -- data present at hash input bus lb_h_in : out std_logic; -- data present at hash input bus is the last block ack_h_out : out std_logic; -- message digest has been read dp_h_out : in std_logic; -- message digest available to read -- output control sel_out : out std_logic_vector(1 downto 0) -- output select control line ); end ctrl_hamsi64; -- ================================================================================================ architecture behaviour of ctrl_hamsi64 is -- constant declaration constant OB : natural := DIG/BWS; -- number of output blocks required to pass full message digest constant CW : natural := log2c(OB); -- output counter width -- type declaration type state_type is (idle, read_msb, read_lsb, send_int, half_pad, all_pad, send_ctr, data_wait, data_send); -- signal declaration signal f1_reg, f1_next : std_logic; -- last block flag signal f2_reg, f2_next : std_logic; -- padding complete flag signal i_reg, i_next : unsigned(CW-1 downto 0); -- output block counter signal s_reg, s_next : state_type; begin -- register assignment process(clk, rst) begin if (rst='1') then f1_reg <= '0'; f2_reg <= '0'; i_reg <= (others=>'0'); s_reg <= idle; elsif (clk'event and clk='1') then f1_reg <= f1_next; f2_reg <= f2_next; i_reg <= i_next; s_reg <= s_next; end if; end process; -- controller process(f1_reg, f2_reg, i_reg, s_reg, dp_in, lb_in, ack_h_in, dp_h_out, ack_out) begin -- default output signal values -- input signals ack_in <= '0'; -- padding signals ctr_en <= '0'; ctr_cl <= '0'; sel_in <= "000"; -- hash function signals dp_h_in <= '0'; lb_h_in <= '0'; ack_h_out <= '0'; -- output block signals sel_out <= "00"; -- output signals dp_out <= '0'; lb_out <= '0'; -- default register values i_next <= i_reg; f1_next <= f1_reg; f2_next <= f2_reg; -- state machine case s_reg is when idle => -- mealy output if (dp_in='1') then ack_in <= '1'; ctr_en <= '1'; sel_in <= "001"; if (lb_in='1') then f1_next <= '1'; s_next <= half_pad; else s_next <= read_msb; end if; else if (lb_in='1') then ack_in <= '1'; sel_in <= "011"; s_next <= all_pad; else s_next <= idle; end if; end if; when read_msb => if (dp_in='1') then ack_in <= '1'; ctr_en <= '1'; sel_in <= "001"; s_next <= send_int; if (lb_in='1') then f1_next <= '1'; end if; else s_next <= read_msb; end if; when read_lsb => if (dp_in='1') then ack_in <= '1'; ctr_en <= '1'; sel_in <= "001"; if (lb_in='1') then f1_next <= '1'; s_next <= half_pad; else s_next <= read_msb; end if; else s_next <= read_lsb; end if; when half_pad => sel_in <= "010"; f2_next <= '1'; s_next <= send_int; when send_int => dp_h_in <= '1'; if (ack_h_in='1') then if (f1_reg='1') then if (f2_reg='1') then sel_in <= "100"; s_next <= send_ctr; else sel_in <= "011"; s_next <= all_pad; end if; else s_next <= read_lsb; end if; else s_next <= send_int; end if; when all_pad => dp_h_in <= '1'; if (ack_h_in='1') then sel_in <= "100"; s_next <= send_ctr; else s_next <= all_pad; end if; when send_ctr => dp_h_in <= '1'; lb_h_in <= '1'; if (ack_h_in='1') then f1_next <= '0'; f2_next <= '0'; ctr_cl <= '1'; sel_in <= "101"; s_next <= data_wait; else s_next <= send_ctr; end if; when data_wait => -- mealy output if (dp_h_out='1') then ack_h_out <= '1'; sel_out <= "01"; i_next <= to_unsigned(0, CW); s_next <= data_send; else s_next <= data_wait; end if; when data_send => -- moore output dp_out <= '1'; -- mealy output if (i_reg=OB-1) then lb_out <= '1'; if (ack_out='1') then sel_out <= "11"; i_next <= (others=>'0'); s_next <= idle; else s_next <= data_send; end if; else s_next <= data_send; if (ack_out='1') then sel_out <= "10"; i_next <= i_reg+1; end if; end if; end case; end process; end behaviour;