---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: DspFpgaTop.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card DSP FPGA
--
-- Design Description:
-- Top Level for Digitiser Card DSP FPGA
---------------------------------------------------------------------------

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

library work;
use work.DspFpgaVerPkg.all;
use work.DspFpgaPkg.all;

entity DspFpgaTop is
  port(-- Local bus
       pnLReset    : in    std_ulogic;
       pnFpgaCs    : in    std_ulogic;
       pLWnR       : in    std_ulogic;
       pLA         : in    std_logic_vector(31 downto 2);
       pLD         : inout std_logic_vector(31 downto 0);
       pLCLK       : in    std_ulogic;  -- (GCK3 input)
       pnIRQ0      : out   std_ulogic;  -- interrupt
       -- Peripheral FPGA Communications signals
       pZ0         : out   std_ulogic;  -- Clock DLL reset signal
       pZ1         : in    std_ulogic;  -- Serial shaft encoder results enable
       pZ2         : in    std_ulogic;  -- Serial shaft encoder results
       pZ3         : in    std_ulogic;  -- Serial gate data in
       pZ4         : in    std_ulogic;  -- Serial gate data enable in
       pZ5         : in    std_ulogic;  -- Serial gate sel (bit 0)
       pZ6         : in    std_ulogic;  -- Serial gate sel (bit 1)
       pZ7         : in    std_ulogic;  -- Serial gate sel (bit 2)
       pZ8         : out   std_ulogic;  -- B-Scan is active indicator
       pZ9         : out   std_ulogic;  -- Raw External Trigger signal to Peripheral FPGA
       pZ10        : in    std_ulogic;  -- Trigger signal from Peripheral FPGA
       pZ11        : in    std_ulogic;  -- External Trigger is selected
       -- A to D Signals
       pADC_En     : out   std_ulogic;
       pADC_Clk    : in    std_ulogic;  -- Clock from AtoD convertor (GCK2 input)
       pADC_DataA  : in    std_logic_vector(11 downto 0);  -- Data stream A from AtoD convertor
       pADC_DataB  : in    std_logic_vector(11 downto 0);  -- Data stream B from AtoD convertor
       pTrigIn     : in    std_ulogic;  -- Sample run started trigger
       pSampleClk  : in    std_ulogic;  -- Sample clock (GCK0 input)
       -- Bank A SRAM Signals
       pSramA_Addr : out   std_logic_vector(17 downto 0);  -- SRAM Bank A Address bus
       pSramA_Data : inout std_logic_vector(31 downto 0);  -- SRAM Bank A Data bus
       pSramA_nWE  : out   std_ulogic;                     -- SRAM Bank A Read strobe
       pSramA_nRD  : out   std_ulogic;                     -- SRAM Bank A Write strobe
       pSramA_nCS  : out   std_logic_vector(3 downto 0);   -- SRAM Bank A chip selects
       -- Bank B SRAM Signals
       pSramB_Addr : out   std_logic_vector(17 downto 0);  -- SRAM Bank B Address bus
       pSramB_Data : inout std_logic_vector(31 downto 0);  -- SRAM Bank B Data bus
       pSramB_nWE  : out   std_ulogic;                     -- SRAM Bank B Read strobe
       pSramB_nRD  : out   std_ulogic;                     -- SRAM Bank B Write strobe
       pSramB_nCS  : out   std_logic_vector(3 downto 0);   -- SRAM Bank B chip selects
       -- DDS Signals
       pDDS_nWR    : out   std_ulogic;
       pDDSA       : out   std_logic_vector(5 downto 0);
       pDDSD       : out   std_logic_vector(7 downto 0);
       pDDSRESET   : out   std_ulogic;
       pDDS_IO     : in    std_ulogic;
       -- DAC Signels
       pDACCLK     : out   std_ulogic;
       pDAC1WRT    : out   std_ulogic;
       pDAC2WRT    : out   std_ulogic;
       pDACSLEEP   : out   std_ulogic;
       -- DAC SRAM Signals
       pDACnWR     : out   std_ulogic;
       pDACnRD     : out   std_ulogic;
       pDACD       : out   std_logic_vector(15 downto 0);
       pDACA       : out   std_logic_vector(17 downto 0);
       --
       pSYNC       : out   std_ulogic;
       -- LEDs
       pLED0       : out   std_ulogic;
       pLED1       : out   std_ulogic);
end entity DspFpgaTop;


