---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2008
--
-- 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(nReset         : in  std_ulogic;
       Clk            : in  std_ulogic;
       SampleEn       : in  std_ulogic;
       TriggerIn      : in  std_ulogic;
       Enable         : in  std_ulogic;
       StartCount     : in  std_logic_vector(23 downto 0);
       StopCount      : in  std_logic_vector(23 downto 0);
       Threshold      : in  std_logic_vector(10 downto 0);
       TriggerMode    : in  std_ulogic;
       PolarityMode   : in  std_logic_vector(1 downto 0);
       RectifiedData  : in  std_logic_vector(10 downto 0);
       PolarityIn     : in  std_ulogic;
       GateFiring     : out std_ulogic;
       GateFired      : out std_ulogic;
       GateDidNotFire : out std_ulogic;
       GateOutputData : 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(23 downto 0);
  signal GateOpen:       std_ulogic;
  signal GateClose:      std_ulogic;
  signal GateActive:     std_ulogic;
  signal iGateFiring:    std_ulogic;
  signal iGateFired:     std_ulogic;
  signal iGateDidNotFire: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 StatusNibble: std_logic_vector(3 downto 0);

begin

  RegisterSampleData: process(nReset, Clk)
  begin
    if nReset = '0' then
      Trigger     <= '0';
      SampleEarly <= (others => '0');
      Polarity    <= '0';
      SampleData  <= (others => '0');

      DelayedSampleEn <= '0';
    elsif rising_edge(Clk) then
      if SampleEn = '1' then
        Trigger     <= TriggerIn;
--      end if;

--      if DelayedSampleEn = '1' then
        SampleEarly <= RectifiedData;
        Polarity <= PolarityIn;

        if PolarityMode = "00" then  -- Bipolar mode
          SampleData <= SampleEarly;
        elsif PolarityMode = "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 <= SampleEn;
    end if;
  end process RegisterSampleData;


  GenGateActive: process(nReset, Clk)
  begin
    if nReset = '0' then
      TimeCount   <= (others => '1');
      GateOpen    <= '0';
      GateClose   <= '0';
      GateActive  <= '0';
    elsif rising_edge(Clk) then
      if SampleEn = '1' then
        GateOpen  <= '0';
        GateClose <= '0';

        if TimeCount = StopCount then
          -- Gate has closed
          GateClose <= '1';
          GateActive  <= '0';
        elsif TimeCount = StartCount then
          -- Gate has become active
          GateOpen    <= '1';
          GateActive  <= '1';
        end if;

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


  GenGateOutputs: process(nReset, Clk)
  begin
    if nReset = '0' then
      iGateFired      <= '0';
      iGateFiring     <= '0';
      iGateDidNotFire <= '0';
      InterfacePeakDone <= '0';
    elsif rising_edge(Clk) then
      if SampleEn = '1' then
        iGateFiring <= '0';

        if Trigger = '1' then
          iGateFired      <= '0';
          iGateDidNotFire <= '0';

        elsif TriggerMode = '1' and GateActive = '1' and iGateFired = '0' and
              LastLessThreshold = '1' and DataLessThreshold = '0' then
          iGateFired       <= '1';
          iGateFiring      <= '1';

        elsif TriggerMode = '0' and GateActive = '1' and iGateFired = '0' and
              DataLessThreshold = '0' then
          iGateFired       <= '1';
          iGateFiring      <= '1';

        elsif GateClose = '1' and iGateFired = '0' then
          iGateDidNotFire <= '1';
        end if;


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

      end if;
    end if;
  end process GenGateOutputs;

  GateFiring     <= '0' when Enable = '0' else iGateFiring;
  GateFired      <= '0' when Enable = '0' else iGateFired;
  GateDidNotFire <= '1' when Enable = '0' else iGateDidNotFire;


  AnalyseDatastream:  process(nReset, Clk)
    variable vLastSampleData: std_logic_vector(11 downto 0);
  begin
    if nReset = '0' then
      DataLessThreshold <= '0';
      LastLessThreshold <= '0';
      MaxDataValue      <= X"000";
      vLastSampleData   := X"000";
    elsif rising_edge(Clk) then
      if SampleEn = '1' then
        if SampleData < Threshold then
          DataLessThreshold <= '1';
        else
          DataLessThreshold <= '0';
        end if;

        LastLessThreshold <= DataLessThreshold;

        if iGateFired = '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;

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

    end if;
  end process AnalyseDatastream;

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

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


end architecture Rtl;