---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: GateResultSelect.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card DSP FPGA
--
-- Design Description:
-- Module to to implement gate result selection module
--
---------------------------------------------------------------------------

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

library work;
use work.DspFpgaPkg.all;

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


architecture Rtl of GateResultSelect is

  signal DelayedSampleEn: std_ulogic;
  signal TimeCount: std_logic_vector(15 downto 0);

  type tGateFireTime is array(0 to 7) of std_logic_vector(15 downto 0);
  signal GateFireTime:   tGateFireTime;
  signal GateStoredTime: tGateFireTime;

  type tGateResultMux is array(0 to 7) of std_logic_vector(29 downto 0);
  signal GateResultMux: tGateResultMux;

begin

  GenTimeCount: process(pnReset, pADC_2xClk)
  begin
    if pnReset = '0' then
      TimeCount   <= (others => '1');
      DelayedSampleEn <= '0';
    elsif rising_edge(pADC_2xClk) then
      if DelayedSampleEn = '1' then
        if pTriggersIn(15) = '1' then
          -- Start count when main delayed trigger fires
          TimeCount <= (others => '0');

        elsif TimeCount /= "1111111111111111" then
          TimeCount <= unsigned(TimeCount) + 1;
        end if;
      end if;

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


  -- Log the fire time for each gate
  LogGateFireTimes: process(pnReset, pADC_2xClk)
  begin
    if pnReset = '0' then
      for Count in 0 to 7 loop
        GateFireTime(Count) <= (others => '0');
      end loop;

    elsif rising_edge(pADC_2xClk) then
      if pSampleEn = '1' then
        for Count in 0 to 7 loop
          if pTriggersIn(15) = '1' or pNoTriggersIn(Count) = '1' then
            GateFireTime(Count) <= (others => '0');

          else
            if pTriggersIn(Count) = '1' and pUntriggersIn(Count) = '0' then
              -- This is a trigger event, get the new fire time
              GateFireTime(Count) <= TimeCount;

            elsif pTriggersIn(Count) = '0' and pUntriggersIn(Count) = '1' then
              -- this is an UnTrigger event, go back to the old fire time
              GateFireTime(Count) <= GateStoredTime(Count);

            elsif pTriggersIn(Count) = '1' and pUntriggersIn(Count) = '1' then
              -- Both a Trigger event and an UnTrigger event, do nothing
              -- Just shown for clarity
              null;

            end if;
          end if;
        end loop;
      end if;
    end if;
  end process LogGateFireTimes;


  -- Store gate fire times when required
  StoreFireTimes: process(pnReset, pADC_2xClk)
  begin
    if pnReset = '0' then
      for Count in 0 to 7 loop
        GateStoredTime(Count) <= (others => '0');
      end loop;

    elsif rising_edge(pADC_2xClk) then
      if pSampleEn = '1' then
        for Count in 0 to 7 loop
          if pTriggersIn(Count) = '1' and pReTriggersIn(Count) = '0' then
            GateStoredTime(Count) <= GateFireTime(Count);
          end if;
        end loop;
      end if;
    end if;
  end process StoreFireTimes;


  -- Mux required gate data onto output port as required
  GenTristateMux: for Count in 0 to 7 generate
    GateResultMux(Count) <= pGateDataIn(Count) & GateFireTime(Count) when pGateSelect(Count) = '1' else (others => 'Z');
    pGateData(29 downto 16) <= GateResultMux(Count)(29 downto 16);
    pGateData(15 downto 0)  <= GateResultMux(Count)(15 downto 0);
  end generate GenTristateMux;

  -- These values are constant
  pGateData(31 downto 30) <= "10";


end architecture Rtl;