architecture Rtl of DspFpgaTop is

  -- Component Definitions
  component IBUF
    port (I   : in    std_ulogic;
          O   : out   std_ulogic);
  end component;

  component IBUFG
    port (I   : in    std_ulogic;
          O   : out   std_ulogic);
  end component;

  component BUFG
    port (I   : in    std_ulogic;
          O   : out   std_ulogic);
  end component;

  component CLKDLL  -- Xilinx CLKDLL component
    port (CLKIN  : in  std_ulogic;
          CLKFB  : in  std_ulogic;
          RST    : in  std_ulogic;
          CLK0   : out std_ulogic;
          CLK90  : out std_ulogic;
          CLK180 : out std_ulogic;
          CLK270 : out std_ulogic;
          CLK2X  : out std_ulogic;
          CLKDV  : out std_ulogic;
          LOCKED : out std_ulogic);
  end component;


  component StrobeExtender is
    generic(gLfsrBits: integer range 3 to 32 := 3);
    port(pnReset    : in  std_ulogic;
         pClk       : in  std_ulogic;
         pStrobeIn  : in  std_ulogic;
         pStrobeOut : out std_ulogic);
  end component StrobeExtender;


  component TriggerGenerator
    port(pnReset            : in  std_ulogic;
         pADC_2xClk         : in  std_ulogic;
         pSampleEn          : in  std_ulogic;
         pTriggerIn         : in  std_ulogic;
         pTriggerOut        : out std_ulogic;
         pAllTriggersOut    : out std_ulogic;
         pCaptureDone       : in  std_ulogic;
         pDataReady         : in  std_ulogic;
         pSetDataReady      : out std_ulogic;
         pSetEarlyTrigError : out std_ulogic;
         pSetDataFullError  : out std_ulogic;
         pSomeDataReady     : out std_ulogic;
         pBScansAvailable   : out std_logic_vector(14 downto 0);
         -- Early data delivery request
         pEarlyDataReq      : in  std_ulogic;
         -- Register Data
         pAScansPerBScan    : in  std_logic_vector(6 downto 0);
         pNumOfBScans       : in  std_logic_vector(14 downto 0);
         pStorageMode       : in  std_logic_vector(1 downto 0);
         --
         pAScanNum          : out std_logic_vector(6 downto 0);
         pBScanActive       : out std_ulogic;
         pAllBScanActive    : out std_ulogic;
         pBScanStart        : out std_ulogic;
         pLastAScan         : out std_ulogic;
         pResetElemNum      : out std_ulogic;
         pResetAScanAddr    : out std_ulogic;
         pResetCScanAddr    : out std_ulogic;
         pSramBankSelect    : out std_ulogic;
         pnSramBankSelect   : out std_ulogic;
         pTest0             : out std_ulogic;
         pTest1             : out std_ulogic);
  end component TriggerGenerator;

  component DataInterleave
    port (pnReset         : in  std_ulogic;
          pADC_2xClk      : in  std_ulogic;  -- Frequency doubled version of clock
          pADC_2xClkValid : in  std_ulogic;  -- x2 Clock is valid
          pADC_DataA      : in  std_logic_vector(11 downto 0);  -- Data stream A from AtoD convertor
          pADC_DataB      : in  std_logic_vector(11 downto 0);  -- Data stream B from AtoD convertor
          pADC_DataOut    : out std_logic_vector(11 downto 0)); -- Combined data stream
  end component DataInterleave;

  component DataRectifier is
       port(pnReset       : in  std_ulogic;
            pADC_2xClk    : in  std_ulogic;
            pDropSamples  : in  std_logic_vector(3 downto 0);
            pMode         : in  std_logic_vector(1 downto 0);
            p8BitValues   : in  std_ulogic;
            pDataIn       : in  std_logic_vector(11 downto 0);
            pSampleEn     : out std_ulogic;
            pDataOut      : out std_logic_vector(11 downto 0);
            pRectifiedOut : out std_logic_vector(10 downto 0));
  end component DataRectifier;

  component LBusInterface
    port (-- Local bus signals
          pnReset              : in  std_ulogic;
          pLClk                : in  std_ulogic;
          pnFPGACS             : in  std_ulogic;
          pLAin                : in  std_logic_vector(31 downto 2);
          pLDin                : in  std_logic_vector(31 downto 0);
          pLDout               : out std_logic_vector(31 downto 0);
          pLDoutput_enable     : out std_ulogic;
          pLWnR                : in  std_ulogic;
          pnIRQ0               : out std_ulogic;
          -- ClkDll reset signal
          pResetClkDll         : out std_ulogic;
          --SRAM Signals
          pSram_nCS            : out std_logic_vector(3 downto 0);  -- Chip selects for SRAM
          pSram_nRD            : out std_ulogic;  -- Write Enable for SRAM
          pSramData            : in  std_logic_vector(31 downto 0);  -- Data bus from SRAM
          pSramAddr            : out std_logic_vector(17 downto 0); -- Address bus for SRAM
          -- Signals for DDS chip
          pDDS_addr            : out std_logic_vector(5 downto 0);
          pDDS_data            : out std_logic_vector(7 downto 0);
          pDDS_wr              : out std_ulogic;
          pDDS_reset           : out std_ulogic;
          pDDS_IO              : in  std_ulogic;
          -- Signals for DAC RAM
          pDACA                : out std_logic_vector(17 downto 0);
          pDACD                : out std_logic_vector(15 downto 0);
          pDACnWR              : out std_ulogic;
          pDAC_Sel             : out std_ulogic;
          -- Signals to Curved Gate Dual Port RAM
          pCurveWr             : out std_ulogic;
          pCurveAddr           : out std_logic_vector(11 downto 0);
          pCurveData           : out std_logic_vector(10 downto 0);
          -- Signals from Trigger Generation module
          pBScansInSram        : in  std_logic_vector(14 downto 0);
          pSetDataReady        : in  std_ulogic;
          pSetNewTrigger       : in  std_ulogic;
          pSetEarlyTrigError   : in  std_ulogic;
          pSetDataFullError    : in  std_ulogic;
          pSomeDataReady       : in  std_ulogic;
          -- Sample raw ADC signals
          pSampleAdcData       : out std_ulogic;
          pRawAdcData          : in  std_logic_vector(11 downto 0);
          -- Data ready indicator to S/W
          pDataReady           : out std_ulogic;
          -- Early data delivery request
          pEarlyDataReq        : out std_ulogic;
          -- Reset sampling circuitry
          pResetSampling       : out std_ulogic;
          -- Force trigger event
          pForceTrigger      : out std_ulogic;
          -- Readable register contents
          pAdc2xClkValid       : in  std_ulogic;
          pDebug               : in  std_logic_vector(31 downto 0) := X"00000000";
          -- Register Outputs
          pRegData             : out tRegSet);
  end component;


  component SramWriteCtrl
    port (pnReset         : in  std_ulogic;
          pADC_2xClk      : in  std_ulogic;  -- Frequency doubled version of clock
          pADC_Data       : in  std_logic_vector(11 downto 0);  -- Combined data stream from ADC
          pSampleEn       : in  std_ulogic;  -- Enable signal for sample data
          pAllTriggers    : in  std_ulogic;
          pLastTrigger    : in  std_ulogic;
          pBScanActive    : in  std_ulogic;
          pLastAScan      : in  std_ulogic;
          pAScanDone      : out std_ulogic;
          pGateEnables    : in  std_logic_vector(7 downto 0);
          pStartCapture   : in  std_ulogic;  -- Start strobe
          pCaptureDone    : out std_ulogic;  -- Capture has completed
          p12BitPack      : in  std_ulogic;
          p8BitStore      : in  std_ulogic;
          p8BitValues     : in  std_ulogic;
          pNumOfSamples   : in  std_logic_vector(14 downto 0);
          pCScanStartAddr : in  std_logic_vector(19 downto 0);
          pStorageMode    : in  std_logic_vector(1 downto 0);
          pResetElemNum   : in  std_ulogic;
          pResetAScanAddr : in  std_ulogic;
          pResetCScanAddr : in  std_ulogic;
          pEnc0Data       : in  std_logic_vector(31 downto 0);
          pEnc1Data       : in  std_logic_vector(31 downto 0);
          pEnc2Data       : in  std_logic_vector(31 downto 0);
          pEnc3Data       : in  std_logic_vector(31 downto 0);
          pEnc4Data       : in  std_logic_vector(31 downto 0);
          pEnc5Data       : in  std_logic_vector(31 downto 0);
          pGateData       : in  std_logic_vector(31 downto 0);
          pGateSelect     : out std_logic_vector(7 downto 0);
          pSram_nCS       : out std_logic_vector(3 downto 0);   -- Chip select for SRAM
          pSram_nWEEn     : in  std_ulogic;
          pSram_nWE       : out std_logic_vector(1 downto 0);   -- Write Enable for SRAM
          pSramData       : out std_logic_vector(31 downto 0);  -- Data bus for SRAM
          pSramAddr       : out std_logic_vector(17 downto 0)); -- Address bus for SRAM
  end component SramWriteCtrl;


  component SramSwitching
    port (pBankAnB_Active : in  std_ulogic;  -- Which bank is active for the datastream storage
          pBankBnA_Active : in  std_ulogic;
          -- Inputs to/from datastream storing logic
          pDStreamAddr    : in  std_logic_vector(17 downto 0);
          pDStreamDataOut : in  std_logic_vector(31 downto 0);
          pDStream_nWE    : in  std_logic_vector(1 downto 0);
          pDStream_nCS    : in  std_logic_vector(3 downto 0);
          -- Inputs to/from local bus
          pLBusSramAddr   : in  std_logic_vector(17 downto 0);
          pLBusSramDataOE : in  std_ulogic;
          pLBusSramDataIn : out std_logic_vector(31 downto 0);
          pLBusSram_nRD   : in  std_ulogic;
          pLBusSram_nCS   : in  std_logic_vector(3 downto 0);
          -- Outputs to/for SRAM bank A
          pSramA_Addr    : out std_logic_vector(17 downto 0);  -- SRAM Bank A Address bus
          pSramA_DataOut : out std_logic_vector(31 downto 0);  -- SRAM Bank A Data bus
          pSramA_DataOE  : out std_ulogic;                     -- SRAM Bank A Data output enable
          pSramA_DataIn  : in  std_logic_vector(31 downto 0);  -- SRAM Bank A Data bus
          pSramA_nWE     : out std_ulogic;                     -- SRAM Bank A Read strobe
          pSramA_nRD     : out std_ulogic;                     -- SRAM Bank A Write strobe
          pSramA_nCS     : out std_logic_vector(3 downto 0);   -- SRAM Bank A chip selects
          -- Outputs to/for SRAM bank B
          pSramB_Addr    : out std_logic_vector(17 downto 0);  -- SRAM Bank B Address bus
          pSramB_DataOut : out std_logic_vector(31 downto 0);  -- SRAM Bank B Data bus
          pSramB_DataOE  : out std_ulogic;                     -- SRAM Bank B Data output enable
          pSramB_DataIn  : in  std_logic_vector(31 downto 0);  -- SRAM Bank B Data bus
          pSramB_nWE     : out std_ulogic;                     -- SRAM Bank B Read strobe
          pSramB_nRD     : out std_ulogic;                     -- SRAM Bank B Write strobe
          pSramB_nCS     : out std_logic_vector(3 downto 0));  -- SRAM Bank B chip selects
  end component SramSwitching;


  component TcgCtrl is
    port (-- Local bus signals
          pnReset       : in  std_ulogic;
          pADC_2xClk    : in  std_ulogic;
          pTcgEnable    : in  std_ulogic;
          pNumOfSamples : in  std_logic_vector(13 downto 0);
          pTriggersIn   : in  std_logic_vector(15 downto 0);
          pTriggerNum   : in  std_ulogic;
          pElemSelBits  : in  std_logic_vector(1 downto 0);
          pAScanNum     : in  std_logic_vector(6 downto 0);
          pTcgApplyTime : in  std_logic_vector(3 downto 0);
          pCaptureDone  : in  std_ulogic;
          -- DAC SRAM Signals
          pDACA         : out std_logic_vector(17 downto 0);
          -- Actual DAC Signals
          DACWRT        : out std_ulogic;
          DACCLK        : out std_ulogic;
          Test          : out std_ulogic);
  end component TcgCtrl;


  component DualPortRam is
    generic(gAddressWidth: integer range 1 to 32 := 6;
            gDataWidth:    integer range 1 to 32 := 32);
    port(pClk       : in  std_ulogic;
         pWriteEn   : in  std_ulogic;
         pAddr      : in  std_logic_vector(gAddressWidth-1 downto 0);
         pDataIn    : in  std_logic_vector(gDataWidth-1 downto 0);
         pDataOut   : out std_logic_vector(gDataWidth-1 downto 0);
         pDpClk     : in  std_ulogic;
         pDpAddr    : in  std_logic_vector(gAddressWidth-1 downto 0);
         pDpDataOut : out std_logic_vector(gDataWidth-1 downto 0));
  end component DualPortRam;


  component InterfaceGate
    port(pnReset         : in  std_ulogic;
         pADC_2xClk      : in  std_ulogic;
         pSampleEn       : in  std_ulogic;
         pTrigger        : in  std_ulogic;
         pEnable         : in  std_ulogic;
         pStartCount     : in  std_logic_vector(15 downto 0);
         pStopCount      : in  std_logic_vector(15 downto 0);
         pThreshold      : in  std_logic_vector(10 downto 0);
         pTriggerMode    : in  std_ulogic;
         pPolarityMode   : in  std_logic_vector(1 downto 0);
         pRectifiedData  : in  std_logic_vector(10 downto 0);
         pPolarity       : in  std_ulogic;
         pGateFiring     : out std_ulogic;
         pGateFired      : out std_ulogic;
         pGateDidNotFire : out std_ulogic;
         pGateOutputData : out std_logic_vector(13 downto 0));
  end component InterfaceGate;


  component Gate
    port(pnReset         : in  std_ulogic;
         pADC_2xClk      : in  std_ulogic;
         pSampleEn       : in  std_ulogic;
         pTriggersIn     : in  std_logic_vector(15 downto 0);
         pNoTriggersIn   : in  std_logic_vector(15 downto 0);
         pEnable         : in  std_ulogic;
         pStartCount     : in  std_logic_vector(15 downto 0);
         pStopCount      : in  std_logic_vector(15 downto 0);
         pForceStop      : in  std_ulogic;
         pThreshold      : in  std_logic_vector(10 downto 0);
         pTriggerNum     : in  std_logic_vector(3 downto 0);
         pTriggerMode    : in  std_ulogic;
         pZeroCrossMode  : in  std_ulogic;
         pPolarityMode   : in  std_logic_vector(1 downto 0);
         pDistMetric     : in  std_logic_vector(1 downto 0);
         pPeakSelAmp     : in  std_logic_vector(3 downto 0);
         pPeakSelDist    : in  std_logic_vector(3 downto 0);
         pHoldoff        : in  std_logic_vector(6 downto 0);
         pSampleData     : in  std_logic_vector(11 downto 0);
         pRectifiedData  : in  std_logic_vector(10 downto 0);
         pGateFiring     : out std_ulogic;
         pGateUnTrigger  : out std_ulogic;
         pGateFired      : out std_ulogic;
         pGateDidNotFire : out std_ulogic;
         pGateReFire     : out std_ulogic;
         pGateOutputData : out std_logic_vector(13 downto 0));
  end component Gate;


  component CurvedGate
    port(pnReset         : in  std_ulogic;
         pADC_2xClk      : in  std_ulogic;
         pSampleEn       : in  std_ulogic;
         pTriggersIn     : in  std_logic_vector(15 downto 0);
         pNoTriggersIn   : in  std_logic_vector(15 downto 0);
         pEnable         : in  std_ulogic;
         pStartCount     : in  std_logic_vector(15 downto 0);
         pStopCount      : in  std_logic_vector(15 downto 0);
         pForceStop      : in  std_ulogic;
         pThresPoints    : in  std_logic_vector(2 downto 0);
         pTriggerNum     : in  std_logic_vector(3 downto 0);
         pTriggerMode    : in  std_ulogic;
         pPolarityMode   : in  std_logic_vector(1 downto 0);
         pDistMetric     : in  std_logic_vector(1 downto 0);
         pPeakSelAmp     : in  std_logic_vector(3 downto 0);
         pPeakSelDist    : in  std_logic_vector(3 downto 0);
         pHoldoff        : in  std_logic_vector(6 downto 0);
         pSampleData     : in  std_logic_vector(11 downto 0);
         pRectifiedData  : in  std_logic_vector(10 downto 0);
         pThreshAddr     : out std_logic_vector(11 downto 0);
         pThreshData     : in  std_logic_vector(10 downto 0);
         pGateFiring     : out std_ulogic;
         pGateUnTrigger  : out std_ulogic;
         pGateFired      : out std_ulogic;
         pGateDidNotFire : out std_ulogic;
         pGateOutputData : out std_logic_vector(13 downto 0));
  end component CurvedGate;


  component GateResultSelect
    port(pnReset         : in  std_ulogic;
         pADC_2xClk      : in  std_ulogic;
         pSampleEn       : in  std_ulogic;
         pTriggersIn     : in  std_logic_vector(15 downto 0);
         pUnTriggersIn   : in  std_logic_vector(15 downto 0);
         pNoTriggersIn   : in  std_logic_vector(15 downto 0);
         pReTriggersIn   : in  std_logic_vector(15 downto 0);
         pGateSelect     : in  std_logic_vector(7 downto 0);
         pGateDataIn     : in  tGateData;
         pGateData       : out std_logic_vector(31 downto 0));
  end component GateResultSelect;

  attribute uselowskewlines: string;
  
  signal DebugTest: std_ulogic;

  signal nFpgaCs: std_ulogic;
  attribute uselowskewlines of nFpgaCs : signal is "yes";  -- Use low skew line in Xilinx device
  signal nFpgaCs_NoBuff: std_ulogic;
  signal nLReset: std_ulogic;

  -- Signal Definitions
  signal LD_OE:    std_ulogic;  -- Output enable for LD bus
  signal LD_IN:    std_logic_vector(31 downto 0);  -- LD bus into the FPGA
  signal LD_OUT:   std_logic_vector(31 downto 0);  -- LD bus out of the FPGA

  -- Signals for generating double speed ADC clock
  signal ADC_Clk:          std_ulogic;
  signal ADC_2xClk_NoBuff: std_ulogic;
  signal ADC_2xClkValid:   std_ulogic;
  signal ADC_2xClk:        std_ulogic;  -- Frequency doubled ADC clock
  signal nReset_AdcClk:    std_ulogic;
  attribute uselowskewlines of nReset_AdcClk : signal is "yes";  -- Use low skew line in Xilinx device

  -- ADC data stream made from two ADC data stream inputs
  signal ADC_Data1: std_logic_vector(11 downto 0);  -- Combined ADC data stream
  signal ADC_Data2: std_logic_vector(11 downto 0);  -- Rectified ADC data stream
  signal RectifiedData: std_logic_vector(10 downto 0);  -- Always Rectified ADC data stream
  signal SampleEn:  std_ulogic;

  -- Signals to connect SRAM read module to SRAM switching module
  signal LBusSramDataIn:  std_logic_vector(31 downto 0);
  signal LBusSramAddr:    std_logic_vector(17 downto 0);
  signal LBusSram_nCS:    std_logic_vector(3 downto 0);
  signal LBusSram_nRD:    std_ulogic;

  -- Signals to connect datastream to SRAM switching module
  signal DStreamDataOut:  std_logic_vector(31 downto 0);
  signal DStream_nCS:     std_logic_vector(3 downto 0);
  signal DStreamAddr:     std_logic_vector(17 downto 0);
  signal DStream_nWE:     std_logic_vector(1 downto 0);

  signal DDS_nWR:        std_ulogic;
  signal ResetClkDll:    std_ulogic;

  signal SramA_DataOut:  std_logic_vector(31 downto 0);
  signal SramA_DataIn:   std_logic_vector(31 downto 0);
  signal SramA_DataOE:   std_ulogic;
  signal SramB_DataOut:  std_logic_vector(31 downto 0);
  signal SramB_DataIn:   std_logic_vector(31 downto 0);
  signal SramB_DataOE:   std_ulogic;

  signal SetDataReady:      std_ulogic;
  signal DataReady:         std_ulogic;
  signal SetEarlyTrigError: std_ulogic;
  signal SetDataFullError:  std_ulogic;
  signal EarlyDataReq:      std_ulogic;
  signal SomeDataReady:     std_ulogic;
  signal BScansInSram:      std_logic_vector(14 downto 0);

  signal SampleAdcData:     std_ulogic;
  signal RawAdcData:        std_logic_vector(11 downto 0);

  signal SetNewTrigger:  std_ulogic;
  signal StartSampling:  std_ulogic;
  signal DelayedTrigger: std_ulogic;
  signal AllTriggers:    std_ulogic;
  signal LastTrigger:    std_ulogic;
  signal BScanActive:    std_ulogic;
  signal BScanStart:     std_ulogic;
  signal LastAScan:      std_ulogic;
  signal AScanDone:      std_ulogic;
  signal CaptureDone:    std_ulogic;
  signal AScanNum:       std_logic_vector(6 downto 0);

  signal SramBankSelect:  std_ulogic;
  signal nSramBankSelect: std_ulogic;
  signal RegData:         tRegSet;

  signal TriggerSeen:    std_ulogic;
  signal TriggerPresent: std_ulogic;

  signal GateDataIn:     std_ulogic;
  signal GateEnIn:       std_ulogic;
  signal GateSelIn:      std_logic_vector(2 downto 0);
  signal SerialGateEn:   std_logic_vector(7 downto 0);
  signal SerialGateData: std_ulogic;
  signal Gate0Data:      std_logic_vector(63 downto 0);
  signal Gate1Data:      std_logic_vector(63 downto 0);
  signal Gate2Data:      std_logic_vector(63 downto 0);
  signal Gate3Data:      std_logic_vector(63 downto 0);
  signal Gate4Data:      std_logic_vector(63 downto 0);
  signal Gate5Data:      std_logic_vector(63 downto 0);
  signal Gate6Data:      std_logic_vector(63 downto 0);
  signal Gate7Data:      std_logic_vector(63 downto 0);
  signal Holdoff:        std_logic_vector(6 downto 0);

  signal GateTriggers:   std_logic_vector(15 downto 0);
  signal GateNoTriggers: std_logic_vector(15 downto 0);
  signal GateUnTriggers: std_logic_vector(15 downto 0);
  signal GateReTriggers: std_logic_vector(15 downto 0);
  signal GateOutputData: std_logic_vector(31 downto 0);
  signal GateEnables:    std_logic_vector(7 downto 0);
  signal GateSelect:     std_logic_vector(7 downto 0);
  signal GateData:       tGateData;
  signal ResetAScanAddr: std_ulogic;
  signal ResetCScanAddr: std_ulogic;
  signal ResetElemNum:   std_ulogic;
  signal ResetSampling:  std_ulogic;
  signal ResetSampling_2xClk: std_ulogic;
  signal ForceTrigger:   std_ulogic;
  signal TriggerIn:      std_ulogic;
  signal Debug:          std_logic_vector(31 downto 0);

  signal DAC_Sel:        std_ulogic;  -- Local bus has control of DAC SRAM when '1'
  signal DACA1:          std_logic_vector(17 downto 0);
  signal DACA2:          std_logic_vector(17 downto 0);
  signal DacClk:         std_ulogic;
  signal DacWr:          std_ulogic;
  signal DACD:           std_logic_vector(15 downto 0);

  signal CurveWr:        std_ulogic;
  signal CurveAddr:      std_logic_vector(11 downto 0);
  signal CurveData:      std_logic_vector(10 downto 0);
  signal ThreshAddr:     std_logic_vector(11 downto 0);
  signal ThreshData:     std_logic_vector(10 downto 0);

  signal EncResultData:  std_logic_vector(191 downto 0);
  signal ElementNum:     std_logic_vector(6 downto 0);

  signal Z1:  std_ulogic;
  signal Z2:  std_ulogic;

  signal SyncPulse:    std_ulogic;
  signal SyncPulseEn:  std_ulogic;

  signal Test0:  std_ulogic;
  signal Test1:  std_ulogic;

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

