---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2005
--
-- Filename: Testbench.vhd
-- Language: VHDL '93
-- Project:  Pulse Receiver Card FPGAs
--
-- Design Description:
-- System testbench for the Pulse Receiver Card
---------------------------------------------------------------------------


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

library work;
use work.LocalBusModelPkg.all;


entity Testbench is
end entity testbench;


architecture Test of Testbench is

  -- Define the LocalBus Model component
  component LocalBusModel is
    port(-- Control signals to/from main simulation module
         ToBusModel  : in  tToBusModel;
         FromBusModel: out tFromBusModel;
         -- Bus Signals
         pnLRESET    : out   std_ulogic;
         pLCLKA      : out   std_ulogic;
         pLWnR       : out   std_ulogic;
         pnADS       : out   std_ulogic;
         pnBLAST     : out   std_ulogic;
         pnREADY     : in    std_ulogic;
         pLA         : inout std_logic_vector(31 downto 0);
         pLD         : inout std_logic_vector(31 downto 0);
         pLHOLD      : out   std_ulogic;
         pLHOLDA     : in    std_ulogic;
         pnBTERM     : in    std_ulogic;
         pnCCS       : in    std_ulogic;
         pBREQi      : in    std_ulogic);
  end component LocalBusModel;

  -- Define the Simulation Control Component
  component SimCtrl
    port(ToBusModel    : out tToBusModel;
         FromBusModel  : in  tFromBusModel;
         pHVCtrl       : in  std_logic_vector(11 downto 0);
         pTCGVal       : in  std_logic_vector(11 downto 0);
         pTrigger      : out std_ulogic;
         pTriggerIn    : in  std_ulogic;
         pAck          : in  std_ulogic;
         pHighVoltageOK: out std_ulogic;
         pFineDelay    : in  std_logic_vector(7 downto 0));
  end component;

  -- Define the System FPGA component
  component SystemFPGATop
    port(
      pPLX_nReset : in    std_ulogic;      -- Master reset input
      pPLX_LCLK   : in    std_ulogic;  -- same Local Bus Clock as sent to PLX chip
      pPLX_LA     : in    std_logic_vector(31 downto 2);  -- PLX Local bus address 
      pPLX_LD     : inout std_logic_vector(31 downto 0);  -- PLX Local bus data
      pPLX_LWR    : in    std_ulogic;      -- PLX Local Bus write NOT read
      pPLX_nADS   : in    std_ulogic;      -- Address Strobe
      pPLX_nBLAST : in    std_ulogic;      -- Burst Last
      pPLX_nREADY : out   std_ulogic;      -- Ready
      pPLX_LHOLD  : in    std_ulogic;      -- Local Hold Request
      pPLX_LHOLDA : out   std_ulogic;      -- Local Hold Acknowledge
      pPLX_nBTERM : out   std_ulogic;
      pPLX_nCCS   : out   std_ulogic;
      pPLX_BREQI  : out   std_ulogic;
      pRAM_nCS    : out   std_ulogic;
      pRAM_nOE    : out   std_ulogic;
      pRAM_nWE    : out   std_ulogic;
      pEEPROM_Q   : in    std_ulogic;
      pEEPROM_C   : out   std_ulogic;
      pEEPROM_nS  : out   std_ulogic;
      pEEPROM_D   : out   std_ulogic;
      pSTxD       : out   std_ulogic; 
      pSRxD       : in    std_ulogic;
      pnCtrlReset : out   std_ulogic;
      pIO         : inout std_logic_vector(52 downto 0);
      pLED        : out   std_ulogic);
  end component;

  -- Define the control FPGA component
  component ControlFPGATop
    port(
      pClock          : in  std_ulogic;
      -- System FPGA signals
      pnReset         : in  std_ulogic;
      pSTxD           : out std_ulogic;
      pSRxD           : in  std_ulogic;
      pHVStatus       : out std_ulogic;
      -- trigger and delay i/o
      pTrigger        : in  std_ulogic;
      pTriggerOut     : out std_ulogic;
      pTriggerDel     : in  std_ulogic;
      pFineDelay      : out std_logic_vector(7 downto 0);
      pAck            : out std_ulogic;
      -- control i/o
      pTestPort       : out std_logic_vector(7 downto 0);
      pExternalGainEn : out std_ulogic;
      pInternalGainEn : out std_ulogic;
      pBeHighPass     : out std_logic_vector(2 downto 0);
      pBeLowPass      : out std_logic_vector(2 downto 0);
      pHighPass       : out std_logic_vector(2 downto 0);
      pLowPass        : out std_logic_vector(2 downto 0);
      pFrontPlus20dB  : out std_ulogic;
      pFrontMinus40dB : out std_ulogic;
      pFront0dB       : out std_ulogic;
      pFrontMinus20dB : out std_ulogic;
      pRin47          : out std_ulogic;
      pRin100         : out std_ulogic;
      pRin270         : out std_ulogic;
      pRin470         : out std_ulogic;
      pPEChSel        : out std_logic_vector(8 downto 1);
      pRxChSel        : out std_logic_vector(8 downto 1);
      pPulse          : out std_logic_vector(8 downto 1);
      pHighVoltageEn  : out std_ulogic;
      pHighVoltageOK  : in  std_ulogic;
      pnPowerOn       : out std_ulogic;
      pnPowerOOT      : in  std_ulogic;
      pHTVOOT         : in  std_ulogic;
      pHTIOOT         : in  std_ulogic;
      pHTIsEn         : in  std_ulogic;
      pDAC_nCS        : out std_ulogic;
      pDAC_SDI        : out std_ulogic;
      pDAC_Clk        : out std_ulogic);
  end component;

  -- Define the component for the SRAM Model
  component SramModel is
    generic (gDataBusWidth : integer := 32;
             gAddrBusWidth : integer := 18);
    port (pData : inout std_logic_vector(gDataBusWidth-1 downto 0);
          pAddr : in    std_logic_vector(gAddrBusWidth-1 downto 0);
          pnCS  : in    std_ulogic;
          pnOE  : in    std_ulogic;
          pnWE  : in    std_ulogic);
  end component SramModel;

  --Define the componen for the DAC model
  component AD5399Model
    port(pDacClk     : in std_ulogic;
         pDacnCs     : in std_ulogic;
         pDacSdi     : in std_ulogic;
         pDacDataA   : out std_logic_vector(11 downto 0);
         pDacDataB   : out std_logic_vector(11 downto 0));
  end component;

  -- Signals to connect to models used in trhe system simulation
  signal ToBusModel: tToBusModel;
  signal FromBusModel: tFromBusModel;

  signal nLRESET:    std_ulogic;
  signal LCLKA:      std_ulogic;
  signal LWnR:       std_ulogic;
  signal nADS:       std_ulogic;
  signal nBLAST:     std_ulogic;
  signal nREADY:     std_ulogic;
  signal LA:         std_logic_vector(31 downto 0);
  signal LD:         std_logic_vector(31 downto 0);
  signal LHOLD:      std_ulogic;
  signal LHOLDA:     std_ulogic;
  signal nBTERM:     std_ulogic;
  signal nCCS:       std_ulogic;
  signal BREQi:      std_ulogic;

  signal nSysRamCS: std_ulogic;
  signal nSysRamWE: std_ulogic;
  signal nSysRamOE: std_ulogic;

  -- EEPROM Signals
  signal Eeprom_C:  std_ulogic;
  signal Eeprom_nS: std_ulogic;
  signal Eeprom_D:  std_ulogic;
  signal Eeprom_Q:  std_ulogic;
  signal EepromInstr: std_logic_vector(7 downto 0);
  signal EepromAddr:  std_logic_vector(8 downto 0);
  signal EepromData1: std_logic_vector(31 downto 0);
  signal EepromData2: std_logic_vector(31 downto 0);
  signal EepromData3: std_logic_vector(31 downto 0);
  signal EepromData4: std_logic_vector(31 downto 0);

  -- Control FPGA signals
  signal STxD       : std_ulogic;
  signal SRxD       : std_ulogic;
  signal nCtrlReset : std_ulogic;
  signal Clk100     : std_logic := '0';
  signal TestLed    : std_logic_vector(7 downto 0);

  signal HVStatus       : std_ulogic;
  signal Trigger        : std_ulogic;
  signal TriggerOut     : std_ulogic;
  signal TriggerDel     : std_ulogic;
  signal FineDelay      : std_logic_vector(7 downto 0);
  signal Ack            : std_ulogic;
  signal ExternalGainEn : std_ulogic;
  signal InternalGainEn : std_ulogic;
  signal BeHighPass     : std_logic_vector(2 downto 0);
  signal BeLowPass      : std_logic_vector(2 downto 0);
  signal HighPass       : std_logic_vector(2 downto 0);
  signal LowPass        : std_logic_vector(2 downto 0);
  signal FrontPlus20dB  : std_ulogic;
  signal FrontMinus40dB : std_ulogic;
  signal Front0dB       : std_ulogic;
  signal FrontMinus20dB : std_ulogic;
  signal Rin47          : std_ulogic;
  signal Rin100         : std_ulogic;
  signal Rin270         : std_ulogic;
  signal Rin470         : std_ulogic;
  signal PEChSel        : std_logic_vector(8 downto 1);
  signal RxChSel        : std_logic_vector(8 downto 1);
  signal Pulse          : std_logic_vector(8 downto 1);
  signal HighVoltageEn  : std_ulogic;
  signal HighVoltageOK  : std_ulogic;
  signal DAC_nCS        : std_ulogic;
  signal DAC_SDI        : std_ulogic;
  signal DAC_Clk        : std_ulogic;
  signal DacTcg         : std_logic_vector(11 downto 0);
  signal DacHvCtrl      : std_logic_vector(11 downto 0);


  constant cGnd: std_ulogic := '0';
  constant cVcc: std_ulogic := '1';

