---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: InterfaceGate.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card DSP FPGA
--
-- Design Description:
-- Module to to implement Interface Gate
--
---------------------------------------------------------------------------

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

entity InterfaceGate is
  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 entity InterfaceGate;


architecture Rtl of InterfaceGate is

  signal DelayedSampleEn: std_ulogic;

  signal Trigger:        std_ulogic;
  signal SampleEarly:    std_logic_vector(10 downto 0);
  signal Polarity:       std_ulogic;
  signal SampleData:     std_logic_vector(10 downto 0);
  signal TimeCount:      std_logic_vector(14 downto 0);
  signal GateOpen:       std_ulogic;
  signal GateClose:      std_ulogic;
  signal GateActive:     std_ulogic;
  signal GateFiring:     std_ulogic;
  signal GateFired:      std_ulogic;
  signal GateDidNotFire: std_ulogic;

  signal InterfacePeak:     std_ulogic;
  signal InterfacePeakDone: std_ulogic;

  signal DataLessThreshold: std_ulogic;
  signal LastLessThreshold: std_ulogic;

  signal MaxDataValue: std_logic_vector(11 downto 0);
  signal GateFireTime: std_logic_vector(15 downto 0);

  signal StatusNibble: std_logic_vector(3 downto 0);

begin

  RegisterSampleData: process(pnReset, pADC_2xClk)
  begin
    if pnReset = '0' then
      Trigger     <= '0';
      SampleEarly <= "00000000000";
      Polarity    <= '0';
      SampleData  <= "00000000000";

      DelayedSampleEn <= '0';
    elsif rising_edge(pADC_2xClk) then
      if pSampleEn = '1' then
        Trigger     <= pTrigger;
      end if;

      if DelayedSampleEn = '1' then
        SampleEarly <= pRectifiedData;
        Polarity <= pPolarity;

        if pPolarityMode = "10"  then -- -Ve threshold
          if Polarity = '1' then  -- -ve Sample
            SampleData <= SampleEarly;
          else
            SampleData <= (others => '0');
          end if;
        else   -- +Ve threshold
          if Polarity = '0' then  -- +Ve Sample
            SampleData <= SampleEarly;
          else
            SampleData <= (others => '0');
          end if;
        end if;
      end if;

      DelayedSampleEn <= pSampleEn;
    end if;
  end process RegisterSampleData;


  GenGateActive: process(pnReset, pADC_2xClk)
  begin
    if pnReset = '0' then
      TimeCount   <= (others => '1');
      GateOpen    <= '0';
      GateClose   <= '0';
      GateActive  <= '0';
    elsif rising_edge(pADC_2xClk) then
      if pSampleEn = '1' then
        GateOpen  <= '0';
        GateClose <= '0';

        if TimeCount = pStopCount(14 downto 0) then
          -- Gate has closed
          GateClose <= '1';
          GateActive  <= '0';
        elsif TimeCount = pStartCount(14 downto 0) then
          -- Gate has become active
          GateOpen    <= '1';
          GateActive  <= '1';
        end if;

        if Trigger = '1' then
          TimeCount <= (others => '0');
        elsif TimeCount /= "111111111111111" then
          TimeCount <= unsigned(TimeCount) + 1;
        end if;
      end if;
    end if;
  end process GenGateActive;


  GenGateOutputs: process(pnReset, pADC_2xClk)
  begin
    if pnReset = '0' then
      GateFired      <= '0';
      GateFiring     <= '0';
      GateDidNotFire <= '0';
      InterfacePeakDone <= '0';
    elsif rising_edge(pADC_2xClk) then
      if pSampleEn = '1' then
        GateFiring <= '0';

        if Trigger = '1' then
          GateFired      <= '0';
          GateDidNotFire <= '0';

        elsif pTriggerMode = '1' and GateActive = '1' and GateFired = '0' and
              LastLessThreshold = '1' and DataLessThreshold = '0' then
          GateFired       <= '1';
          GateFiring      <= '1';

        elsif pTriggerMode = '0' and GateActive = '1' and GateFired = '0' and
              DataLessThreshold = '0' then
          GateFired       <= '1';
          GateFiring      <= '1';

        elsif GateClose = '1' and GateFired = '0' then
          GateDidNotFire <= '1';
        end if;


        if Trigger = '1' then
          InterfacePeakDone <= '0';
        elsif GateFired = '1' and DataLessThreshold = '1' then
          -- Sample data has dropped below threshold
          InterfacePeakDone <= '1';
        end if;

      end if;
    end if;
  end process GenGateOutputs;

  pGateFiring     <= '0' when pEnable = '0' else GateFiring;
  pGateFired      <= '0' when pEnable = '0' else GateFired;
  pGateDidNotFire <= '1' when pEnable = '0' else GateDidNotFire;


  AnalyseDatastream:  process(pnReset, pADC_2xClk)
    variable vLastSampleData: std_logic_vector(11 downto 0);
  begin
    if pnReset = '0' then
      DataLessThreshold <= '0';
      LastLessThreshold <= '0';
      MaxDataValue      <= X"000";
      GateFireTime      <= X"0000";
      vLastSampleData   := X"000";
    elsif rising_edge(pADC_2xClk) then
      if pSampleEn = '1' then
        if SampleData < pThreshold then
          DataLessThreshold <= '1';
        else
          DataLessThreshold <= '0';
        end if;

        LastLessThreshold <= DataLessThreshold;

        if GateFired = '0' then
          MaxDataValue <= vLastSampleData;

        elsif GateActive = '1' and InterfacePeakDone = '0' then
          if SampleData > MaxDataValue(10 downto 0) then
            MaxDataValue  <= '0' & SampleData;
            InterfacePeak <= '1';
          end if;
        end if;

        if GateFiring = '1' then
          GateFireTime <= '0' & TimeCount;
        end if;

        vLastSampleData := '0' & SampleData;
      end if;

    end if;
  end process AnalyseDatastream;

  -- Generate the status nibble
  StatusNibble(0) <= GateFired;
  StatusNibble(1) <= GateFired;
  StatusNibble(3 downto 2) <= "10";

  pGateOutputData <= StatusNibble(1 downto 0) & MaxDataValue;


end architecture Rtl;