begin

  pZ9 <= pTrigIn;

  -- generate SyncPulse enabled by register bit
  GenSyncPulseEn: process(ADC_2xClk)
  begin
    if rising_edge(ADC_2xClk) then
      SyncPulseEn <= RegData(cSramCtrlNoScans)(27);
    end if;
  end process GenSyncPulseEn;

  SyncPulse <= BScanStart and SyncPulseEn;

  -- Produce >100us pulse on the sync output for each B-Scan
  StrobeExtender1: StrobeExtender
    generic map(gLfsrBits => 14)
    port map(pnReset    => nLReset,
             pClk       => ADC_2xClk,
             pStrobeIn  => SyncPulse,
             pStrobeOut => pSYNC);

  -- Tie the ADC Enable active
  pADC_En <= cVcc;

  -- Tie the pDACSLEEP output to Gnd
  pDACSLEEP <= cGnd;

  -- Generate the bi-directional bus pLD
  pLD <= LD_OUT when LD_OE = '1' else (others => 'Z');
  LD_IN <= pLD;

  -- Generate the tri-stateable pSramB_Data signal
  pSramA_Data <= SramA_DataOut when SramA_DataOE = '1' else (others => 'Z');

  -- Generate the tri-stateable pSramB_Data signal
  pSramB_Data <= SramB_DataOut when SramB_DataOE = '1' else (others => 'Z');