begin

  -- Instantiate the LocalBus model component
  LocalBusModel0: LocalBusModel
    port map(-- Control signals to/from main simulation module
             ToBusModel    => ToBusModel,
             FromBusModel  => FromBusModel,
             -- Actual bus signals
             pnLRESET      => nLRESET,
             pLCLKA        => LCLKA,
             pLWnR         => LWnR,
             pnADS         => nADS,
             pnBLAST       => nBLAST,
             pnREADY       => nREADY,
             pLA           => LA,
             pLD           => LD,
             pLHOLD        => LHOLD,
             pLHOLDA       => LHOLDA,
             pnBTERM       => nBTERM,
             pnCCS         => nCCS,
             pBREQi        => BREQi);

  -- Instantiate the Simulation Control component
  SimCtrl0: SimCtrl
    port map(ToBusModel     => ToBusModel,
             FromBusModel   => FromBusModel,
             pHVCtrl        => DacHvCtrl,
             pTCGVal        => DacTcg,
             pTrigger       => Trigger,
             pTriggerIn     => TriggerOut,
             pAck           => Ack,
             pHighVoltageOK => HighVoltageOK,
             pFineDelay     => FineDelay);

  DelayLine : process (TriggerOut, FineDelay) is
    variable vDelayTime: time;
  begin
    vDelayTime := (conv_integer(unsigned(FineDelay)) * (500 ps)) + 10 ns;

    TriggerDel <= TriggerOut after vDelayTime;
  end process DelayLine;    

  -- Instantiate the DSP FPGA component
  SystemFpgaTop0: SystemFpgaTop
    port map(-- Local bus
             pPLX_nReset => nLRESET,
             pPLX_LCLK   => LCLKA,
			       pPLX_LA     => LA(31 downto 2),
			       pPLX_LD     => LD,
             pPLX_LWR    => LWnR,
             pPLX_nADS   => nADS,
             pPLX_nBLAST => nBLAST,
             pPLX_nREADY => nREADY,
             pPLX_LHOLD  => LHOLD,
             pPLX_LHOLDA => LHOLDA,
			       pPLX_BREQI  => BREQi,
             -- System SRAM control
             pRAM_nCS    => nSysRamCS,
             pRAM_nWE    => nSysRamWE,
             pRAM_nOE    => nSysRamOE,
             -- EEPROM connections
             pEEPROM_C   => Eeprom_C,
             pEEPROM_nS  => Eeprom_nS,
             pEEPROM_D   => Eeprom_D,
             pEEPROM_Q   => Eeprom_Q,
             -- Control FPGA connections
			       pSTxD       => STxD,
             pSRxD		   => SRxD,
             pnCtrlReset => nCtrlReset,
             pIO         => open,
             pLED        => open);


  SramModel0: SramModel
    generic map(gDataBusWidth => 32,
                gAddrBusWidth => 18)
    port map(pData => LD,
             pAddr => LA(19 downto 2),
             pnCS  => nSysRamCS,
             pnOE  => nSysRamOE,
             pnWE  => nSysRamWE);


  -- Instantiate the Control FPGA component
  ControlFPGATop0: ControlFPGATop
    port map(pClock          => Clk100,
             pnReset         => nCtrlReset,
             pSTxD           => SRxD,
             pSRxD           => STxD,
             pHVStatus       => HVStatus,
             -- trigger and delay i/o
             pTrigger        => Trigger,
             pTriggerOut     => TriggerOut,
             pTriggerDel     => TriggerDel,
             pFineDelay      => FineDelay,
             pAck            => Ack,
             -- control i/o
             pTestPort       => TestLed,
             pExternalGainEn => ExternalGainEn,
             pInternalGainEn => InternalGainEn,
             pBeHighPass     => BeHighPass,
             pBeLowPass      => BeLowPass,
             pHighPass       => HighPass,
             pLowPass        => LowPass,
             pFrontPlus20dB  => FrontPlus20dB,
             pFrontMinus40dB => FrontMinus40dB,
             pFront0dB       => Front0dB,
             pFrontMinus20dB => FrontMinus20dB,
             pRin47          => Rin47,
             pRin100         => Rin100,
             pRin270         => Rin270,
             pRin470         => Rin470,
             pPEChSel        => PEChSel,
             pRxChSel        => RxChSel,
             pPulse          => Pulse,
             pHighVoltageEn  => HighVoltageEn,
             pHighVoltageOK  => HighVoltageOK,
             pnPowerOn       => open,
             pnPowerOOT      => '1',
             pHTVOOT         => '0',
             pHTIOOT         => '0',
             pHTIsEn         => '0',
             pDAC_nCS        => DAC_nCS,
             pDAC_SDI        => DAC_SDI,
             pDAC_Clk        => DAC_Clk);

  Clk100 <= not Clk100 after 5 ns;

  DACModel0: AD5399Model
    port map(pDacClk     => DAC_Clk,
             pDacnCs     => DAC_nCS,
             pDacSdi     => DAC_SDI,
             pDacDataA   => DacTcg,
             pDacDataB   => DacHvCtrl);

  EepromModel: process
    constant cReadData1: std_logic_vector(7 downto 0) := X"12";
    constant cReadData2: std_logic_vector(7 downto 0) := X"34";
    constant cReadData3: std_logic_vector(7 downto 0) := X"56";
    constant cReadData4: std_logic_vector(7 downto 0) := X"78";
    constant cReadData5: std_logic_vector(7 downto 0) := X"DE";
    constant cReadData6: std_logic_vector(7 downto 0) := X"AD";
    constant cReadData7: std_logic_vector(7 downto 0) := X"BE";
    constant cReadData8: std_logic_vector(7 downto 0) := X"EF";
    constant cReadData9: std_logic_vector(7 downto 0) := X"FE";
    constant cReadData10: std_logic_vector(7 downto 0) := X"ED";
    constant cReadData11: std_logic_vector(7 downto 0) := X"B0";
    constant cReadData12: std_logic_vector(7 downto 0) := X"0B";
    constant cReadData13: std_logic_vector(7 downto 0) := X"FE";
    constant cReadData14: std_logic_vector(7 downto 0) := X"DC";
    constant cReadData15: std_logic_vector(7 downto 0) := X"BA";
    constant cReadData16: std_logic_vector(7 downto 0) := X"98";

    constant cStatus:   std_logic_vector(7 downto 0) := X"FE";
  begin
    Eeprom_Q <= '1';

    wait on Eeprom_nS until falling_edge(Eeprom_nS);

    for Count in 7 downto 0 loop
      wait on Eeprom_C until rising_edge(Eeprom_C);
      EepromInstr(Count) <= Eeprom_D;
    end loop;

    wait for 1 ps;

    if EepromInstr = X"05" then  -- Read Status reg
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cStatus(Count);
        end loop;
        wait on Eeprom_C until falling_edge(Eeprom_C);
    end if;

    if EepromInstr = X"03" then  -- Read Memory Array
      -- Get past address
      EepromAddr(8) <= EepromInstr(3);
      for Count in 7 downto 0 loop
        wait on Eeprom_C until rising_edge(Eeprom_C);
        EepromAddr(Count) <= Eeprom_D;
      end loop;

      for MyLoop in 0 to 31 loop
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData1(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData2(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData3(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData4(Count);
        end loop;

        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData5(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData6(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData7(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData8(Count);
        end loop;

        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData9(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData10(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData11(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData12(Count);
        end loop;

        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData13(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData14(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData15(Count);
        end loop;
        for Count in 7 downto 0 loop
          wait on Eeprom_C until falling_edge(Eeprom_C);
          Eeprom_Q <= cReadData16(Count);
        end loop;

      end loop;
    end if;

    if EepromInstr = X"02" or EepromInstr = X"0A" then  -- Write Memory Array
      -- Get past address
      EepromAddr(8) <= EepromInstr(3);
      for Count in 7 downto 0 loop
        wait on Eeprom_C until rising_edge(Eeprom_C);
        EepromAddr(Count) <= Eeprom_D;
      end loop;

      for Count in 31 downto 0 loop
        wait on Eeprom_C until rising_edge(Eeprom_C);
        EepromData1(Count) <= Eeprom_D;
      end loop;
      for Count in 31 downto 0 loop
        wait on Eeprom_C until rising_edge(Eeprom_C);
        EepromData2(Count) <= Eeprom_D;
      end loop;
      for Count in 31 downto 0 loop
        wait on Eeprom_C until rising_edge(Eeprom_C);
        EepromData3(Count) <= Eeprom_D;
      end loop;
      for Count in 31 downto 0 loop
        wait on Eeprom_C until rising_edge(Eeprom_C);
        EepromData4(Count) <= Eeprom_D;
      end loop;

    end if;
  end process EepromModel;

end architecture Test;