---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2005
--
-- Filename: SystemFpgaTop.vhd
-- Language: VHDL '93
-- Project:  Pulse Receive Card System FPGA
--
-- Design Description:
-- Top level of Pulser Receiver Card (PRx) System FPGA
--
---------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

use work.SystemFPGA_pkg.all;

entity SystemFPGATop is
  port( -- Local bus
    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;
    -- System RAM signals
    pRAM_nCS    : out   std_ulogic;
    pRAM_nOE    : out   std_ulogic;
    pRAM_nWE    : out   std_ulogic;
    -- EEPROM signals
    pEEPROM_Q   : in    std_ulogic;
    pEEPROM_C   : out   std_ulogic;
    pEEPROM_nS  : out   std_ulogic;
    pEEPROM_D   : out   std_ulogic;
    -- Control FPGA signals
    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 SystemFPGATop;

architecture RTL of SystemFPGATop is

  component ClockReset
    port (
      pClockIn   : in  std_ulogic;
      pClockOut  : out std_ulogic;
      pnResetIn  : in  std_ulogic;
      pnResetOut : out std_ulogic);
  end component;
  
  component AddressDecoder
    port (
      pPLX_LA      : in  std_logic_vector(31 downto 2);
      pPLX_LWR     : in  std_ulogic;
      pPLX_nREADY  : in  std_ulogic;
      pWnR         : in  std_ulogic;
      pnSTROBE     : in  std_ulogic;
      pnEN_RAM     : out std_ulogic;
      pnEN_Check   : out std_ulogic;
      pnEN_Version : out std_ulogic;
      pnEN_Command : out std_ulogic;
      pnEN_EEPROM  : out std_ulogic;
      pnEn_SeqTab  : out std_ulogic;
      pnEN_GlbConf : out std_ulogic;
      pnEN_IOData0 : out std_ulogic;
      pnEN_IODir0  : out std_ulogic;
      pnEN_IOData1 : out std_ulogic;
      pnEN_IODir1  : out std_ulogic;
      pnWE         : out std_ulogic;
      pnOE         : out std_ulogic);
  end component;

  component BusArbiter
    port (
      pnReset  : in  std_ulogic;
      pClock   : in  std_ulogic;
      pHOLD_1  : in  std_ulogic;
      pHOLD_2  : in  std_ulogic;
      pHOLDA_1 : out std_ulogic;
      pHOLDA_2 : out std_ulogic);
  end component;

  component PLXInterface
    port(
      pnReset     : in  std_ulogic;
      pClock      : in  std_ulogic;
      pHOLDA      : in  std_ulogic;
      pPLX_LWR    : in  std_ulogic;
      pPLX_nADS   : in  std_ulogic;
      pPLX_nBLAST : in  std_ulogic;
      pPLX_nREADY : out std_ulogic;
      pPLX_BREQI  : out std_ulogic);
  end component;

  component DataMux
    port(
      pDataIn0 : in  std_logic_vector(31 downto 0);
      pDataIn1 : in  std_logic_vector(31 downto 0);
      pDataIn2 : in  std_logic_vector(31 downto 0);
      pDataIn3 : in  std_logic_vector(31 downto 0);
      pDataIn4 : in  std_logic_vector(31 downto 0);
      pDataIn5 : in  std_logic_vector(31 downto 0);
      pDataIn6 : in  std_logic_vector(31 downto 0);
      pDataIn7 : in  std_logic_vector(31 downto 0);
      pDataIn8 : in  std_logic_vector(31 downto 0);
      pDataIn9 : in  std_logic_vector(31 downto 0);
      pDSEL0   : in  std_ulogic;
      pDSEL1   : in  std_ulogic;
      pDSEL2   : in  std_ulogic;
      pDSEL3   : in  std_ulogic;
      pDSEL4   : in  std_ulogic;
      pDSEL5   : in  std_ulogic;
      pDSEL6   : in  std_ulogic;
      pDSEL7   : in  std_ulogic;
      pDSEL8   : in  std_ulogic;
      pDSEL9   : in  std_ulogic;
      pDataOut : out std_logic_vector(31 downto 0));
  end component;

  component SysControl
    port (
      pnReset     : in  std_ulogic;
      pClock      : in  std_ulogic;
      pnWE        : in  std_ulogic;
      pnCECmd     : in  std_ulogic;
      pnCEGlb     : in  std_ulogic;
      pHOLDA      : in  std_ulogic;
      pSRxD       : in  std_ulogic;
      pEEBusy     : in  std_ulogic;
      pDataIn     : in  std_logic_vector(31 downto 0);
      pStatusDOut : out std_logic_vector(31 downto 0);
      pGlobDOut   : out std_logic_vector(31 downto 0);
      pAddress    : out std_logic_vector(31 downto 2);
      pDPRAMIn    : in  std_logic_vector(31 downto 0);
      pSTxD       : out std_ulogic;
      pCtrlRst    : out std_ulogic;
      pEERead     : out std_ulogic;
      pEEWrite    : out std_ulogic);
  end component;
  
  component CheckReg
    port(
      pClock   : in  std_ulogic;
      pnReset  : in  std_ulogic;
      pnWE     : in  std_ulogic;
      pnCS     : in  std_ulogic;
      pDataIn  : in  std_logic_vector(31 downto 0);
      pDataOut : out std_logic_vector(31 downto 0));
  end component;

  component SysIo
    generic(
      gWidth   : in     integer := 32);
    port(
      pClock   : in     std_ulogic;
      pnReset  : in     std_ulogic;
      pnWE     : in     std_ulogic;
      pnCSData : in     std_ulogic;
      pnCSDir  : in     std_ulogic;
      pDataIn  : in     std_logic_vector(31 downto 0);
      pDataOut : out    std_logic_vector(31 downto 0);
      pDirOut  : out    std_logic_vector(31 downto 0);
      pIO      : inout  std_logic_vector(gWidth-1 downto 0));
  end component;

  component EEPROM
    port (
      pnReset    : in  std_ulogic;
      pClock     : in  std_ulogic;
      pDoWrite   : in  std_ulogic;
      pDoRead    : in  std_ulogic;
      pnWE       : in  std_ulogic;
      pnCS       : in  std_ulogic;
      pAddress   : in  std_logic_vector(7 downto 0);
      pDataIn    : in  std_logic_vector(31 downto 0);
      pEEPROM_Q  : in  std_ulogic;
      pBusy      : out std_ulogic;
      pEEPROM_C  : out std_ulogic;
      pEEPROM_nS : out std_ulogic;
      pEEPROM_D  : out std_ulogic;
      pDataOut   : out std_logic_vector(31 downto 0));
  end component;
  
  component SysSequenceTable
    port (
      pnReset       : in  std_ulogic;
      pClock        : in  std_ulogic;
      pnWE          : in  std_ulogic;
      pnCS          : in  std_ulogic;
      pAddress      : in  std_logic_vector(7 downto 0);
      pDataIn       : in  std_logic_vector(31 downto 0);
      pDataOut      : out std_logic_vector(31 downto 0);
      pSeqTableAddr : in  std_logic_vector(7 downto 0);
      pSeqTableOut  : out std_logic_vector(31 downto 0));
  end component;
  
  constant cSysVersion : std_logic_vector(31 downto 0) := x"00000" & cFpgaRevision;

  signal nReset  : std_ulogic;  -- Local reset, from the LOCKED signal of DLL
  signal Clock   : std_ulogic;           -- Local clock - output of DLL
  signal HOLDA_1 : std_ulogic;
  signal HOLD_2  : std_ulogic;
  signal HOLDA_2 : std_ulogic;
  signal CtrlRst : std_ulogic;

  signal PLX_nREADY  : std_ulogic;
  signal nEN_RAM     : std_ulogic;
  signal nEN_EEPROM  : std_ulogic;
  signal nEN_Check   : std_ulogic;
  signal nEN_Version : std_ulogic;
  signal nEN_Command : std_ulogic;
  signal nEn_SeqTable: std_ulogic;
  signal nEN_GlbConf : std_ulogic;
  signal nEN_IOData0 : std_ulogic;
  signal nEN_IODir0  : std_ulogic;
  signal nEN_IOData1 : std_ulogic;
  signal nEN_IODir1  : std_ulogic;
  signal nOE         : std_ulogic;
  signal nWE         : std_ulogic;

  signal DBus0 : std_logic_vector (31 downto 0);
  signal DBus1 : std_logic_vector (31 downto 0);
  signal DBus2 : std_logic_vector (31 downto 0);
  signal DBus3 : std_logic_vector (31 downto 0);
  signal DBus4 : std_logic_vector (31 downto 0);
  signal DBus5 : std_logic_vector (31 downto 0);
  signal DBus6 : std_logic_vector (31 downto 0);
  signal DBus7 : std_logic_vector (31 downto 0);
  signal DBus8 : std_logic_vector (31 downto 0);

  signal EERead  : std_ulogic;
  signal EEWrite : std_ulogic;
  signal EEBusy  : std_ulogic;

  signal PLX_LA_I : std_logic_vector (31 downto 2);
  signal PLX_LD_I : std_logic_vector (31 downto 0);
  signal PLX_LD_O : std_logic_vector (31 downto 0);

  signal SeqTableAddr: std_logic_vector(31 downto 2);
  signal SeqTableOut: std_logic_vector(31 downto 0);

  signal WnR     : std_ulogic;
  signal nStrobe : std_ulogic;

begin

  pLED        <= '0';                   -- LED on
  pPLX_LHOLDA <= HOLDA_1;
  pPLX_nREADY <= PLX_nREADY;

  pRAM_nCS <= nEN_RAM;
  pRAM_nOE <= nOE;
  pRAM_nWE <= nWE;

  PLX_LA_I <= pPLX_LA;

  PLX_LD_I <= pPLX_LD;
  pPLX_LD  <= PLX_LD_O when ((nEN_EEPROM = '0' or nEN_Command = '0' or nEn_SeqTable = '0' or nEN_GlbConf = '0' or
                              nEN_Check = '0' or nEN_Version = '0' or nEN_IOData0 = '0' or 
                              nEN_IOData1 = '0' or nEN_IODir0 = '0' or nEN_IODir1 = '0') and nOE = '0' )
                            else (others => 'Z');
  pPLX_nBTERM <= '1';
  pPLX_nCCS   <= '1';

  ClockReset_1 : ClockReset             -- Clock sync and clean reset generator
    port map (
      pClockIn   => pPLX_LCLK,
      pClockOut  => Clock,
      pnResetIn  => pPLX_nReset,
      pnResetOut => nReset);

  pnCtrlReset <= not CtrlRst;

  AddressDecoder_1: AddressDecoder
    port map (
      pPLX_LA      => PLX_LA_I,
      pPLX_LWR     => pPLX_LWR,
      pPLX_nREADY  => PLX_nREADY,
      pWnR         => '1',
      pnSTROBE     => '1',
      pnEN_RAM     => nEN_RAM,
      pnEN_Check   => nEN_Check,
      pnEN_Version => nEN_Version,
      pnEN_Command => nEN_Command,
      pnEN_EEPROM  => nEN_EEPROM,
      pnEn_SeqTab  => nEn_SeqTable,
      pnEN_GlbConf => nEN_GlbConf,
      pnEN_IOData0 => nEN_IOData0,
      pnEN_IODir0  => nEN_IODir0,
      pnEN_IOData1 => nEN_IOData1,
      pnEN_IODir1  => nEN_IODir1,
      pnWE         => nWE,
      pnOE         => nOE);
  
  BusArbiter_1 : BusArbiter
    port map (
      pnReset  => nReset,
      pClock   => Clock,
      pHOLD_1  => pPLX_LHOLD,
      pHOLD_2  => HOLD_2,
      pHOLDA_1 => HOLDA_1,
      pHOLDA_2 => HOLDA_2);

  PLXInterface_1 : PLXInterface
    port map(
      pnReset     => nReset,
      pClock      => Clock,
      pHOLDA      => HOLDA_1,
      pPLX_LWR    => pPLX_LWR,
      pPLX_nADS   => pPLX_nADS,
      pPLX_nBLAST => pPLX_nBLAST,
      pPLX_nREADY => PLX_nREADY,
      pPLX_BREQI  => pPLX_BREQI);

  SysControl_1 : SysControl
    port map (
      pnReset     => nReset,
      pClock      => Clock,
      pnWE        => nWE,
      pnCECmd     => nEN_Command,
      pnCEGlb     => nEN_GlbConf,
      pHOLDA      => HOLDA_2,
      pSRxD       => pSRxD,
      pEEBusy     => EEBusy,
      pDataIn     => PLX_LD_I,
      pStatusDOut => DBus1,
      pGlobDOut   => DBus8,
      pAddress    => SeqTableAddr,
      pDPRAMIn    => SeqTableOut,
      pSTxD       => pSTxD,
      pCtrlRst    => CtrlRst,
      pEERead     => EERead,
      pEEWrite    => EEWrite);

  DataMux_1: DataMux
    port map (
      pDataIn0 => DBus0,
      pDataIn1 => DBus1,
      pDataIn2 => DBus2,
      pDataIn3 => DBus3,
      pDataIn4 => DBus4,
      pDataIn5 => DBus5,
      pDataIn6 => DBus6,
      pDataIn7 => DBus7,
      pDataIn8 => DBus8,
      pDataIn9 => cSysVersion,
      pDSEL0   => nEN_EEPROM,
      pDSEL1   => nEN_Command, -- Status register
      pDSEL2   => nEn_SeqTable,
      pDSEL3   => nEn_Check,
      pDSEL4   => nEN_IOData0,
      pDSEL5   => nEN_IODir0,
      pDSEL6   => nEN_IOData1,
      pDSEL7   => nEN_IODir1,
      pDSEL8   => nEN_GlbConf,
      pDSEL9   => nEn_Version,
      pDataOut => PLX_LD_O);
  
  CheckReg_1: CheckReg
    port map (
      pClock   => Clock,
      pnReset  => nReset,
      pnWE     => nWE,
      pnCS     => nEn_Check,
      pDataIn  => PLX_LD_I,
      pDataOut => DBus3);

  SysIO0: SysIo
  generic map(
    gWidth   => 32)
  port map(
    pClock   => Clock,
    pnReset  => nReset,
    pnWE     => nWE,
    pnCSData => nEN_IOData0,
    pnCSDir  => nEN_IODir0,
    pDataIn  => PLX_LD_I,
    pDataOut => DBus4,
    pDirOut  => DBus5,
    pIO      => pIO(31 downto 0));

  SysIO1: SysIo
  generic map(
    gWidth   => 21)
  port map(
    pClock   => Clock,
    pnReset  => nReset,
    pnWE     => nWE,
    pnCSData => nEN_IOData1,
    pnCSDir  => nEN_IODir1,
    pDataIn  => PLX_LD_I,
    pDataOut => DBus6,
    pDirOut  => DBus7,
    pIO      => pIO(52 downto 32));

  EEPROM_1 : EEPROM
    port map (
      pnReset    => nReset,
      pClock     => Clock,
      pDoWrite   => EEWrite,
      pDoRead    => EERead,
      pnWE       => nWE,
      pnCS       => nEN_EEPROM,
      pAddress   => PLX_LA_I(9 downto 2),
      pDataIn    => PLX_LD_I,
      pEEPROM_Q  => pEEPROM_Q,
      pBusy      => EEBusy,
      pEEPROM_C  => pEEPROM_C,
      pEEPROM_nS => pEEPROM_nS,
      pEEPROM_D  => pEEPROM_D,
      pDataOut   => DBus0);

  SeqTab_1: SysSequenceTable
    port map (
      pnReset       => nReset,
      pClock        => Clock,
      pnWE          => nWE,
      pnCS          => nEn_SeqTable,
      pAddress      => PLX_LA_I(9 downto 2),
      pDataIn       => PLX_LD_I,
      pDataOut      => DBus2,
	    pSeqTableAddr => SeqTableAddr(9 downto 2),
	    pSeqTableOut  => SeqTableOut);

end architecture RTL;