--  -- Instantiate an IBUF to prevent synthesis tool from assuming an IBUFG
--  IBUF0: IBUF
--    port map(I   => pnFpgaCs,
--             O   => nFpgaCs_NoBuff);
--  nFpgaCs <= nFpgaCs_NoBuff;
  nFpgaCs <= pnFpgaCs;

  IBUF1: IBUF
    port map(I   => pnLReset,
             O   => nLReset);

  --
  -- Instantiate components to produce frequency doubled pADC_Clk
  -- Start
  --
  IBUFG0: IBUFG
    port map(I   => pADC_Clk,
             O   => ADC_Clk);

  pZ0 <= ResetClkDll;  -- Pass signal to Peripheral FPGA

  CLKDLL0: CLKDLL
    port map(CLKIN  => ADC_Clk,
             CLKFB  => ADC_2xClk,
             RST    => ResetClkDll,
             CLK0   => open,
             CLK90  => open,
             CLK180 => open,
             CLK270 => open,
             CLK2X  => ADC_2xClk_NoBuff,
             CLKDV  => open,
             LOCKED => ADC_2xClkValid);

  BUFG0: BUFG
    port map(I   => ADC_2xClk_NoBuff,
             O   => ADC_2xClk);
  --
  -- Instantiate components to produce frequency doubled pADC_Clk
  -- Done
  --

  -- Create an asynchronous reset signal for circuits using the ADC_2xClk
  -- Is is required to hold this circuitry in reset until the clock is locked
  -- because the white noise type signal that comes through before it has locked
  -- can lock up the circuitry.
  GenResetSampling_2xClk: process(ADC_2xClk)
    variable vResetSampling: std_ulogic;
  begin
    if rising_edge(ADC_2xClk) then
      -- Double clock signal into ADC_2xClk domain
      ResetSampling_2xClk <= vResetSampling;
      vResetSampling      := (ResetSampling or GateEnIn);
    end if;
  end process GenResetSampling_2xClk;

  nReset_AdcClk <= '0' when nLReset = '0' or ADC_2xClkValid = '0'or ResetSampling_2xClk = '1' else '1';



  TriggerIn <= pZ10 or ForceTrigger;

  TriggerGenerator0: TriggerGenerator
    port map(pnReset            => nReset_AdcClk,
             pADC_2xClk         => ADC_2xClk,
             pSampleEn          => SampleEn,
             pTriggerIn         => TriggerIn,
             pTriggerOut        => StartSampling,
             pAllTriggersOut    => AllTriggers,
             pCaptureDone       => CaptureDone,
             pDataReady         => DataReady,
             pSetDataReady      => SetDataReady,
             pSetEarlyTrigError => SetEarlyTrigError,
             pSetDataFullError  => SetDataFullError,
             pSomeDataReady     => SomeDataReady,
             pBScansAvailable   => BScansInSram,
             pEarlyDataReq      => EarlyDataReq,
             pAScansPerBScan    => RegData(cSramCtrlNoScans)(6 downto 0),
             pNumOfBScans       => RegData(cSramCtrlNoScans)(22 downto 8),
             pStorageMode       => RegData(cSramCtrlNoScans)(31 downto 30),
             pAScanNum          => AScanNum,
             pBScanActive       => BScanActive,
             pAllBScanActive    => pz8,
             pBScanStart        => BScanStart,
             pLastAScan         => LastAScan,
             pResetElemNum      => ResetElemNum,
             pResetAScanAddr    => ResetAScanAddr,
             pResetCScanAddr    => ResetCScanAddr,
             pSramBankSelect    => SramBankSelect,
             pnSramBankSelect   => nSramBankSelect,
             pTest0             => Test0,
             pTest1             => Test1);

  DelayedTrigger <= StartSampling;

