---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2005
--
-- Filename: SimCtrl004.vhd
-- Language: VHDL '93
-- Project:  Pulse Receive Card FPGAs
--
-- Design Description:
-- Simulation Control file (004) for pulse receive card testbench
---------------------------------------------------------------------------


library IEEE;
use IEEE.Std_Logic_1164.all;
use IEEE.Std_Logic_Arith.all;
use std.textio.all;

library work;
use work.LocalBusModelPkg.all;


architecture Test of SimCtrl is

  -- Define some system register addresses
  constant cSysCommandReg:       integer := 16#00500014#;
  constant cSysStatusReg:        integer := 16#00500014#;

  -- Define the base of the system SRAM
  constant cSysSramBase:         integer := 16#00400000#;

  constant cSysGlobalConfigReg:  integer := 16#005000f0#;
  constant cSysSeqTableBase:     integer := 16#00700000#;

begin

  -- Main Simulation Control process
  Main: process
    variable vAddr: integer;
    variable vRData: integer;
    variable vWData: integer;
    variable vTestFail: boolean;
    variable vLine: Line;
    variable vDone: boolean;

  begin

    -- Initialise the test fail flag
    vTestFail := false;

    pHighVoltageOK <= '0';
    pTrigger <= '0';

    -- Initialise the Bus Model (bus clock = 33 MHz)
    BusInit(30 ns, ToBusModel, FromBusModel);

    write (vLine, string'("Testbench: Testing Sequence Table RAM Buffer operation"));
    writeline (OUTPUT, vLine);
    -- Write to the Sequence Table RAM Buffer
    vAddr := cSysSeqTableBase;
    for Count in 1 to 8 loop
      vWData := 16#01010101# * Count;
      LBusWrite(vAddr, vWData, ToBusModel, FromBusModel);
      vAddr := vAddr + 4;
    end loop;

    wait for 100 ns;
    vAddr := cSysSeqTableBase;

    for Count in 1 to 8 loop
      LBusRead(vAddr, vRData, ToBusModel, FromBusModel);
      if vRData /= (16#01010101# * Count) then
        write (vLine, string'("Testbench: Error - Unexpected data read from Sequence Table Block RAM"));
        writeline (OUTPUT, vLine);
        vTestFail := true;
      end if;
      vAddr := vAddr + 4;
    end loop;

    wait for 100 ns;
    -- set up some realistic values sequence table
    LBusWrite(cSysSeqTableBase,     16#80000001#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+1*4, 16#00000555#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+2*4, 16#02031020#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+3*4, 16#00000308#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+4*4, 16#00000033#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+5*4, 16#00000010#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+7*4, 1000, ToBusModel, FromBusModel);

    -- 2nd entry disabled
--    LBusWrite(cSysSeqTableBase+8*4, 16#00000000#, ToBusModel, FromBusModel);

    -- 2nd entry - with skip = 2
    LBusWrite(cSysSeqTableBase+8*4, 16#82000000#, ToBusModel, FromBusModel);
    -- also need to set reprate to small non-zero value
    LBusWrite(cSysSeqTableBase+15*4, 100, ToBusModel, FromBusModel);

    -- 3rd entry
    LBusWrite(cSysSeqTableBase+16*4, 16#80000002#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+17*4, 16#00000444#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+18*4, 16#02031020#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+19*4, 16#00000204#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+20*4, 16#00000022#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+21*4, 16#00000020#, ToBusModel, FromBusModel);
    LBusWrite(cSysSeqTableBase+23*4, 800, ToBusModel, FromBusModel);

    -- 4th entry disabled
    LBusWrite(cSysSeqTableBase+24*4, 16#00000000#, ToBusModel, FromBusModel);

    wait for 100 ns;

    write (vLine, string'("Testbench: Testing Skip operation"));
    writeline (OUTPUT, vLine);
    -- set Global configuration register
    LBusWrite(cSysGlobalConfigReg, 16#55018aaa#, ToBusModel, FromBusModel);

    -- send global configuration and sequence table over serial link to control FPGA
    LBusWrite(cSysCommandReg, 16#00000008#, ToBusModel, FromBusModel);

    wait for 100 us;

    vRData := 16#00000004#;
    while (conv_std_logic_vector(vRData, 32) and X"00000004") /= X"00000000" loop
      LBusRead(cSysStatusReg, vRData, ToBusModel, FromBusModel);
      wait for 100 us;
    end loop;

    wait for 100 ns;
    pTrigger <= '1';
    wait for 50 ns;
    pTrigger <= '0';

    wait for 20 us;
    -- check for Ack
    if (pAck'last_event < 9 us or pAck'last_event > 11 us) then
      write (vLine, string'("Testbench: Error - First entry Ack incorrect"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 100 ns;
    pTrigger <= '1';
    wait for 20 ns;
    if (pAck /= '1') then
      write (vLine, string'("Testbench: Error - Ack not driven by trigger during 1st skip"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    wait for 30 ns;
    pTrigger <= '0';
    wait for 20 ns;
    if (pAck /= '0') then
      write (vLine, string'("Testbench: Error - Ack not released after trigger during 1st skip"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 20 us;
    -- check for no Ack
    if (pAck'last_event < 20 us) then
      write (vLine, string'("Testbench: Error - unexpected Ack during 1st skip"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 100 ns;
    pTrigger <= '1';
    wait for 20 ns;
    if (pAck /= '1') then
      write (vLine, string'("Testbench: Error - Ack not driven by trigger during 1st skip"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    wait for 30 ns;
    pTrigger <= '0';
    wait for 20 ns;
    if (pAck /= '0') then
      write (vLine, string'("Testbench: Error - Ack not released after trigger during 1st skip"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 20 us;
    -- check for no Ack
    if (pAck'last_event < 20 us) then
      write (vLine, string'("Testbench: Error - unexpected Ack during 2nd skip"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 100 ns;
    pTrigger <= '1';
    wait for 50 ns;
    pTrigger <= '0';

    wait for 20 us;
    -- check for Ack
    if (pAck'last_event < 11 us or pAck'last_event > 13 us) then
      write (vLine, string'("Testbench: Error - 3rd entry Ack incorrect"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 100 ns;
    pTrigger <= '1';
    wait for 50 ns;
    pTrigger <= '0';

    wait for 20 us;
    -- check for Ack
    if (pAck'last_event < 9 us or pAck'last_event > 11 us) then
      write (vLine, string'("Testbench: Error - First entry Ack (for 2nd time) incorrect"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 100 ns;

    -- Stop the simulation and report pass/fail
    if vTestFail then
      report "Testbench: Simulation 004 completed - FAIL"
      severity failure;
    else
      report "Testbench: Simulation 004 completed - PASS"
      severity failure;
    end if;

    wait;

  end process main;


end architecture Test;