---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: TriggerPulseGen.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card Peripheral FPGA
--
-- Design Description:
-- Module to generate the trigger pulse
---------------------------------------------------------------------------

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


entity TriggerPulseGen is
  Port (-- Local bus signals
        pnReset            : in  std_ulogic;
        pSample2xClk       : in  std_ulogic;
        pTriggerLen        : in  std_logic_vector(11 downto 0);
        pTriggerIn         : in  std_ulogic;
        pTxDone            : out std_ulogic;
        pTriggerOut        : out std_ulogic);
end entity TriggerPulseGen;


architecture Rtl of TriggerPulseGen is

  attribute uselowskewlines: string;
  attribute MAX_FANOUT: string;

  signal TriggerIn:     std_logic_vector(2 downto 0);
  signal Trigger:       std_ulogic;

  signal CEActive:   std_ulogic;
  signal TxActive:   std_ulogic;
  signal ClkEnCount: integer range 0 to 3;
  signal ClkEn:      std_ulogic;
  attribute uselowskewlines of ClkEn : signal is "yes";
--  attribute uselowskewlines of TxActive : signal is "yes";
--  attribute MAX_FANOUT of ClkEn: signal is "10";

  signal NibbleCount:       std_logic_vector(9 downto 0);
  signal NibbleCountEqZero: std_ulogic;
  signal FinalBits:         std_logic_vector(2 downto 0);
  signal ShiftReg:          std_logic_vector(3 downto 0);
  signal DoneLastBits:      std_ulogic;

begin


  -- Detect rising edge of trigger signal
  GenTrigger: process(pnReset, pSample2xClk)
    variable vTrigRE: std_ulogic;
  begin
    if pnReset = '0' then
      Trigger   <= '0';
      TriggerIn <= "000";
    elsif rising_edge(pSample2xClk) then
      if TriggerIn(2 downto 1) = "01" then
        Trigger <= '1';
      else
        Trigger <= '0';
      end if;

      TriggerIn <= TriggerIn(1 downto 0) & pTriggerIn;
    end if;
  end process GenTrigger;


  -- Generate a flag to enable CE counter
  GenCEActive: process(pnReset, pSample2xClk)
  begin
    if pnReset = '0' then
      CEActive <= '0';
    elsif rising_edge(pSample2xClk) then
      if Trigger = '1' then
        CEActive <= '1';
      elsif DoneLastBits = '1' then
        CEActive <= '0';
      end if;
    end if;
  end process GenCEActive;


  -- Generate a slow clock enable
  GenClockEn: process(pnReset, pSample2xClk)
  begin
    if pnReset = '0' then
      ClkEnCount <= 0;
      ClkEn      <= '0';
    elsif rising_edge(pSample2xClk) then
      if ClkEnCount = 0 and CEActive = '0' then
      --if CEActive = '0' then
        -- Hold clock enable off untill a transmit pulse is required
        ClkEnCount <= 0;
      else
        ClkEnCount <= (ClkEnCount + 1) mod 4;
      end if;

      if ClkEnCount = 3 then
        ClkEn <= '1';
      else
        ClkEn <= '0';
      end if;
    end if;
  end process GenClockEn;


  -- Generate a flag to follow when a transmit is active
  GenTxActive: process(pnReset, pSample2xClk)
    variable vTxActive: std_ulogic;
  begin
    if pnReset = '0' then
      TxActive  <= '0';
    elsif rising_edge(pSample2xClk) then
      if ClkEn = '1' then
        if NibbleCountEqZero = '1' and TxActive = '1' then
          TxActive  <= '0';
        elsif CEActive = '1' then
          TxActive  <= '1';
        end if;
      end if;
    end if;
  end process GenTxActive;


  GenFinalBits: process(pTriggerLen)
  begin
    case pTriggerLen(1 downto 0) is
      when "00"   => FinalBits <= "000";
      when "01"   => FinalBits <= "100";
      when "10"   => FinalBits <= "110";
      when others => FinalBits <= "111";
    end case;
  end process GenFinalBits;


  GenCount: process(pnReset, pSample2xClk)
  begin
    if pnReset = '0' then
      NibbleCount <= (others => '0');
    elsif rising_edge(pSample2xClk) then
      if ClkEn = '1' then
        if CEActive = '0' then
          NibbleCount <= "0000000000";
        elsif TxActive = '0' then
          NibbleCount <= pTriggerLen(11 downto 2);
        elsif NibbleCountEqZero /= '1' then
          NibbleCount <= (unsigned(NibbleCount) - 1) and "1111111111";
        end if;
      end if;
    end if;
  end process GenCount;

  -- Use signal here to ensure resource sharing of 'equals comparitor'
  NibbleCountEqZero <= '1' when NibbleCount = "0000000000" else '0';


  GenShiftReg: process(pnReset, pSample2xClk)
    variable vTriggerOut: std_ulogic;
  begin
    if pnReset = '0' then
      ShiftReg     <= (others => '0');
      vTriggerOut  := '0';
      pTriggerOut  <= '0';
      DoneLastBits <= '0';
    elsif rising_edge(pSample2xClk) then

      if ClkEn = '1' then
        if NibbleCountEqZero = '1' and TxActive = '1' then
          DoneLastBits <= '1';
        else
          DoneLastBits <= '0';
        end if;

        if TxActive = '1' then
          if NibbleCountEqZero /= '1' then
            -- Nibble count is non-zero
            ShiftReg <= X"F";
          else
            -- Nibble count is zero
            ShiftReg <= FinalBits & '0';
          end if;
        else
          -- Transmit pulse not active
          ShiftReg <= X"0";
        end if;

      else
        ShiftReg <= ShiftReg(2 downto 0) & '0';
      end if;

      pTriggerOut <= ShiftReg(3);--vTriggerOut;
      vTriggerOut := ShiftReg(3);
    end if;
  end process GenShiftReg;



  -- Generate output signal to indicate when the transmit has completed
  GenpTxDone: process(pnReset, pSample2xClk)
  begin
    if pnReset = '0' then
      pTxDone   <= '0';
    elsif rising_edge(pSample2xClk) then
      if ClkEn = '1' then
        if DoneLastBits = '1' then--and vLastDone = '0' then
          pTxDone <= '1';
        else
          pTxDone <= '0';
        end if;
      end if;
    end if;
  end process GenpTxDone;


end Rtl;

