------------------------------------------------------------
-- Copyright: 2011 Integrated Sytems Laboratory, ETH Zurich
--            http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
-------------------------------------------------------------------------------
-- Title      : Testbench for design "Sha256
-- Project    : 
-------------------------------------------------------------------------------
-- File       : ethz_sha2_tb.vhd
-- Author     : Christoph Keller  
-- Company    : Integrated Systems Laboratory, ETH Zurich
-- Created    : 2011-08-12
-- Last update: 2011-09-10
-- Platform   : ModelSim (simulation), Synopsys (synthesis)
-- Standard   : VHDL'87
-------------------------------------------------------------------------------
-- Description: 
-------------------------------------------------------------------------------
-- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2011-08-12  1.0      chrikell        Created
-- 2011-08-25  1.01     kgf      Changed entity name
-- 2011-09-10  1.02     kgf      Changed name of the Reset to RstxRBI
-------------------------------------------------------------------------------



library ieee;
use ieee.std_logic_1164.all;
use work.shapkg.all;
use work.simulstuff.all;
use std.textio.all;

-------------------------------------------------------------------------------

entity ethz_sha2_tb is

end ethz_sha2_tb;

-------------------------------------------------------------------------------

architecture test of ethz_sha2_tb is


  component ethz_sha2
    port (
      ClkxCI         : in  std_logic;
      RstxRBI        : in  std_logic;
      FinBlockxSI    : in  std_logic;
      InWrEnxSI      : in  std_logic;
      PenUltCyclexSO : out std_logic;
      OutWrEnxSO     : out std_logic;
      TextInxDI      : in  std_logic_vector(511 downto 0);
      HOutxDO        : out std_logic_vector(255 downto 0);
      ScanInxTI      : in  std_logic;
      ScanEnxTI      : in  std_logic;
      ScanOutxTO     : out std_logic);
  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(HWIDTH-1 downto 0);
  signal ExpRespxD     : std_logic_vector(255 downto 0);
  signal ScanInxT      : std_logic := '0';  -- No scan for this version
  signal ScanEnxT      : std_logic := '0';  -- No scan for this version
  signal ScanOutxT     : std_logic;


  -- clock
  signal Clk : std_logic := '1';



  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 : ethz_sha2
    port map (
      CLKxCI         => CLKxC,
      RstxRBI        => RstxRB,
      FinBlockxSI    => FinBlockxS,
      InWrEnxSI      => InWrEnxS,
      PenUltCyclexSO => PenUltCyclexS,
      OutWrEnxSO     => OutWrEnxS,
      TextInxDI      => DataInxD,
      HOutxDO        => DigestxD,
      ScanInxTI      => ScanInxT,
      ScanEnxTI      => ScanEnxT,
      ScanOutxTO     => ScanOutxT);     -- component instantiation

  ScanInxT <= '0';
  ScanEnxT <= '0';

  -- 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;
    variable out_line     : line;

  begin
    -- wait for start sign
    wait until SIMPROGRESS = green;

    -- default values
    RstxRB     <= '0';                  -- Resets Active
    FinBlockxS <= '0';
    InWrEnxS   <= '0';                  -- No enbable yet
    DataInxD   <= (others => '0');      -- all zeroes per default
    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;

    wait until ClkxC'event and ClkxC = '1';  -- make sure data is clocked in

    -- process until we run out of stimuli
    appli_loop : while not (endfile(stimulifile)) loop
      wait for stimulusapplicationtime;
      InWrEnxS   <= '0';                -- no longer needed
      FinBlockxS <= '0';

      -- wait the cycles until the PenUltCyclexS arrives
      -- This is the penultimate cycle. Everything will be clear after this
      wait until ClkxC'event and ClkxC = '1';  -- make sure data is clocked in


      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

      -- note that the expected response and FinBlockxS will be updated in the
      -- next cycle. The last values are still used in this cycle

      -- see if we have an output to compare already    

      wait until ClkxC'event and ClkxC = '1';
      wait for stimulusapplicationtime;
      InWrEnxS   <= '1';                -- new data is here
      FinBlockxS <= STIMULI.FinBlockxS;
      DataInxD   <= STIMULI.DataInxD;   -- apply new data;

      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

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

    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;

    wait until CLKxC'event and CLKxC = '1';
    wait until CLKxC'event and CLKxC = '1';
    wait for stimulusapplicationtime;

    ExpRespxD <= STIMULI.DigestxD;      -- initial value 


    while SIMPROGRESS = green loop
      wait until CLKxC'event and CLKxC = '1';
      wait for responseacquisitiontime;

      if PenUltCyclexS = '1' then
        ExpRespxD <= STIMULI.DigestxD;  -- also for this guy
      end if;

      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);
          write(out_line, string'("   Received = "));
          vector2hex(out_line, DigestxD);
          writeline(output, out_line);
          write(out_line, string'("   Expected = "));
          vector2hex(out_line, ExpRespxD);
          writeline(output, out_line);
        end if;
        -- change the expresp after the out wren,
        -- assumes that InwrEn is already there
        
      end if;

    end loop;  -- sim green
    PutSimulationReportSummary(respaccount);


    wait;                               -- kill the queue
    
  end process tb_respcheck;

  

end test;


Generated on Tue Nov 22 15:16:34 CET 2011
Home