---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: SimCtrl001.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card FPGAs
--
-- Design Description:
--Simulation Control file (001) for Digitiser 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;
use work.AdcModelPkg.all;


entity SimCtrl is
  port(ToBusModel   : out tToBusModel;
       FromBusModel : in tFromBusModel;
       ToAdcModel   : out tToAdcModel;
       FromAdcModel : in tFromAdcModel);
end entity SimCtrl;


architecture Test of SimCtrl is

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

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

  -- Define the base of the sample SRAM
  constant cSampleSramBase:   integer := 16#00000000#;


begin

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

  begin

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

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

    -- Write description of test to output
    write (vLine, string'("Testbench: Testing System Check Register"));
    writeline (OUTPUT, vLine);

    LBusRead(cSysCheckReg, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#FFFFFFFF# then
      write (vLine, string'("Testbench: Error - Expected 0xFFFFFFFF from System Check register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusWrite(cSysCheckReg, 16#5555AAAA#, ToBusModel, FromBusModel);
    LBusRead(cSysCheckReg, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#AAAA5555# then
      write (vLine, string'("Testbench: Error - Expected 0xAAAA5555 from System Check register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusWrite(cSysCheckReg, 16#00000001#, ToBusModel, FromBusModel);
    LBusRead(cSysStatusReg, vRData, ToBusModel, FromBusModel);
    LBusRead(cSysCheckReg, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#FFFFFFFE# then
      write (vLine, string'("Testbench: Error - Expected 0xFFFFFFFE from System Check register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    write (vLine, string'("Testbench: System Check Register tests complete"));
    writeline (OUTPUT, vLine);

    -- Write description of test to output
    write (vLine, string'("Testbench: Testing Out of range count register"));
    writeline (OUTPUT, vLine);

    -- test out of range count register
    LBusRead(cSysOorCountReg, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#00000000# then
      write (vLine, string'("Testbench: Error - Expected 0x0000000 from Out of range count register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    -- read from invalid address
    LBusRead(16#00700000#, vRData, ToBusModel, FromBusModel);

    LBusRead(cSysOorCountReg, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#00000001# then
      write (vLine, string'("Testbench: Error - Expected 0x0000001 from Out Of range count register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusWrite(cSysCommandReg, 16#00000200#, ToBusModel, FromBusModel);
    LBusRead(cSysOorCountReg, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#00000000# then
      write (vLine, string'("Testbench: Error - Expected 0x0000000 from Out of range count register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    write (vLine, string'("Testbench: Out of range count register tests complete"));
    writeline (OUTPUT, vLine);

    -- Write description of test to output
    write (vLine, string'("Testbench: Testing Accesses to System SRAM"));
    writeline (OUTPUT, vLine);

    -- Write  a test pattern to the Syatem SRAM
    for Offset in 0 to 16#50# loop
      vWData := 16#FFFFFFFF# - Offset;
      LBusWrite(cSysSramBase + (Offset*4), vWData, ToBusModel, FromBusModel);
    end loop;

    for Offset in 0 to 16#50# loop
      LBusRead(cSysSramBase + (Offset*4), vRData, ToBusModel, FromBusModel);
      if vRData /= 16#FFFFFFFF# - Offset then
        write (vLine, string'("Testbench: Error - Unexpected data read from System SRAM"));
        writeline (OUTPUT, vLine);
        vTestFail := true;
      end if;
    end loop;

    -- Test burst write and read from System SRAM
    vBurstData(1) := 16#01010101#;
    vBurstData(2) := 16#02020202#;
    vBurstData(3) := 16#03030303#;
    vBurstData(4) := 16#04040404#;
    vBurstData(5) := 16#05050505#;
    vBurstData(6) := 16#06060606#;
    vBurstData(7) := 16#07070707#;
    vBurstData(8) := 16#08080808#;

    LBusBurstWrite(cSysSramBase, vBurstData, 8, ToBusModel, FromBusModel);
    LBusBurstRead(cSysSramBase, vReadBurstData, 8, ToBusModel, FromBusModel);

    for Count in 1 to 8 loop
      if vReadBurstData(Count) /= vBurstData(Count) then
        write (vLine, string'("Testbench: Error - Unexpected data read from System SRAM (Burst access)"));
        writeline (OUTPUT, vLine);
        vTestFail := true;
      end if;
    end loop;

    write (vLine, string'("Testbench: System SRAM access tests complete"));
    writeline (OUTPUT, vLine);

    LBusRead(16#00500004#, vRData, ToBusModel, FromBusModel);

    LBusWrite(cSysCheckReg, 16#DEADBEEF#, ToBusModel, FromBusModel);
    LBusRead(cSysCheckReg, vRData, ToBusModel, FromBusModel);

    -- Write to the System EEPROM Buffer
    LBusWrite(16#00600004#, 16#01234567#, ToBusModel, FromBusModel);

    wait for 100 ns;
    LBusRead(16#00600004#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#01234567# then
        write (vLine, string'("Testbench: Error - Unexpected data read from EEPROM Block RAM"));
        writeline (OUTPUT, vLine);
        vTestFail := true;
    end if;

    wait for 100 ns;
    LBusBurstWrite(16#00600000#, vBurstData, 8, ToBusModel, FromBusModel);

    wait for 100 ns;
    LBusBurstRead(16#00600000#, vReadBurstData, 8, ToBusModel, FromBusModel);


    for Count in 1 to 8 loop
      if vBurstData(Count) /= vReadBurstData(Count) then
        write (vLine, string'("Testbench: Error - Unexpected data read from EEPROM Block RAM"));
        writeline (OUTPUT, vLine);
        write (vLine, vReadBurstData(Count));
        vTestFail := true;
        writeline (OUTPUT, vLine);
      end if;
    end loop;

    wait for 100 ns;
    -- Load data from EEPROM to EEPROM Block RAM Buffer
    write (vLine, string'("Testbench: Testing EEPROM to EEPROM Block RAM Buffer operation"));
    writeline (OUTPUT, vLine);
    LBusWrite(cSysCommandReg, 16#00000014#, ToBusModel, FromBusModel);

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

    wait for 300 ns;
    LBusRead(16#00600000#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#12345678# then
      write (vLine, string'("Testbench: Error - Expected 0x12345678 from EEPROM Block RAM Buffer"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusRead(16#00600004#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#DEADBEEF# then
      write (vLine, string'("Testbench: Error - Expected 0xDEADBEEF from EEPROM Block RAM Buffer"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusRead(16#00600008#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#FEEDB00B# then
      write (vLine, string'("Testbench: Error - Expected 0xFEEDBOOB from EEPROM Block RAM Buffer"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusRead(16#0060000C#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#FEDCBA98# then
      write (vLine, string'("Testbench: Error - Expected 0xFEDCBA98 from EEPROM Block RAM Buffer"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    wait for 300 ns;

    -- Save data in EEPROM Block RAM Buffer to EEPROM
    write (vLine, string'("Testbench: Testing EEPROM Block RAM Buffer to EEPROM operation"));
    writeline (OUTPUT, vLine);
    LBusWrite(cSysCommandReg, 16#00000012#, ToBusModel, FromBusModel);

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

    wait for 100 ns;

    -- Program the FPGAs (or at least write the correct number of bytes
    write (vLine, string'("Testbench: FPGA configuration test (this will take over 7 ms)"));
    writeline (OUTPUT, vLine);

    -- Write dummy config data to System SRAM (checked by testbench)
    for Count in 0 to 9 loop  -- First 10 config values for DSP FPGA
      vWData := Count;
      LBusWrite(cSysSramBase + Count*4, vWData, ToBusModel, FromBusModel);
    end loop;
    for Count in 166970 to 166979 loop  -- Last 10 config values for DSP FPGA
      vWData := Count - 166900;
      LBusWrite(cSysSramBase + Count*4, vWData, ToBusModel, FromBusModel);
    end loop;
    for Count in 0 to 9 loop  -- First 10 config values for Peripheral FPGA
      vWData := Count;
      LBusWrite(cSysSramBase + 166980*4 + Count*4, vWData, ToBusModel, FromBusModel);
    end loop;
    for Count in 69890 to 69899 loop  -- Last 10 config values for Peripheral FPGA
      vWData := Count - 69800;
      LBusWrite(cSysSramBase + 166980*4 + Count*4, vWData, ToBusModel, FromBusModel);
    end loop;

    -- Start the FPGA programming sequence
    LBusWrite(cSysCommandReg, 16#00000011#, ToBusModel, FromBusModel);

    -- Try to access the check register, should be delayed untill FPGAs have been configured
    LBusWrite(cSysCheckReg, 16#01234567#, ToBusModel, FromBusModel);
    LBusRead(cSysCheckReg, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#FEDCBA98# then
      write (vLine, string'("Testbench: Error - Expected 0xFEDCBA98 from System Check register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    else
      write (vLine, string'("Testbench: System Check register worked after FPGA configuration complete"));
      writeline (OUTPUT, vLine);
    end if;

    write (vLine, string'("Testbench: FPGA configuration test complete"));
    writeline (OUTPUT, vLine);

    wait for 100 ns;

    -- Test register accesses to DSP FPGA
    LBusRead(16#00500258#, vRData, ToBusModel, FromBusModel);
    LBusWrite(16#00500258#, 16#FFFFFFFF#, ToBusModel, FromBusModel);
    LBusRead(16#00500258#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#000F7FFF# then
      write (vLine, string'("Testbench: Error - Expected 0x000F7FFF from DSP FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    wait for 100 ns;

    -- Test register accesses to Peripheral FPGA
    LBusRead(16#00500400#, vRData, ToBusModel, FromBusModel);
    LBusRead(16#00500404#, vRData, ToBusModel, FromBusModel);
    LBusWrite(16#00500400#, 16#FFFFFFFF#, ToBusModel, FromBusModel);
    LBusRead(16#00500400#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#01FCFFFF# then
      write (vLine, string'("Testbench: Error - Expected 0x01FCFFFF from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusRead(16#00500404#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#00010000# then
      write (vLine, string'("Testbench: Error - Expected 0x00010000 from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    -- Test Peripheral FPGA gpio
    LBusRead(16#00500448#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#00000000# then
      write (vLine, string'("Testbench: Error - Expected 0x00000000 from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusWrite(16#00500448#, 16#FFFFFFFF#, ToBusModel, FromBusModel);
    LBusRead(16#00500448#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#FFFFFFFC# then
      write (vLine, string'("Testbench: Error - Expected 0xFFFFFFFC from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusWrite(16#00500444#, 16#AAAAAAAA#, ToBusModel, FromBusModel);
    LBusRead(16#00500444#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#AAAAAAA8# then
      write (vLine, string'("Testbench: Error - Expected 0xAAAAAAA8 from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusWrite(16#00500444#, 16#55555555#, ToBusModel, FromBusModel);
    LBusRead(16#00500444#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#55555554# then
      write (vLine, string'("Testbench: Error - Expected 0x55555554 from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusRead(16#00500468#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#00000000# then
      write (vLine, string'("Testbench: Error - Expected 0x00000000 from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusWrite(16#00500468#, 16#FFFFFFFF#, ToBusModel, FromBusModel);
    LBusRead(16#00500468#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#7FFFFFFF# then
      write (vLine, string'("Testbench: Error - Expected 0x7FFFFFFF from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusWrite(16#00500464#, 16#AAAAAAAA#, ToBusModel, FromBusModel);
    LBusRead(16#00500464#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#2AAAAAAA# then
      write (vLine, string'("Testbench: Error - Expected 0x2AAAAAAA from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;
    LBusWrite(16#00500464#, 16#55555555#, ToBusModel, FromBusModel);
    LBusRead(16#00500464#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#55555555# then
      write (vLine, string'("Testbench: Error - Expected 0x55555555 from Peripheral FPGA register"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

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

    wait;

  end process main;


end architecture Test;