--  pZ8 <= BScanActive;

  -- Instantiate other Components
  DataInterleave0: DataInterleave
    port map(pnReset         => nLReset,--nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pADC_2xClkValid => ADC_2xClkValid,
             pADC_DataA      => pADC_DataA,
             pADC_DataB      => pADC_DataB,
             pADC_DataOut    => ADC_Data1);


  DataRectifier0: DataRectifier
    port map(pnReset       => nReset_AdcClk,
             pADC_2xClk    => ADC_2xClk,
             pDropSamples  => RegData(cSramCtrlSampleCtrl)(19 downto 16),
             pMode         => RegData(cRectifierMode)(1 downto 0),
             p8BitValues   => RegData(cRectifierMode)(2),
             pDataIn       => ADC_Data1,
             pSampleEn     => SampleEn,
             pDataOut      => ADC_Data2,
             pRectifiedOut => RectifiedData);


  -- Process to detect edge of pZ10 (Trigger signal from Peripheral FPGA)
  -- Including clocking into pLCLK domain
  -- This creates signal 'SetNewTrigger' which is used to set the 'New
  -- Trigger Seen' bit in the Data Sampling Status Register.
  GenSetNewTrigger: process(nLReset, pLCLK)
    variable vTriggerDelayed: std_logic_vector(2 downto 0);
  begin
    if nLReset = '0' then
      vTriggerDelayed := "000";
      SetNewTrigger   <= '0';

    elsif rising_edge (pLCLK) then
      SetNewTrigger <= '0';

      if vTriggerDelayed(2) = '0' and vTriggerDelayed(1) = '1' then
        -- Rising edge of pZ10
        SetNewTrigger <= '1';
      end if;

      -- Clock pZ10 through 3 D-types
      vTriggerDelayed(2) := vTriggerDelayed(1);
      vTriggerDelayed(1) := vTriggerDelayed(0);
      vTriggerDelayed(0) := pZ10;
    end if;
  end process GenSetNewTrigger;


  LBusInterface0: LBusInterface
    port map(pnReset              => nLReset,
             pLClk                => pLCLK,
             pnFPGACS             => nFpgaCs,
             pLAin                => pLA,
             pLDin                => LD_IN,
             pLDout               => LD_OUT,
             pLDoutput_enable     => LD_OE,
             pLWnR                => pLWnR,
             pnIRQ0               => pnIRQ0,
             --
             pResetClkDll         => ResetClkDll,
             --
             pSram_nCS            => LBusSram_nCS,
             pSram_nRD            => LBusSram_nRD,
             pSramData            => LBusSramDataIn,
             pSramAddr            => LBusSramAddr,
             --
             pDDS_addr            => pDDSA,
             pDDS_data            => pDDSD,
             pDDS_wr              => DDS_nWR,
             pDDS_reset           => pDDSRESET,
             pDDS_IO              => pDDS_IO,
             --
             pDACA                => DACA1,
             pDACD                => DACD,
             pDACnWR              => pDACnWR,
             pDAC_Sel             => DAC_Sel,
             --
             pCurveWr             => CurveWr,
             pCurveAddr           => CurveAddr,
             pCurveData           => CurveData,
             --
             pBScansInSram        => BScansInSram,
             --
             pSampleAdcData       => SampleAdcData,
             pRawAdcData          => RawAdcData,
             --
             pSetDataReady        => SetDataReady,
             pSetNewTrigger       => SetNewTrigger,
             pSetEarlyTrigError   => SetEarlyTrigError,
             pSetDataFullError    => SetDataFullError,
             pSomeDataReady       => SomeDataReady,
             pDataReady           => DataReady,
             pEarlyDataReq        => EarlyDataReq,
             pResetSampling       => ResetSampling,
             pForceTrigger        => ForceTrigger,
             pAdc2xClkValid       => ADC_2xClkValid,
             pDebug               => Debug,
             pRegData             => RegData);

  -- Connect internal signal to pDDS_nWR output
  pDDS_nWR <= DDS_nWR;


  -- Generate the raw data samples for direct register reads
  GenRawDataSamples: process(nLReset, ADC_2xClk)
    variable vSampleData: std_logic_vector(2 downto 0);
  begin
    if nLReset = '0' then
      vSampleData := "000";
      RawAdcData  <= X"000";
    elsif rising_edge(ADC_2xClk) then
      -- Latch sample data on rising edge of control signal
      if vSampleData(2 downto 1) = "01" then
        RawAdcData <= ADC_Data1;
      end if;

      -- Clock control signal into ADC_2xClk domain and once more to detect
      -- rising edge
      vSampleData := vSampleData(1 downto 0) & SampleAdcData;
    end if;
  end process GenRawDataSamples;


  TcgCtrl0: TcgCtrl
    port map(--
             pnReset        => nReset_AdcClk,
             pADC_2xClk     => ADC_2xClk,
             pTcgEnable     => RegData(cTcgConfig)(1),
             pNumOfSamples  => RegData(cSramCtrlSampleCtrl)(13 downto 0),
             pTriggersIn    => GateTriggers,
             pTriggerNum    => RegData(cTcgConfig)(0),
             pElemSelBits   => RegData(cTcgConfig)(3 downto 2),
             pAScanNum      => AScanNum,
             pTcgApplyTime  => RegData(cTcgConfig)(7 downto 4),
             pCaptureDone   => CaptureDone,
             --
             pDACA          => DACA2,
             --
             DACWRT         => DacWr,
             DACCLK         => DacClk,
             Test           => open);

  pDACnRD <= DAC_Sel;
  pDACA <= DACA1 when DAC_Sel = '1' else (others => 'Z');
  pDACA <= DACA2 when DAC_Sel = '0' else (others => 'Z');
  pDAC1WRT <= DacWr;
  pDAC2WRT <= DacWr;
  pDACCLK  <= DacClk;
  pDACD <= DACD when DAC_Sel = '1' else (others => 'Z');


  DualPortRam0: DualPortRam
    generic map(gAddressWidth  => 12,
                gDataWidth     => 11)
    port map(pClk       => pLCLK,
             pWriteEn   => CurveWr,
             pAddr      => CurveAddr,
             pDataIn    => CurveData,
             pDataOut   => open,
             pDpClk     => ADC_2xClk,
             pDpAddr    => ThreshAddr,
             pDpDataOut => ThreshData);


  -- Generate the gate data from the serial datastream
  GenGateData: process(nLReset, pLCLK)
  begin
    if nLReset = '0' then
      GateDataIn <= '0';
      GateEnIn   <= '0';
      GateSelIn  <= "000";

      SerialGateData <= '0';
      SerialGateEn   <= X"00";

    elsif rising_edge(pLCLK) then
      -- Register Inputs to ease timings
      GateDataIn <= pZ3;
      GateEnIn   <= pZ4;
      GateSelIn  <= pZ7 & pZ6 & pZ5;

      SerialGateData <= GateDataIn;
      SerialGateEn <= X"00";
      if GateEnIn = '1' then
        case GateSelIn is
          when "000" => SerialGateEn(0) <= '1';
          when "001" => SerialGateEn(1) <= '1';
          when "010" => SerialGateEn(2) <= '1';
          when "011" => SerialGateEn(3) <= '1';
          when "100" => SerialGateEn(4) <= '1';
          when "101" => SerialGateEn(5) <= '1';
          when "110" => SerialGateEn(6) <= '1';
          when "111" => SerialGateEn(7) <= '1';
          when others => null;
        end case;
      end if;
    end if;
  end process GenGateData;


  -- Generate the gate data
  -- No reset condition to allow Xilinx shift regs to be used and
  -- reduce area
  process(pLCLK)
  begin
    if rising_edge(pLCLK) then
      if SerialGateEn(0) = '1' then
        Gate0Data <= Gate0Data(62 downto 0) & SerialGateData;
      end if;
      if SerialGateEn(1) = '1' then
        Gate1Data <= Gate1Data(62 downto 0) & SerialGateData;
      end if;
      if SerialGateEn(2) = '1' then
        Gate2Data <= Gate2Data(62 downto 0) & SerialGateData;
      end if;
      if SerialGateEn(3) = '1' then
        Gate3Data <= Gate3Data(62 downto 0) & SerialGateData;
      end if;
      if SerialGateEn(4) = '1' then
        Gate4Data <= Gate4Data(62 downto 0) & SerialGateData;
      end if;
      if SerialGateEn(5) = '1' then
        Gate5Data <= Gate5Data(62 downto 0) & SerialGateData;
      end if;
      if SerialGateEn(6) = '1' then
        Gate6Data <= Gate6Data(62 downto 0) & SerialGateData;
      end if;
      if SerialGateEn(7) = '1' then
        Gate7Data <= Gate7Data(62 downto 0) & SerialGateData;
      end if;
    end if;
  end process;

  GateEnables(0) <= Gate0Data(23);
  GateEnables(1) <= Gate1Data(23);
  GateEnables(2) <= Gate2Data(23);
  GateEnables(3) <= Gate3Data(23);
  GateEnables(4) <= Gate4Data(23);
  GateEnables(5) <= Gate5Data(23);
  GateEnables(6) <= Gate6Data(23);
  GateEnables(7) <= Gate7Data(23);


  -- No reset condition to make use of IOB FFs
  GenZ1andZ2: process(pLCLK)
  begin
    if rising_edge(pLCLK) then
      Z1 <= pZ1;
      Z2 <= pZ2;
    end if;
  end process GenZ1andZ2;


  -- Shift in the Results from the Shaft encoders from the Peripheral FPGA
  GenEncResultData: process(nLReset, pLCLK)
    variable vZ1, vZ2: std_ulogic;
  begin
      if nLReset = '0' then
        vZ1 := '0';
        vZ2 := '0';
        EncResultData(31 downto 0)    <= X"01020304";
        EncResultData(63 downto 32)   <= X"05060708";
        EncResultData(95 downto 64)   <= X"090A0B0C";
        EncResultData(127 downto 96)  <= X"0D0E0F00";
        EncResultData(159 downto 128) <= X"11121314";
        EncResultData(191 downto 160) <= X"15161718";
        ElementNum <= "0000000";
      elsif rising_edge(pLCLK) then
        if vZ1 = '1' then
          EncResultData <= EncResultData(190 downto 0) & vZ2;
        end if;

        -- Put both signals through a couple of registers to ease placement and routing
        vZ2 := Z2;
        vZ1 := Z1;
      end if;
  end process GenEncResultData;


  LastTrigger <= LastAScan when pZ11 = '1' else '0';

  SramWriteCtrl0: SramWriteCtrl
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pADC_Data       => ADC_Data2,
             pSampleEn       => SampleEn,
             pAllTriggers    => AllTriggers,
             pLastTrigger    => LastTrigger,
             pBScanActive    => BScanActive,
             pLastAScan      => LastAScan,
             pAScanDone      => AScanDone,
             pGateEnables    => GateEnables,
             pStartCapture   => DelayedTrigger,
             pCaptureDone    => CaptureDone,
             p12BitPack      => '0',
             p8BitStore      => '0',
             p8BitValues     => RegData(cRectifierMode)(2),
             pNumOfSamples   => RegData(cSramCtrlSampleCtrl)(14 downto 0),
             pCScanStartAddr => RegData(cCScanDataSramBase)(21 downto 2),
             pStorageMode    => RegData(cSramCtrlNoScans)(31 downto 30),
             pResetElemNum   => ResetElemNum,
             pResetAScanAddr => ResetAScanAddr,
             pResetCScanAddr => ResetCScanAddr,
             pEnc0Data       => EncResultData(31 downto 0),
             pEnc1Data       => EncResultData(63 downto 32),
             pEnc2Data       => EncResultData(95 downto 64),
             pEnc3Data       => EncResultData(127 downto 96),
             pEnc4Data       => EncResultData(159 downto 128),
             pEnc5Data       => EncResultData(191 downto 160),
             pGateData       => GateOutputData,
             pGateSelect     => GateSelect,
             pSram_nCS       => DStream_nCS,
             pSram_nWEEn     => SramBankSelect,
             pSram_nWE       => DStream_nWE,
             pSramData       => DStreamDataOut,
             pSramAddr       => DStreamAddr);

  SramA_DataIn <= pSramA_Data;
  SramB_DataIn <= pSramB_Data;

  SramSwitching0: SramSwitching
    port map(pBankAnB_Active =>  SramBankSelect,
             pBankBnA_Active =>  nSramBankSelect,
             -- Inputs to/from datastream storing logic
             pDStreamAddr     => DStreamAddr,
             pDStreamDataOut  => DStreamDataOut,
             pDStream_nWE     => DStream_nWE,
             pDStream_nCS     => DStream_nCS,
             -- Inputs to/from local bus
             pLBusSramAddr    => LBusSramAddr,
             pLBusSramDataOE  => cGnd,  -- Local bus is always reading from SRAM
             pLBusSramDataIn  => LBusSramDataIn,
             pLBusSram_nRD    => LBusSram_nRD,
             pLBusSram_nCS    => LBusSram_nCS,
             -- Outputs to/for SRAM bank A
             pSramA_Addr      => pSramA_Addr,
             pSramA_DataOut   => SramA_DataOut,
             pSramA_DataOE    => SramA_DataOE,
             pSramA_DataIn    => SramA_DataIn,
             pSramA_nWE       => pSramA_nWE,
             pSramA_nRD       => pSramA_nRD,
             pSramA_nCS       => pSramA_nCS,
             -- Outputs to/for SRAM bank B
             pSramB_Addr      => pSramB_Addr,
             pSramB_DataOut   => SramB_DataOut,
             pSramB_DataOE    => SramB_DataOE,
             pSramB_DataIn    => SramB_DataIn,
             pSramB_nWE       => pSramB_nWE,
             pSramB_nRD       => pSramB_nRD,
             pSramB_nCS       => pSramB_nCS);


  GateTriggers(15)   <= StartSampling;
  GateNoTriggers(15) <= cGnd;  -- Delayed trigger will always trigger

  InterfaceGate0: InterfaceGate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTrigger        => StartSampling,
             pEnable         => GateEnables(0),--Gate0Data(23),
             pStartCount     => Gate0Data(47 downto 32),
             pStopCount      => Gate0Data(63 downto 48),
             pThreshold      => Gate0Data(10 downto 0),
             pTriggerMode    => Gate0Data(20),
             pPolarityMode   => Gate0Data(19 downto 18),
             pRectifiedData  => RectifiedData,
             pPolarity       => ADC_Data2(11),
             pGateFiring     => GateTriggers(0),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(0),
             pGateOutputData => GateData(0));

             GateUnTriggers(0) <= '0';
             GateReTriggers(0) <= '0';

  -- Trailing edge holdoff is only present in version 1 of the DSP FPGA
  Holdoff <= RegData(cTrailingHoldoff)(6 downto 0);-- when cFpgaVersion = X"1" else "0000000";

  Gate1: Gate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(1),--Gate1Data(23),
             pStartCount     => Gate1Data(47 downto 32),
             pStopCount      => Gate1Data(63 downto 48),
             pForceStop      => AScanDone,
             pThreshold      => Gate1Data(10 downto 0),
             pTriggerNum     => Gate1Data(15 downto 12),
             pTriggerMode    => Gate1Data(20),
             pZeroCrossMode  => Gate1Data(16),
             pPolarityMode   => Gate1Data(19 downto 18),
             pDistMetric     => Gate1Data(22 downto 21),
             pPeakSelAmp     => Gate1Data(27 downto 24),
             pPeakSelDist    => Gate1Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pGateFiring     => GateTriggers(1),
             pGateUnTrigger  => GateUnTriggers(1),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(1),
             pGateReFire     => GateReTriggers(1),
             pGateOutputData => GateData(1));

  Gate2: Gate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(2),--Gate2Data(23),
             pStartCount     => Gate2Data(47 downto 32),
             pStopCount      => Gate2Data(63 downto 48),
             pForceStop      => AScanDone,
             pThreshold      => Gate2Data(10 downto 0),
             pTriggerNum     => Gate2Data(15 downto 12),
             pTriggerMode    => Gate2Data(20),
             pZeroCrossMode  => Gate2Data(16),
             pPolarityMode   => Gate2Data(19 downto 18),
             pDistMetric     => Gate2Data(22 downto 21),
             pPeakSelAmp     => Gate2Data(27 downto 24),
             pPeakSelDist    => Gate2Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pGateFiring     => GateTriggers(2),
             pGateUnTrigger  => GateUnTriggers(2),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(2),
             pGateReFire     => GateReTriggers(2),
             pGateOutputData => GateData(2));

  Gate3: Gate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(3),--Gate1Data(23),
             pStartCount     => Gate3Data(47 downto 32),
             pStopCount      => Gate3Data(63 downto 48),
             pForceStop      => AScanDone,
             pThreshold      => Gate3Data(10 downto 0),
             pTriggerNum     => Gate3Data(15 downto 12),
             pTriggerMode    => Gate3Data(20),
             pZeroCrossMode  => Gate3Data(16),
             pPolarityMode   => Gate3Data(19 downto 18),
             pDistMetric     => Gate3Data(22 downto 21),
             pPeakSelAmp     => Gate3Data(27 downto 24),
             pPeakSelDist    => Gate3Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pGateFiring     => GateTriggers(3),
             pGateUnTrigger  => GateUnTriggers(3),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(3),
             pGateReFire     => GateReTriggers(3),
             pGateOutputData => GateData(3));

  Gate4: Gate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(4),--Gate4Data(23),
             pStartCount     => Gate4Data(47 downto 32),
             pStopCount      => Gate4Data(63 downto 48),
             pForceStop      => AScanDone,
             pThreshold      => Gate4Data(10 downto 0),
             pTriggerNum     => Gate4Data(15 downto 12),
             pTriggerMode    => Gate4Data(20),
             pZeroCrossMode  => Gate4Data(16),
             pPolarityMode   => Gate4Data(19 downto 18),
             pDistMetric     => Gate4Data(22 downto 21),
             pPeakSelAmp     => Gate4Data(27 downto 24),
             pPeakSelDist    => Gate4Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pGateFiring     => GateTriggers(4),
             pGateUnTrigger  => GateUnTriggers(4),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(4),
             pGateReFire     => GateReTriggers(4),
             pGateOutputData => GateData(4));

  Gate5: Gate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(5),--Gate5Data(23),
             pStartCount     => Gate5Data(47 downto 32),
             pStopCount      => Gate5Data(63 downto 48),
             pForceStop      => AScanDone,
             pThreshold      => Gate5Data(10 downto 0),
             pTriggerNum     => Gate5Data(15 downto 12),
             pTriggerMode    => Gate5Data(20),
             pZeroCrossMode  => Gate5Data(16),
             pPolarityMode   => Gate5Data(19 downto 18),
             pDistMetric     => Gate5Data(22 downto 21),
             pPeakSelAmp     => Gate5Data(27 downto 24),
             pPeakSelDist    => Gate5Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pGateFiring     => GateTriggers(5),
             pGateUnTrigger  => GateUnTriggers(5),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(5),
             pGateReFire     => GateReTriggers(5),
             pGateOutputData => GateData(5));

  Gate6: Gate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(6),--Gate6Data(23),
             pStartCount     => Gate6Data(47 downto 32),
             pStopCount      => Gate6Data(63 downto 48),
             pForceStop      => AScanDone,
             pThreshold      => Gate6Data(10 downto 0),
             pTriggerNum     => Gate6Data(15 downto 12),
             pTriggerMode    => Gate6Data(20),
             pZeroCrossMode  => Gate6Data(16),
             pPolarityMode   => Gate6Data(19 downto 18),
             pDistMetric     => Gate6Data(22 downto 21),
             pPeakSelAmp     => Gate6Data(27 downto 24),
             pPeakSelDist    => Gate6Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pGateFiring     => GateTriggers(6),
             pGateUnTrigger  => GateUnTriggers(6),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(6),
             pGateReFire     => GateReTriggers(6),
             pGateOutputData => GateData(6));

