------------------------------------------------------------ -- Copyright: 2011 George Mason University, Virginia USA -- http://www.iis.ee.ethz.ch/~sha3 ------------------------------------------------------------ ------------------------------------------------------------------------------- -- Title : Testbench for Blake GMU version -- Project : Shabziger ------------------------------------------------------------------------------- -- File : gmu_blake_tb.vhdl -- Author : Frank K. Guerkaynak -- Company : Integrated Systems Laboratory, ETH Zurich -- Created : 2011-08-22 -- Last update: 2011-08-25 -- Platform : ModelSim (simulation), Synopsys (synthesis) -- Standard : VHDL'87 ------------------------------------------------------------------------------- -- Description: Standard Shabziger testbench ------------------------------------------------------------------------------- -- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2011-08-22 1.0 kgf Created ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use work.sha3_pkg.all; use work.sha3_blake_package.all; use work.simulstuff.all; use std.textio.all; ------------------------------------------------------------------------------- entity gmu_blake_tb is end gmu_blake_tb; ------------------------------------------------------------------------------- architecture test of gmu_blake_tb is component gmu_blake_top port ( ClkxCI : in std_logic; RstxRBI : in std_logic; ScanInxTI : in std_logic; ScanOutxTO : out std_logic; ScanEnxTI : in std_logic; InEnxSI : in std_logic; FinBlockxSI : in std_logic; DataxDI : in std_logic_vector(511 downto 0); MsgLenxDI : in std_logic_vector(63 downto 0); OutEnxSO : out std_logic; PenUltCyclexSO : out std_logic; DataxDO : out std_logic_vector(255 downto 0)); end component; -- component ports signal ClkxC : std_logic; signal RstxRB : std_logic; signal FinBlockxS : std_logic; signal InWrEnxS : std_logic; signal OutWrEnxS : std_logic; signal PenUltCyclexS : std_logic; signal DataInxD : std_logic_vector(511 downto 0); signal DigestxD : std_logic_vector(255 downto 0); signal ExpRespxD : std_logic_vector(255 downto 0); signal MsgLenxD : std_logic_vector(63 downto 0); -- clock signal Clk : std_logic := '1'; signal ScanInxT : std_logic := '0'; -- No scan for this version signal ScanEnxT : std_logic := '0'; -- No scan for this version signal ScanOutxT: std_logic; type stimulirecordtype is record DataInxD : std_logic_vector(511 downto 0); FinBlockxS : std_logic; MsgLenxD : std_logic_vector(63 downto 0); DigestxD : std_logic_vector(255 downto 0); end record; signal STIMULI: stimulirecordtype; -- record of stimuli -- declarations of signals that do help coordinate testbench processes signal SIMPROGRESS : ResolveTrafficLight trafficlight := orange; -- timing of clock and simulation events constant clkphasehigh: time:= 10 ns; constant clkphaselow: time:= 10 ns; constant responseacquisitiontime: time:= 15 ns; constant stimulusapplicationtime: time:= 5 ns; constant resetactivetime: time:= 5 ns; -- declaration of stimuli, expected responses, and simulation report files file stimulifile : text; constant stimulifilename : string := "../simvectors/testvectors.txt"; ---- declaration of non-universal i.e. MUT-dependent subprograms -- purpose: get one record worth of stimuli from file. impure function GetStimuliRecord (file stimulifile : text) return stimulirecordtype is variable read_ok : boolean; variable in_line, in_line_tmp : line; -- stimuli to default to unknown in case no value is obtained from file variable stimulirecord : stimulirecordtype := ( DataInxD => (others => '0'), FinBlockxS => '0', MsgLenxD => (others => '0'), DigestxD => (others => '-') ); begin -- read a line from the stimuli file -- skipping any empty and comment lines encountered loop readline(stimulifile,in_line); -- copy line read to enable meaningful error messages later in_line_tmp := new string'(in_line(in_line'low to in_line'high)); if in_line_tmp'length >= 1 then exit when in_line_tmp(1) /= '%'; end if; deallocate(in_line_tmp); end loop; -- extract all values of a record of stimuli GetFileEntry (stimulirecord.DataInxD,in_line,in_line_tmp,stimulifilename); GetFileEntry (stimulirecord.FinBlockxS,in_line,in_line_tmp,stimulifilename); GetFileEntry (stimulirecord.MsgLenxD,in_line,in_line_tmp,stimulifilename); GetFileEntry (stimulirecord.DigestxD,in_line,in_line_tmp,stimulifilename); -- deallocate line copy now that all entries have been read deallocate(in_line_tmp); return stimulirecord; end GetStimuliRecord; -- purpose: compose a failure message line and write it to the report file. procedure PutSimulationReportFailure (ActualDigestxD : in std_logic_vector(255 downto 0); ExpectedDigestxD : in std_logic_vector(255 downto 0); respmatch : in respmatchtype) is variable out_line : line; begin report "Error Encountered " severity warning; write(out_line,string'("ERROR at ")); write(out_line,now); writeline(output,out_line); -- add expected responses write(out_line,string'(" Received = ")); vector2hex(out_line,ActualDigestxD); writeline(output,out_line); write(out_line,string'(" Expected = ")); vector2hex(out_line,ExpectedDigestxD); writeline(output,out_line); end PutSimulationReportFailure; begin -- test -- component instantiation DUT: gmu_blake_top port map ( ClkxCI => ClkxC, RstxRBI => RstxRB, ScanEnxTI => ScanEnxT, ScanInxTI => ScanInxT, ScanOutxTO => ScanOutxT, InEnxSI => InWrEnxS, FinBlockxSI => FinBlockxS, DataxDI => DataInxD, MsgLenxDI => MsgLenxD, OutEnxSO => OutWrEnxS, PenUltCyclexSO => PenUltCyclexS, DataxDO => DigestxD); -- clock generation Tb_clkgen : process begin case SIMPROGRESS is -- if orange then wait for start sign when orange => wait until SIMPROGRESS=green; -- if green then proceed with yet another clock period when green => null; when green2 => null; -- if yellow (neither red nor any other color should occur here) -- then terminate when others => SIMPROGRESS <= red; wait; -- forever end case; CLKxC <= '1'; wait for clkphasehigh; CLKxC <= '0'; wait for clkphaselow; end process Tb_clkgen; -- launch and terminate simulation run ---------------------------------------------------------------------------- Tb_launchterm : process variable status: file_open_status; begin -- open files for stimuli, config, and simulation report file_open(status,stimulifile,stimulifilename,read_mode); assert status=open_ok report FileOpenMessage(stimulifilename,status) severity failure; -- give start sign to other processes SIMPROGRESS <= green; -- suspend until clock generator shuts down wait until SIMPROGRESS=red; report "Simulation run completed, all stimuli processed." severity note; -- close files file_close(stimulifile); wait; -- forever to starve event queue end process Tb_launchterm; -- obtain stimulus and apply it to MUT ---------------------------------------------------------------------------- Tb_stimappli : process -- variables for accounting of mismatching responses variable respmatch : respmatchtype; variable respaccount : respaccounttype := (0,0,0,0,0); variable exprespavail : boolean := true; begin -- wait for start sign wait until SIMPROGRESS=green; -- default values RstxRB <= '0'; -- Resets Active FinBlockxS <= '0'; MsgLenxD <= (others => '0'); InWrEnxS <= '0'; -- No enable yet DataInxD <= ( others => '0'); -- all zeroes per default '); -- initially no expectation wait for resetactivetime; -- Wait until reset is over RstxRB <= '1'; -- take reset back ------------------------------------------------------------------------------- -- Initial Vector ------------------------------------------------------------------------------- wait until CLKxC'event and CLKxC='1'; STIMULI <= GetStimuliRecord(stimulifile); wait for stimulusapplicationtime; -- wait until the right time InWrEnxS <= '1'; DataInxD <= STIMULI.DataInxD; FinBlockxS <= STIMULI.FinBlockxS; -- delay no more needed.. -- modified for blake the words needs to be swapped per definition -- MsgLenxD MsgLenxD; MsgLenxD(31 downto 0) <= STIMULI.MsgLenxD (63 downto 32); MsgLenxD(63 downto 32) <= STIMULI.MsgLenxD (31 downto 0); wait until ClkxC'event and ClkxC='1'; -- make sure data is clocked in ------------------------------------------------------------------------------- -- Start Loop ------------------------------------------------------------------------------- -- process until we run out of stimuli appli_loop : while not (endfile(stimulifile)) loop wait for stimulusapplicationtime; InWrEnxS <= '0'; -- no longer needed FinBlockxS <= '0'; -- should be sampled MsgLenxD <= (others => '0'); ExpRespxD <= STIMULI.DigestxD; -- we need a slight delay here -- wait the cycles until the PenUltCyclexS arrives -- This is the penultimate cycle. Everything will be clear after this done_loop : while PenUltCyclexS = '0' loop wait until ClkxC'event and ClkxC='1'; wait for responseacquisitiontime; end loop done_loop; -- now we have donexS STIMULI <= GetStimuliRecord(stimulifile); -- read a new value wait until ClkxC'event and ClkxC='1'; wait for stimulusapplicationtime; InWrEnxS <= '1'; -- new data is here DataInxD <= STIMULI.DataInxD; -- apply new data; FinBlockxS <= STIMULI.FinBlockxS; -- apply new FinBlockxS -- modified for blake the words needs to be swapped per definition -- MsgLenxD MsgLenxD; MsgLenxD(31 downto 0) <= STIMULI.MsgLenxD (63 downto 32); MsgLenxD(63 downto 32) <= STIMULI.MsgLenxD (31 downto 0); -- note that the expected response and FinBlockxS will be updated in the -- next cycle. The last values are still used in this cycle wait until CLKxC'event and CLKxC='1'; -- loop until all stimuli have been processed end loop appli_loop; ------------------------------------------------------------------------------- -- Final Vector We applied the last vector, let us wait for the result ------------------------------------------------------------------------------- -- read the last one as well wait for stimulusapplicationtime; InWrEnxS <= '0'; -- no longer needed FinBlockxS <= '0'; -- should be sampled MsgLenxD <= (others => '0'); ExpRespxD <= STIMULI.DigestxD; -- we need a slight delay here -- wait the cycles until the PenUltCyclexS arrives -- This is the penultimate cycle. Everything will be clear after this last_loop : while PenUltCyclexS = '0' loop wait until ClkxC'event and ClkxC='1'; wait for responseacquisitiontime; end loop last_loop; wait until CLKxC'event and CLKxC='1'; -- now we are done ------------------------------------------------------------------------------- SIMPROGRESS <= red; wait; end process Tb_stimappli; ------------------------------------------------------------------------------- -- Check for output responses only ------------------------------------------------------------------------------- tb_respcheck: process -- variables for accounting of mismatching responses variable respmatch : respmatchtype; variable respaccount : respaccounttype := (0,0,0,0,0); variable out_line : line; begin -- process tb_respcheck -- wait for start sign wait until SIMPROGRESS=green; while SIMPROGRESS = green loop wait until CLKxC'event and CLKxC='1'; wait for responseacquisitiontime; if OutWrEnxS = '1' then -- we have a comparison value CheckResponse(DigestxD,ExpRespxD,respmatch,respaccount); if respmatch /= mok then -- is there a mismatch ?? PutSimulationReportFailure(DigestxD,ExpRespxD,respmatch); else write(out_line,string'(" -> Matching result at ")); write(out_line,now); writeline(output,out_line); end if; end if; end loop; -- sim green PutSimulationReportSummary(respaccount); wait; -- kill the queue end process tb_respcheck; end test;