------------------------------------------------------------
-- Copyright: 2011 George Mason University, Virginia USA
-- http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
-------------------------------------------------------------------------------
-- Title : SHA2 testbench
-- Project : Shabziger
-------------------------------------------------------------------------------
-- File : gmu_sha2_tb.vhd
-- Author : Frank K. Guerkaynak
-- Company : Integrated Systems Laboratory, ETH Zurich
-- Created : 2011-09-01
-- Last update: 2011-09-01
-- Platform : ModelSim (simulation), Synopsys (synthesis)
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Standard Testbench
-------------------------------------------------------------------------------
-- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-09-01 1.0 kgf Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.simulstuff.all;
use std.textio.all;
-------------------------------------------------------------------------------
entity gmu_sha2_tb is
end gmu_sha2_tb;
-------------------------------------------------------------------------------
architecture test of gmu_sha2_tb is
component gmu_sha2_top
port (
ClkxCI : in std_logic;
RstxRBI : in std_logic;
InWrEnxSI : in std_logic;
FinBlockxSI : in std_logic;
DataxDI : in std_logic_vector(511 downto 0);
ScanInxTI : in std_logic;
ScanEnxTI : in std_logic;
ScanOutxTO : out std_logic;
OutWrEnxSO : 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);
-- 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;
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',
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.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_sha2_top
port map (
ClkxCI => ClkxC,
RstxRBI => RstxRB,
InWrEnxSI => InWrEnxS,
FinBlockxSI => FinBlockxS,
DataxDI => DataInxD,
ScanInxTI => ScanInxT,
ScanEnxTI => ScanEnxT,
ScanOutxTO => ScanOutxT,
OutWrEnxSO => 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';
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..
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
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
-- 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
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';
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;