GenLastGate0: if cFpgaVersion = X"0" generate
begin
  -- Version 0 of the FPGA, last gate is a curved gate
  Gate7: CurvedGate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(7),
             pStartCount     => Gate7Data(47 downto 32),
             pStopCount      => Gate7Data(63 downto 48),
             pForceStop      => AScanDone,
             pThresPoints    => Gate7Data(2 downto 0),
             pTriggerNum     => Gate7Data(15 downto 12),
             pTriggerMode    => Gate7Data(20),
             pPolarityMode   => Gate7Data(19 downto 18),
             pDistMetric     => Gate7Data(22 downto 21),
             pPeakSelAmp     => Gate7Data(27 downto 24),
             pPeakSelDist    => Gate7Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pThreshAddr     => ThreshAddr,
             pThreshData     => ThreshData,
             pGateFiring     => GateTriggers(7),
             pGateUnTrigger  => GateUnTriggers(7),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(7),
             pGateOutputData => GateData(7));

  GateReTriggers(7) <= '0';
end generate;
GenLastGate1: if cFpgaVersion = X"1" generate
begin
  -- Version 1 and 2  of the FPGA, last gate is a standard gate
  Gate7: Gate
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pEnable         => GateEnables(7),
             pStartCount     => Gate7Data(47 downto 32),
             pStopCount      => Gate7Data(63 downto 48),
             pForceStop      => AScanDone,
             pThreshold      => Gate7Data(10 downto 0),
             pTriggerNum     => Gate7Data(15 downto 12),
             pTriggerMode    => Gate7Data(20),
             pZeroCrossMode  => Gate7Data(16),
             pPolarityMode   => Gate7Data(19 downto 18),
             pDistMetric     => Gate7Data(22 downto 21),
             pPeakSelAmp     => Gate7Data(27 downto 24),
             pPeakSelDist    => Gate7Data(31 downto 28),
             pHoldoff        => Holdoff,
             pSampleData     => ADC_Data2,
             pRectifiedData  => RectifiedData,
             pGateFiring     => GateTriggers(7),
             pGateUnTrigger  => GateUnTriggers(7),
             pGateFired      => open,
             pGateDidNotFire => GateNoTriggers(7),
             pGateReFire     => GateReTriggers(7),
             pGateOutputData => GateData(7));
