-------------------------------------------------------------------------------- -- Company: -- Engineer: ice -- Version : 0.3.2 -- Brief Description : -- -- VHDL Test Bench for the Module: any SHA-3 candidate ... (supposedly :D) -- Intended to process KAT files that have been preprocessed by "pad.pl" -- -- Dependencies: fifo.vhd and any required *.vhd of hash core -- ============================================================================= -- Usage : Changes must be made in the following 3 places for a specific hash module -- 1 : Values of generics inside Entity Declarative part -- 2 : Component declaration inside of the Architecture Declarative Part -- 3 : Component's instantiation inside of the Architecture Body -- 4 : "FILES DECLARATION" section -- 5 (Optional) : tbtest process. This portion is at the end of the code. -- It should be used to verify the TB's functionality without the core. -- ============================================================================= -- Output : -- The code produces two output files. The output names are based on the file identifier. -- error_file ("test_error.txt" by default) contains the point at which the script does comparison -- test_file ("test_result.txt" by default) contains the result of testbench (0 means pass, 1 means fail) -------------------------------------------------------------------------------- -- Contact : Please contact ehomsiri@gmu.edu for any problems regarding this file -------------------------------------------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_unsigned.all; USE ieee.numeric_std.ALL; USE ieee.std_logic_textio.all; LIBRARY std; USE std.textio.all; ENTITY sha_tb IS --++++++++++++++++++++++++-- --++++++ EDIT BELOW ++++++-- GENERIC ( -- Testbench PARAMETERS clk_period : time := 50 ns; -- clock speed clk_period_mult : integer := 2; -- this value will be used for io_clk where io_clk_period = clk_period/clk_period_mult; (in ns) -- CORE PARAMETERS depth : integer := 2; -- depth of FIFO log2depth : integer := 1; -- 2^X = depth, where X = log2depth w : integer := 64 -- DESIGN WIDTH ); --++++++ END OF EDIT +++++-- --++++++++++++++++++++++++-- END sha_tb; ARCHITECTURE behavior OF sha_tb IS -- ====================== -- -- COMPONENTS DECLARATION -- -- ====================== -- --++++++++++++++++++++++++-- --++++++ EDIT BELOW ++++++-- COMPONENT top is generic ( log2_fast_to_slow_ratio : integer := 1 ); port ( -- global rst : in std_logic; clk : in std_logic; io_clk : in std_logic; --fifo src_ready : in std_logic; src_read : out std_logic; dst_ready : in std_logic; dst_write : out std_logic; din : in std_logic_vector(63 downto 0); dout : out std_logic_vector(63 downto 0) ); end COMPONENT; --++++++ END OF EDIT +++++-- --++++++++++++++++++++++++-- COMPONENT fifo GENERIC ( depth : integer := 64; log2depth : integer := 6; N : integer := 32); port ( clk, rst: in std_logic; wr_en, rd_en: in std_logic; datain : in std_logic_vector(N-1 downto 0); dataout : out std_logic_vector(N-1 downto 0); fifo_full, fifo_empty : out std_logic ); END COMPONENT; -- =================== -- -- SIGNALS DECLARATION -- -- =================== -- -- simulation signals (Used by ATHENa script, ignore if not used) signal simulation_pass : std_logic := '0'; -- '0' signifies a pass at the end of simulation, '1' is fail signal simulation_done : std_logic := '0'; -- '1' signifies a completed simulation, '0' otherwise -- globals SIGNAL clk : std_logic := '1'; signal io_clk : std_logic := '1'; SIGNAL rst : std_logic := '0'; --Inputs SIGNAL fifoin_write : std_logic := '0'; signal fifoout_read : std_logic := '0'; SIGNAL ext_idata : std_logic_vector(w-1 downto 0) := (others=>'0'); --Outputs SIGNAL fifoout_empty : std_logic; SIGNAL fifoin_full : std_logic; SIGNAL ext_odata : std_logic_vector(w-1 downto 0); -- Internals SIGNAL fifoin_empty : std_logic; SIGNAL fifoin_read : std_logic; SIGNAL fifoout_full : std_logic; SIGNAL fifoout_write : std_logic; SIGNAL odata : std_logic_vector(w-1 downto 0); SIGNAL idata : std_logic_vector(w-1 downto 0); ------------- clock constant ------------------ constant io_clk_period : time := clk_period/clk_period_mult; ----------- end of clock constant ------------- ------------- string constant ------------------ constant cons_len : string(1 to 6) := "Len = "; constant cons_msg : string(1 to 6) := "Msg = "; constant cons_md : string(1 to 5) := "MD = "; ----------- end of string constant ------------- ------------- debug constant ------------------ constant debug_input : boolean := false; constant debug_output : boolean := false; ----------- end of clock constant ------------- -- ================= -- -- FILES DECLARATION -- -- ================= -- --------------- input / output files ------------------- FILE datain_file : TEXT OPEN READ_MODE is "input.txt"; FILE dataout_file : TEXT OPEN READ_MODE is "out.txt"; FILE error_file : TEXT OPEN WRITE_MODE is "test_error.txt"; FILE result_file : TEXT OPEN WRITE_MODE is "test_result.txt"; ------------- end of input files -------------------- ---- TEST SIGNALS ---- --signal fifoout_full_aa : std_logic; -- signal test_sel : std_logic; BEGIN clk <= not clk after clk_period / 2; io_clk <= not io_clk after io_clk_period / 2; -- ============ -- -- PORT MAPPING -- -- ============ -- --++++++++++++++++++++++++-- --++++++ EDIT BELOW ++++++-- -- SUBSTITUTE YOUR CORE HERE -- -- NOTE : be careful of src_ready and dst_ready, these inputs are active low and your core must treat them accordingly uut : top generic map ( log2_fast_to_slow_ratio => 1 ) port map ( -- global rst => rst, clk => clk, io_clk => io_clk, --fifo din => idata, src_read => fifoin_read, src_ready => fifoin_empty, dout => odata, dst_write => fifoout_write, dst_ready => fifoout_full); --++++++ END OF EDIT +++++-- --++++++++++++++++++++++++-- fifoin: fifo generic map ( depth => depth, log2depth => log2depth, N => W) port map ( clk=>io_clk, rst=>rst, wr_en=>fifoin_write, rd_en=>fifoin_read, datain=>ext_idata, dataout=>idata, fifo_full=>fifoin_full, fifo_empty=>fifoin_empty ); fifoout: fifo generic map ( depth => depth, log2depth => log2depth, N => W) port map ( clk=>io_clk, rst=>rst, wr_en=>fifoout_write, rd_en=>fifoout_read, datain=>odata, dataout=>ext_odata, fifo_full=>fifoout_full, fifo_empty=>fifoout_empty ); -- =================== -- -- END OF PORT MAPPING -- -- =================== -- -- =========================================================== -- ==================== DATA POPULATION ====================== tb_readdata : PROCESS VARIABLE line_data, errorMsg : LINE; variable word_block : std_logic_vector(w-1 downto 0) := (others=>'0'); variable read_result : boolean; variable loop_enable : boolean := true; variable temp_read : string(1 to 6); BEGIN rst <= '1'; wait for 5*clk_period; rst <= '0'; wait for clk_period; -- read header while ( not endfile (datain_file)) and ( loop_enable ) loop readline(datain_file, line_data); read(line_data, temp_read, read_result); if (temp_read = cons_len) then loop_enable := false; end if; end loop; loop_enable := true; wait for io_clk_period/2; while ( loop_enable ) loop --read data from a line hread( line_data, word_block, read_result ); if ( read_result = false ) then while ((read_result = false) and (not endfile( datain_file ))) loop readline(datain_file, line_data); read(line_data, temp_read, read_result); -- read line header hread( line_data, word_block, read_result );-- read data end loop; if (read_result = false) then loop_enable := false; end if; end if; if ( loop_enable ) then -- if the fifo is full, wait ... fifoin_write <= '1'; while ( fifoin_full = '1' ) loop fifoin_write <= '0'; wait for io_clk_period; fifoin_write <= '1'; end loop; ext_idata <= word_block; wait for io_clk_period; end if; end loop; wait; END PROCESS; -- =========================================================== -- =========================================================== -- =================== DATA VERIFICATION ===================== tb_verifydata : PROCESS variable line_data, errorMsg : LINE; variable word_block : std_logic_vector(w-1 downto 0) := (others=>'0'); variable read_result : boolean; variable loop_enable : boolean := true; variable temp_read : string(1 to 5); begin wait for 6*clk_period; -- read header while ( not endfile (dataout_file)) and ( loop_enable ) loop readline(dataout_file, line_data); read(line_data, temp_read); if (temp_read = cons_md) then loop_enable := false; end if; end loop; loop_enable := true; while ( loop_enable ) loop -- get data to compare hread( line_data, word_block, read_result ); if ( read_result = false ) then while (not endfile( dataout_file ) and (read_result = false)) loop -- if false then read new line readline(dataout_file, line_data); read(line_data, temp_read, read_result); -- read line header hread( line_data, word_block, read_result );-- read data report "---------loading new hash --------" severity error; end loop; if (read_result = false) then loop_enable := false; end if; end if; if ( loop_enable ) then -- if the core is slow in outputting the digested message, wait ... fifoout_read <= '1'; if ( fifoout_empty = '1') then fifoout_read <= '0'; wait until fifoout_empty = '0'; fifoout_read <= '1'; wait for io_clk_period/2; end if; if (ext_odata /= word_block) then report "MISMATCH" severity failure; if ( simulation_pass = '0' ) then simulation_pass <= '1'; end if; write(errorMsg, string'("HASH FAIL at time ==========> ")); write(errorMsg, now); writeline(error_file,errorMsg); end if; wait for io_clk_period; -- wait a cycle for data to come out end if; end loop; fifoout_read <= '0'; wait for io_clk_period; write(errorMsg, simulation_pass); writeline(result_file,errorMsg); simulation_done <= '1'; if ( simulation_pass = '0' ) then report "SIMULATION FINISHED -- Test passed (0)" severity failure; else report "SIMULATION FINISHED -- Test failed (1)" severity failure; end if; wait; end process; -- =========================================================== -- ================================================================ -- # This section is used for testing the tb without the core. -- # Must comment below process in order to run the core properly. -- # Valid signals that can be manipulated in the below process are the handshake signals from a hash core. -- # They are -- fifoin_read, fifoout_empty -- ================================================================ -- fifoout_full_aa <= '1' when test_sel = '1' else fifoout_full; -- tbtest : process -- begin -- test_sel <= '1'; -- wait for 2200 ns; -- test_sel <= '0'; -- wait; -- end process; END;