---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2006
--
-- Filename: SimCtrl006.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card FPGAs
--
-- Design Description:
-- Simulation Control file (006) for Digitiser card testbench - with sequence table
-- based on 004 but using interrupts
---------------------------------------------------------------------------


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;
       Trigger      : in std_ulogic;
       Ack          : out std_ulogic);
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 cPerTriggerCtrl: integer := 16#00500404#;
  constant cPerPulseGen:    integer := 16#00500408#;
  constant cPerAScanCtrl:   integer := 16#00500410#;

  constant cGateStartStop:  integer := 16#00500438#;
  constant cGateAttributes: integer := 16#0050043C#;
  constant cGateSetup:      integer := 16#00500440#;

  constant cPerSequenceStep: integer := 16#0050045C#;
  constant cPerSequenceCtrl: integer := 16#00500460#;

  constant cDspRectMode:        integer := 16#00500250#;
  constant cDspSramCtrl:        integer := 16#00500258#;
  constant cDspSramCtrlNoScans: integer := 16#0050026C#;

  constant cDspSequenceStep: integer := 16#00500274#;
  constant cDspSequenceCtrl: integer := 16#00500278#;

  -- 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
  
  PRx: process
  begin
    Ack <= '0';
    wait until rising_edge(Trigger);
    wait for 15 us;
    Ack <= '1';
    wait for 100 ns;
  end process prx;

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

    -- Trigger from Rapidaq for sequence mode
    ToAdcModel.IntTrigger <= '1';

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

    -- Write description of test to output
    write (vLine, string'("Testbench: Doing shortened FPGA configuration to reduce simulation time"));
    writeline (OUTPUT, vLine);

    -- Program the FPGAs - actually skip full configuration simulation
    LBusWrite(cSysSramBase, 16#DEADBEEF#, ToBusModel, FromBusModel);
    LBusWrite(cSysCommandReg, 16#00000011#, ToBusModel, FromBusModel);

    -- Try to access the check register, should be delayed until 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: Shortened FPGA configuration complete"));
      writeline (OUTPUT, vLine);
    end if;

    -- Setup values for the trigger delay and pulse width
    LBusWrite(cPerSequenceStep, 16#00000000#, ToBusModel, FromBusModel);
    LBusWrite(cPerTriggerCtrl, 16#00000000#, ToBusModel, FromBusModel);
    LBusWrite(cPerPulseGen, 16#00000040#, ToBusModel, FromBusModel);

    LBusWrite(cPerSequenceStep, 16#00000001#, ToBusModel, FromBusModel);
    LBusWrite(cPerTriggerCtrl, 16#00000000#, ToBusModel, FromBusModel);
    LBusWrite(cPerPulseGen, 16#00000040#, ToBusModel, FromBusModel);

    -- Setup values for the number of samples & trigger width
    LBusWrite(cDspSequenceStep, 16#00000000#, ToBusModel, FromBusModel);
    LBusWrite(cDspSramCtrl, 16#0000019F#, ToBusModel, FromBusModel);
    LBusWrite(cDspRectMode, 16#00000000#, ToBusModel, FromBusModel);

    LBusWrite(cDspSequenceStep, 16#00000001#, ToBusModel, FromBusModel);
    LBusWrite(cDspSramCtrl, 16#0000019F#, ToBusModel, FromBusModel);
    LBusWrite(cDspRectMode, 16#00000000#, ToBusModel, FromBusModel);

    -- Setup rep-rate
    LBusWrite(cPerAScanCtrl, 16#000000F0#, ToBusModel, FromBusModel);

    write (vLine, string'("Testbench: Test 1 (Gate 1) - +Ve Threshold - Leading Flank - Test pattern 0"));
    writeline (OUTPUT, vLine);
    write (vLine, string'("Testbench: Test 1 (Gate 1) - Detecting Distance of 1st peak"));
    writeline (OUTPUT, vLine);
    write (vLine, string'("Testbench: Test 1 (Gate 2) - +Ve threshold - leading flank - relative to gate 1"));
    writeline (OUTPUT, vLine);
    write (vLine, string'("Testbench: Test 1 (Gate 2) - Detecting Distance of 1st peak"));
    writeline (OUTPUT, vLine);

    -- Setup values for Interface Gate start/stop + attributes
    LBusWrite(cPerSequenceStep, 16#00000000#, ToBusModel, FromBusModel);
    LBusWrite(cGateStartStop, 16#02C00000#, ToBusModel, FromBusModel);
    LBusWrite(cGateAttributes, 16#0090012E#, ToBusModel, FromBusModel);

    LBusWrite(cPerSequenceStep, 16#00000001#, ToBusModel, FromBusModel);
    LBusWrite(cGateStartStop, 16#02C00000#, ToBusModel, FromBusModel);
    LBusWrite(cGateAttributes, 16#0090012E#, ToBusModel, FromBusModel);
    LBusWrite(cGateSetup, 16#00000000#, ToBusModel, FromBusModel);
    vRData := 16#80000000#;
    while vRData /= 16#00000000# loop
      LBusRead(cGateSetup, vRData, ToBusModel, FromBusModel);
    end loop;

    -- Setup values for Gate 1 start/stop + attributes
    -- Set up as interface gate but distance of peak 1
    LBusWrite(cPerSequenceStep, 16#00000000#, ToBusModel, FromBusModel);
    LBusWrite(cGateStartStop, 16#02C00000#, ToBusModel, FromBusModel);
    LBusWrite(cGateAttributes, 16#1094F12E#, ToBusModel, FromBusModel);

    LBusWrite(cPerSequenceStep, 16#00000001#, ToBusModel, FromBusModel);
    LBusWrite(cGateStartStop, 16#02C00000#, ToBusModel, FromBusModel);
    LBusWrite(cGateAttributes, 16#1094F12E#, ToBusModel, FromBusModel);
    LBusWrite(cGateSetup, 16#00000001#, ToBusModel, FromBusModel);
    vRData := 16#80000001#;
    while vRData /= 16#00000001# loop
      LBusRead(cGateSetup, vRData, ToBusModel, FromBusModel);
    end loop;

    -- Setup values for Gate 2 start/stop + attributes
    -- Set up relative to Gate 1 but distance of peak 0
    LBusWrite(cPerSequenceStep, 16#00000000#, ToBusModel, FromBusModel);
    LBusWrite(cGateStartStop, 16#02C00000#, ToBusModel, FromBusModel);
    LBusWrite(cGateAttributes, 16#0094112E#, ToBusModel, FromBusModel);

    LBusWrite(cPerSequenceStep, 16#00000001#, ToBusModel, FromBusModel);
    LBusWrite(cGateStartStop, 16#02C00000#, ToBusModel, FromBusModel);
    LBusWrite(cGateAttributes, 16#0094112E#, ToBusModel, FromBusModel);
    LBusWrite(cGateSetup, 16#00000002#, ToBusModel, FromBusModel);
    vRData := 16#80000000#;
    while vRData /= 16#00000002# loop
      LBusRead(cGateSetup, vRData, ToBusModel, FromBusModel);
    end loop;

    -- Setup the No of Scans control register
    -- Multiple A-Scan + Multiple C-Scan - 2 sequences
    LBusWrite(cDspSramCtrlNoScans, 16#90000101#, ToBusModel, FromBusModel);

    -- Set Sequence length = 2
    LBusWrite(cDspSequenceCtrl, 16#00000001#, ToBusModel, FromBusModel);

    wait for 2 us;

    -- Start the scan data (send 4 A-Scans)
    AdcSendPattern(0, 4, ToAdcModel, FromAdcModel);

    -- Set Sequence length = 2 and start sequence
    LBusWrite(cPerSequenceCtrl, 16#80000001#, ToBusModel, FromBusModel);

    -- Wait for interrupt
    wait until falling_edge(FromBusModel.nInt);

    -- Check the correct C-Scan data has arrived
    LBusRead(16#00300000#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#43534E00# then
      write (vLine, string'("Testbench: Error - Expected 0x43534E00 from Sample SRAM (C-Scan 0 header)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusRead(16#00300004#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#B1F40070# then
      write (vLine, string'("Testbench: Error - Expected 0xB1F40070 from Sample SRAM (Gate 0 result)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusRead(16#00300008#, vRData, ToBusModel, FromBusModel);
      if vRData /= 16#B1F40138# then
        write (vLine, string'("Testbench: Error - Expected 0x1F4C0138 from Sample SRAM (Gate 1 result)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusRead(16#0030000C#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#B1900200# then
      write (vLine, string'("Testbench: Error - Expected 0xB1900200 from Sample SRAM (Gate 2 result)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    -- Check the correct C-Scan data has arrived for second step
    LBusRead(16#00300010#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#43534E01# then
      write (vLine, string'("Testbench: Error - Expected 0x43534E01 from Sample SRAM (C-Scan 1 header)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusRead(16#00300014#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#B1F4006F# then
      write (vLine, string'("Testbench: Error - Expected 0xB1F4006F from Sample SRAM (Gate 0 result)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusRead(16#00300018#, vRData, ToBusModel, FromBusModel);
      if vRData /= 16#B1F40137# then
        write (vLine, string'("Testbench: Error - Expected 0x1F4C0137 from Sample SRAM (Gate 1 result)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

    LBusRead(16#0030001C#, vRData, ToBusModel, FromBusModel);
    if vRData /= 16#B19001FF# then
      write (vLine, string'("Testbench: Error - Expected 0xB19001FF from Sample SRAM (Gate 2 result)"));
      writeline (OUTPUT, vLine);
      vTestFail := true;
    end if;

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

    wait;

  end process main;


end architecture Test;