end generate;


  GateResultSelect0: GateResultSelect
    port map(pnReset         => nReset_AdcClk,
             pADC_2xClk      => ADC_2xClk,
             pSampleEn       => SampleEn,
             pTriggersIn     => GateTriggers,
             pUnTriggersIn   => GateUnTriggers,
             pNoTriggersIn   => GateNoTriggers,
             pReTriggersIn   => GateReTriggers,
             pGateSelect     => GateSelect,
             pGateDataIn     => GateData,
             pGateData       => GateOutputData);


  -- Clock external trigger signal into LCLK domain
  DetectTrigger: process(nLReset, pLCLK)
    variable vTriggerDelayed: std_logic_vector(2 downto 0);
  begin
    if nLReset = '0' then
      TriggerSeen     <= '0';
      vTriggerDelayed := "000";
    elsif rising_edge(pLCLK) then
      -- Clock pTrigIn through 2 D-types and detect rising edge
      if vTriggerDelayed(2 downto 1) = "01" then
        TriggerSeen <= '1';
      else
        TriggerSeen <= '0';
      end if;
      vTriggerDelayed := vTriggerDelayed(1 downto 0) & pTrigIn;
    end if;
  end process DetectTrigger;


  -- Generate a 15 ms pulse each time a new trigger is seen
  StrobeExtender0: StrobeExtender
    generic map(gLfsrBits => 20)
    port map(pnReset    => nLReset,
             pClk       => pLCLK,
             pStrobeIn  => SetNewTrigger, --TriggerSeen,
             pStrobeOut => TriggerPresent);

  pLED0 <= not ADC_2xClkValid;  -- Light LED 0 when the ADC clock doubler has stabalised
--  pLED1 <= not TriggerPresent;  -- Light LED 1 for 1/4 second each time a new trigger is seen

--  pLED0 <= not Test0;
  pLED1 <= not Test1;

end architecture Rtl;