---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2008
--
-- Filename: GateResultSelect.vhd
-- Language: VHDL '93
-- Project:  NDTS2100 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(nReset         : in  std_ulogic;
       SysClk         : in  std_ulogic;
       SampleEn       : in  std_ulogic;
       TriggersIn     : in  std_logic_vector(15 downto 0);
       UnTriggersIn   : in  std_logic_vector(15 downto 0);
       NoTriggersIn   : in  std_logic_vector(15 downto 0);
       ReTriggersIn   : in  std_logic_vector(15 downto 0);
       GateSelect     : in  std_logic_vector(2 downto 0);
       GateDistance   : in  std_ulogic;
       GateDataIn     : in  tGateData14;
--       GateDataIn     : in  tGateData24;
--       GateDistIn     : in  tGateData24;
       GateData       : out std_logic_vector(31 downto 0));
end entity GateResultSelect;


architecture Rtl of GateResultSelect is

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

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

begin

  GenTimeCount: process(nReset, SysClk)
  begin
    if nReset = '0' then
      TimeCount   <= (others => '1');
      DelayedSampleEn <= '0';
    elsif SysClk'event and SysClk = '1' then
      if DelayedSampleEn = '1' then
        if TriggersIn(15) = '1' then
          -- Start count when main delayed trigger fires
          TimeCount <= (others => '0');

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

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


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

    elsif SysClk'event and SysClk = '1' then
      if SampleEn = '1' then
        for Count in 0 to 7 loop
          if TriggersIn(15) = '1' or NoTriggersIn(Count) = '1' then
            GateFireTime(Count) <= (others => '0');

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

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

            elsif TriggersIn(Count) = '1' and UntriggersIn(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(nReset, SysClk)
  begin
    if nReset = '0' then
      for Count in 0 to 7 loop
        GateStoredTime(Count) <= (others => '0');
      end loop;

    elsif SysClk'event and SysClk = '1' then
      if SampleEn = '1' then
        for Count in 0 to 7 loop
          if TriggersIn(Count) = '1' and ReTriggersIn(Count) = '0' then
            GateStoredTime(Count) <= GateFireTime(Count);
          end if;
        end loop;
      end if;
    end if;
  end process StoreFireTimes;


  GenTristateMux: process(nReset, SysClk)
  begin
    if nReset = '0' then
      GateData <= (others => '0');
    elsif SysClk'event and SysClk = '1' then
      if GateDistance = '0' then
        GateData(31 downto 30) <= "10";
        GateData(29) <= GateDataIn(conv_integer(unsigned(GateSelect)))(13);
        GateData(28) <= GateDataIn(conv_integer(unsigned(GateSelect)))(12);
        GateData(27 downto 12) <= (others => '0');
        GateData(11 downto 0) <= GateDataIn(conv_integer(unsigned(GateSelect)))(11 downto 0);
      else
        GateData(31 downto 24) <= (others => '0');
        GateData(23 downto 0) <= GateFireTime(conv_integer(unsigned(GateSelect)));
--        GateData(23 downto 0) <= GateDistIn(conv_integer(unsigned(GateSelect)));
      end if;
    end if;
  end process GenTristateMux;

end architecture Rtl;