--=============================================================================
--! @file eventFormatter_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture fmc_mTLU_lib.eventFormatter.rtl
--
--! @brief Takes the data delivered on each trigger and turns it into a 64-bit
--!        word\n
--! \n
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 15:10:35 11/09/12
--
--! @version v0.1
--
--! @details
--!
--!
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--!
--! <b>Modified by: Alvaro Dosil , alvaro.dosil@usc.es </b>\n
--! Author: 
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--! 27/Feb/14 DGC Change "If" when setting s_word2 to a case ... generate. Questasim
--!               doesn't like having an if that can take an array out of bounds.
-------------------------------------------------------------------------------
--! @todo Add more input data: \n
--! a) shutter signals. One per DUT. ?? \n
--! b) input levels ( for recording edge data ). Record rising and falling edges\n
--! c) veto levels. One per DUT. Record rising and falling edges.\n
--! \n
--! Add backpressure output if short FIFOs fill up? But many inputs won't
--! respond - e.g. scintillator inputs. This data will be lost....
--! some ports are redundant - e.g. trigger counter, others confusingly
--! labelled. Sort this out..
--------------------------------------------------------------------------------
-- 
-- Created using using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

USE work.fmcTLU.all;
USE work.ipbus.all;

ENTITY eventFormatter IS
   GENERIC( 
      g_EVENT_DATA_WIDTH    : positive := 64;
      g_IPBUS_WIDTH         : positive := 32;
      g_COUNTER_TRIG_WIDTH  : positive := 32;
      g_COUNTER_WIDTH       : positive := 12;
      g_EVTTYPE_WIDTH       : positive := 4;     --! Width of the event type word
      --g_NUM_INPUT_TYPES     : positive := 4;   --! Number of different input types (trigger, shutter, edge...)
      g_NUM_EDGE_INPUTS     : positive := 4;     --! Number of edge inputs
      g_NUM_TRIG_INPUTS     : positive := 5                --! Number of trigger inputs
   );
   PORT( 
      clk_4x_logic_i         : IN     std_logic;        --! Rising edge active
      ipbus_clk_i            : IN     std_logic;                                          
      logic_strobe_i         : IN     std_logic;        --! Pulses high once every 4 cycles of clk_4x_logic
      logic_reset_i          : IN     std_logic;        --! goes high to reset counters. Synchronous with clk_4x_logic
      rst_fifo_i	     : IN     std_logic;       	--! Reset fifos
      buffer_full_i	     : in     std_logic;	--! Buffer full signal from main buffer
		
      trigger_i              : IN     std_logic;                                          --! goes high to load trigger data. One cycle of clk_4x_logic
      trigger_times_i        : IN     t_triggerTimeArray (g_NUM_TRIG_INPUTS-1 DOWNTO 0);  --! Array of trigger times ( w.r.t. logic_strobe)
      trigger_inputs_fired_i : IN     std_logic_vector (g_NUM_TRIG_INPUTS-1 DOWNTO 0);    --! high for each input that "fired"
      trigger_cnt_i          : IN     std_logic_vector (g_COUNTER_TRIG_WIDTH-1 DOWNTO 0);
		
      shutter_i              : IN     std_logic;
      shutter_cnt_i          : IN     std_logic_vector(g_COUNTER_WIDTH-1 DOWNTO 0);
      
      spill_i                : IN     std_logic;
      spill_cnt_i            : IN     std_logic_vector(g_COUNTER_WIDTH-1 DOWNTO 0);
      
      edge_rise_i            : IN     std_logic_vector (g_NUM_EDGE_INPUTS-1 DOWNTO 0);    --! High when rising edge
      edge_fall_i            : IN     std_logic_vector (g_NUM_EDGE_INPUTS-1 DOWNTO 0);    --! High when falling edge
      edge_rise_time_i       : IN     t_triggerTimeArray (g_NUM_EDGE_INPUTS-1 DOWNTO 0);  --! Array of edge times ( w.r.t. logic_strobe)
      edge_fall_time_i       : IN     t_triggerTimeArray (g_NUM_EDGE_INPUTS-1 DOWNTO 0);  --! Array of edge times ( w.r.t. logic_strobe)
		
      ipbus_i                : IN     ipb_wbus;
      ipbus_o                : OUT    ipb_rbus;
      data_strobe_o          : OUT    std_logic;                                          -- goes high when data ready to load into event buffer
      event_data_o           : OUT    std_logic_vector (g_EVENT_DATA_WIDTH-1 DOWNTO 0);
      event_number_i         : in    std_logic_vector (g_IPBUS_WIDTH-1 DOWNTO 0);
      trigger_count_o        : OUT    std_logic_vector (g_IPBUS_WIDTH-1 DOWNTO 0)
   );

-- Declarations

END ENTITY eventFormatter ;

--
ARCHITECTURE rtl OF eventFormatter IS

  -- add to ports
  -- trigger_i           : OUT    std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0);    -- ! High when trigger active
  -- signal inputs_triggered_i :    std_logic_vector (g_NUM_INPUTS-1 DOWNTO 0);    -- ! High when trigger active
  -- signal logic_reset_i : std_logic := '0';  -- put into ports...
  
  constant c_NUM_INPUT_TYPES     : positive := 3+g_NUM_EDGE_INPUTS;               -- Number of different input types (trigger, shutter, edge(0), edge(1)...)
  
  type t_fifo_io is array(natural range <>) of std_logic_vector(g_EVENT_DATA_WIDTH-1 downto 0);
  type t_evttype is array(natural range <>) of std_logic_vector(g_EVTTYPE_WIDTH-1 downto 0);
  type t_var is array(natural range <>) of std_logic_vector(g_COUNTER_WIDTH-1 downto 0);
  -- Input types:
  -- 0 - Trigger
  -- 1 - Shutter
  -- 2 - Edge signal
  -- 3 - Spill
  
  --! delayed strobes
  signal s_event_strobe , s_event_strobe_d1 ,s_event_strobe_d2 ,s_event_strobe_d3 , s_event_strobe_d3_opt : std_logic := '0';
  signal shutter_i_d1, shutter_i_d2, edge_i_d1, edge_i_d2, spill_i_d1, spill_i_d2 : std_logic := '0';
  
  signal s_evttype : t_evttype(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>(others=>'0'));   -- Event type
  -- 0000 trigger internal
  -- 0001 trigger external
  -- 0010 shutter falling
  -- 0011 shutter rising
  -- 0100 edge falling
  -- 0101 edge rising
  -- 0111 spill on
  -- 0110 spill off
  
  signal s_var        : t_var(3+g_NUM_EDGE_INPUTS-1 downto 0) :=(others=>(others=>'0'));       -- 12b different in every input
  
  signal s_FIFO_wr       : std_logic_vector(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>'0');     -- FIFO write signal
  signal s_FIFO_rd       : std_logic_vector(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>'0');     -- FIFO read signals
  signal s_FIFO_rd_d1     : std_logic_vector(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>'0');     -- FIFO read signals delayed
  signal s_FIFO_rd_d2     : std_logic_vector(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>'0');     -- FIFO read signals delayed
  constant c_FIFO_rd_mask  : unsigned(3+g_NUM_EDGE_INPUTS-1 downto 0) := (0 =>'1',others=>'0'); --(3+g_NUM_EDGE_INPUTS-1 =>'1',others=>'0');     -- FIFO read mask
  signal s_FIFO_empty    : std_logic_vector(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>'0');     -- FIFO empty signals
  signal s_FIFO_full		 : std_logic_vector(3+g_NUM_EDGE_INPUTS-1 downto 0) := (others=>'0');     -- FIFO full signals
  signal s_FIFO_i        : t_fifo_io(3+g_NUM_EDGE_INPUTS-1 downto 0) :=(others=>(others=>'0'));   -- FIFO input data
  signal s_FIFO_o        : t_fifo_io(3+g_NUM_EDGE_INPUTS-1 downto 0) :=(others=>(others=>'0'));   -- FIFO output data
  
  
  signal s_data_o        : std_logic_vector(g_EVENT_DATA_WIDTH-1 DOWNTO 0);         -- Multiplexed data from FIFOs
  --signal s_data_o_mask : unsigned(3+g_NUM_EDGE_INPUTS-1 downto 0) := (g_NUM_TRIG_INPUTS+g_NUM_EDGE_INPUTS-1 =>'1',others=>'0');     -- Output data mask
  
  --constant c_COARSE_TIMESTAMP_WIDTH : positive := 48;  -- ! Number of bits in 40MHz timestamp
  constant c_COARSE_TIMESTAMP_L_WIDTH : positive := 16;  -- ! Number of bits in 40MHz timestamp lower bits
  constant c_COARSE_TIMESTAMP_H_WIDTH : positive := 32;  -- ! Number of bits in 40MHz timestamp higher bits
  signal s_coarse_timestamp_l, s_coarse_timestamp_l_d1, s_coarse_timestamp_l_d2, s_coarse_timestamp_l_d3 : unsigned(c_COARSE_TIMESTAMP_L_WIDTH-1 downto 0) := (others => '0');  -- 40MHz timestamp.
  signal s_coarse_timestamp_h, s_coarse_timestamp_h_d1, s_coarse_timestamp_h_d2, s_coarse_timestamp_h_d3 : unsigned(c_COARSE_TIMESTAMP_H_WIDTH-1 downto 0) := (others => '0');  -- 40MHz timestamp.
  signal s_timestamp_h_en : std_logic:='0';
--  signal s_event_number : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0');  -- increment after each post-veto trigger.

  signal s_word0 , s_word1, s_word2 			: std_logic_vector(g_EVENT_DATA_WIDTH-1 downto 0) := (others => '0');  -- clocked to data output on logic_strobe , s_logic_strobe_d1 , etc.
  signal s_word0_d1 , s_word1_d1, s_word2_d1 : std_logic_vector(g_EVENT_DATA_WIDTH-1 downto 0) := (others => '0');  -- clocked to data output on logic_strobe , s_logic_strobe_d1 , etc.
  signal s_word0_d2 , s_word1_d2, s_word2_d2 : std_logic_vector(g_EVENT_DATA_WIDTH-1 downto 0) := (others => '0');  -- clocked to data output on logic_strobe , s_logic_strobe_d1 , etc.
  signal s_word0_d3 , s_word1_d3, s_word2_d3 : std_logic_vector(g_EVENT_DATA_WIDTH-1 downto 0) := (others => '0');  -- clocked to data output on logic_strobe , s_logic_strobe_d1 , etc.
  signal trigger_inputs_fired_d1 				: std_logic_vector (g_NUM_TRIG_INPUTS-1 DOWNTO 0) := (others => '0');
  signal trigger_times_d1							: t_triggerTimeArray (g_NUM_TRIG_INPUTS-1 DOWNTO 0) := (others => (others=>'0')); 
  
  signal s_ipbus_ack      : std_logic := '0';  -- used to produce a delayed IPBus ack signal
  signal s_enable_record, s_enable_record_ipb : std_logic_vector(g_IPBUS_WIDTH-1 downto 0) := (2 downto 0 => '1', others=>'0'); -- Enable data record
  signal s_enable_trigger : std_logic := '1'; -- Enable trigger record
  signal s_enable_shutter : std_logic := '1'; -- Enable shutter record
  signal s_enable_spill   : std_logic := '1'; -- Enable spill record
  signal s_enable_edges   : std_logic_vector(g_NUM_EDGE_INPUTS-1 downto 0) := (others=>'0'); -- Enable edges record
  
BEGIN

  -----------------------------------------------------------------------------
  -- IPBus write
  -----------------------------------------------------------------------------
  ipbus_write: process (ipbus_clk_i)
  begin  -- process ipb_clk_i
    if rising_edge(ipbus_clk_i) then

       if (ipbus_i.ipb_strobe = '1' and ipbus_i.ipb_write = '1') then

         case ipbus_i.ipb_addr(2 downto 0) is
           when "000" => s_enable_record_ipb <= ipbus_i.ipb_wdata ; -- Enable data record
           when others => null;
         end case;
          
       end if;

       s_ipbus_ack <= ipbus_i.ipb_strobe and not s_ipbus_ack;
       
    end if;
  end process ipbus_write;

  ipbus_o.ipb_ack <= s_ipbus_ack;
  ipbus_o.ipb_err <= '0';
  

  -----------------------------------------------------------------------------
  -- IPBUS read
  -----------------------------------------------------------------------------
  with ipbus_i.ipb_addr(2 downto 0) select
    ipbus_o.ipb_rdata <=
      s_enable_record_ipb                     when "000",
      (others => '1')                         when others;

  -- Change clock domain
  p_signals_clk_domain: process (clk_4x_logic_i )
  begin  -- process p_internal_triggers
    if rising_edge(clk_4x_logic_i) then
      s_enable_record  <= s_enable_record_ipb;
		
      s_enable_trigger <= s_enable_record(0);
      s_enable_shutter <= s_enable_record(1);
      s_enable_spill <= s_enable_record(2);
      s_enable_edges <= s_enable_record(g_NUM_EDGE_INPUTS-1+3 downto 3);
		
    end if;
  end process p_signals_clk_domain;


  -- purpose: generate delayed strobes and write enable flags to the FIFOs
  -- type   : combinational
  -- inputs : clk_4x_logic_i , s_FIFO_rd
  -- outputs: s_event_strobe_d1 , s_event_strobe_d2 , s_event_strobe_d3 , s_FIFO_rd_d , s_**_evttype
  p_ff_rst: process (clk_4x_logic_i)
  begin  -- process p_generate_strobes
    if rising_edge(clk_4x_logic_i) then      
      if rst_fifo_i = '1' then
        s_event_strobe_d1 <= '0';
        s_event_strobe_d2 <= '0';
        s_event_strobe_d3 <= '0';
		
        shutter_i_d1 <= '0';
        shutter_i_d2 <= '0';
		
        spill_i_d1 <= '0';
        spill_i_d2 <= '0';
		
        s_FIFO_rd_d1 <= (others=>'0');
        s_FIFO_rd_d2 <= (others=>'0');
		
      else 
        s_event_strobe_d1 <= trigger_i and s_enable_trigger and not s_FIFO_full(0);
        s_event_strobe_d2 <= s_event_strobe_d1;
        s_event_strobe_d3 <= s_event_strobe_d2;
		
        shutter_i_d1 <= shutter_i and s_enable_shutter and not s_FIFO_full(1);
        shutter_i_d2 <= shutter_i_d1;

        spill_i_d1 <= spill_i and s_enable_spill and not s_FIFO_full(3+g_NUM_EDGE_INPUTS-1);
        spill_i_d2 <= spill_i_d1;
		
        s_FIFO_rd_d1 <= s_FIFO_rd;
        s_FIFO_rd_d2 <= s_FIFO_rd_d1;
      end if;
    end if;
  end process p_ff_rst;
  
  p_ff: process (clk_4x_logic_i)
  begin  -- process p_generate_strobes
	if rising_edge(clk_4x_logic_i) then
		for i in 0 to g_NUM_TRIG_INPUTS-1 loop
			trigger_inputs_fired_d1(g_NUM_TRIG_INPUTS-1-i) <= trigger_inputs_fired_i(i);
		end loop;
		trigger_times_d1 <= trigger_times_i;
		
		s_word0_d1 <= s_word0;
		s_word1_d1 <= s_word1;
		s_word1_d2 <= s_word1_d1;
		s_word2_d1 <= s_word2;
		s_word2_d2 <= s_word2_d1;
		s_word2_d3 <= s_word2_d2;
		
		s_coarse_timestamp_l_d1 <= s_coarse_timestamp_l;
		s_coarse_timestamp_l_d2 <= s_coarse_timestamp_l_d1;
		s_coarse_timestamp_l_d3 <= s_coarse_timestamp_l_d2;
		s_coarse_timestamp_h_d1 <= s_coarse_timestamp_h;
		s_coarse_timestamp_h_d2 <= s_coarse_timestamp_h_d1;
		s_coarse_timestamp_h_d3 <= s_coarse_timestamp_h_d2;
	end if;
  end process;
	
  -- If there are more than 4 trigger inputs we need to fill a second word.
  -- .. do this by having an optional strobe.
  -- If 4 or fewer trigger inputs, just leave s_event_strobe_d3_opt at zero..
  gen_strobe_d3: if (g_NUM_TRIG_INPUTS > 4) generate
    s_event_strobe_d3_opt <= s_event_strobe_d3;
  end generate;

-------------------------------------------------------------------------------
-- Trigger event formater
-------------------------------------------------------------------------------
  s_evttype(0) <= "0000" when unsigned(trigger_inputs_fired_d1) = 0 and trigger_i = '1' else
						"0001";
  s_var(0)     <= trigger_inputs_fired_d1 & std_logic_vector(to_unsigned(0,s_var(0)'length-g_NUM_TRIG_INPUTS));

  --s_word0 <= s_evttype(0) & s_var(0) & std_logic_vector(s_coarse_timestamp_d2);
  s_word0 <= s_evttype(0) & s_var(0) & std_logic_vector(s_coarse_timestamp_h_d2) & std_logic_vector(s_coarse_timestamp_l_d2);
  
  s_word1 <= "000" & trigger_times_d1(0) & "000" & trigger_times_d1(1) &
             "000" & trigger_times_d1(2) & "000" & trigger_times_d1(3) &
             trigger_cnt_i;
				 
	
  -- Different number of trigger inputs require packing into s_word2 in
  -- different ways.
  -- Do this in a generate since g_NUM_TRIG_INPUTS is static and
  -- Questasim doesn't like refering to indices outside declared range.
  s_word2 <= (others=>'0'); -- Set all bits to zero
  -- then override with the following assignments....
  gen_word2: for v_trigInput in 4 to g_NUM_TRIG_INPUTS-1 generate
    s_word2( (((11-v_trigInput)*8)+c_NUM_TIME_BITS-1) downto ((11-v_trigInput)*8) ) <= trigger_times_i(v_trigInput);
  end generate;
  
      
  --! Could also output data on trigger_i , but let's use the delayed signals. \n
  --! The counters are one cycle delayed from the signal generation
  p_fifo_i : process (clk_4x_logic_i)
	begin  
		if rising_edge(clk_4x_logic_i) then
			s_FIFO_wr(0) <= s_event_strobe_d1 or s_event_strobe_d2 or s_event_strobe_d3_opt;
		
			if s_event_strobe_d1 = '1' then
				s_FIFO_i(0) <= s_word0_d1;
			elsif s_event_strobe_d2 = '1' then
				s_FIFO_i(0) <= s_word1_d2;
			elsif s_event_strobe_d3_opt = '1' then
				s_FIFO_i(0) <= s_word2_d3;
			else
				s_FIFO_i(0) <= (others=>'0');
			end if;
		end if;
	end process;
		
  
  s_evttype(1) <= "0011" when shutter_i_d1 = '1' and shutter_i_d2 = '0' else
                  "0010" when shutter_i_d1 = '0' and shutter_i_d2 = '1' else
						(others=>'0');
  s_var(1) <= shutter_cnt_i;
		
  edge_formatting : for i in 0 to (g_NUM_EDGE_INPUTS-1) generate		
    s_evttype(i+2) <= "0101" when edge_rise_i(i) = '1' else
                      "0100" when edge_fall_i(i) = '1' else
                      (others=>'0');
    s_var(i+2) <= std_logic_vector(to_unsigned(i,4)) & "000" & edge_rise_time_i(i) when edge_rise_i(i) = '1' else
	               std_logic_vector(to_unsigned(i,4)) & "000" & edge_fall_time_i(i) when edge_fall_i(i) = '1' else
						(others=>'0');
  end generate;
  
  
  s_evttype(3+g_NUM_EDGE_INPUTS-1) <= "0111" when spill_i_d1 = '1' and spill_i_d2 = '0' else
                                      "0110" when spill_i_d1 = '0' and spill_i_d2 = '1' else
						                    (others=>'0');
  s_var(3+g_NUM_EDGE_INPUTS-1) <= spill_cnt_i;

	
	
	p_fifo_wr : process (clk_4x_logic_i)
	begin  
		if rising_edge(clk_4x_logic_i) then
			s_FIFO_wr(1) <= shutter_i_d1 xor shutter_i_d2;
			s_FIFO_wr(3+g_NUM_EDGE_INPUTS-1) <= spill_i_d1 xor spill_i_d2;
		end if;
	end process;
	
	gen_fifo_wr_edge : for i in 0 to (g_NUM_EDGE_INPUTS-1) generate	
		p_fifo_wr : process (clk_4x_logic_i)
		begin  
			if rising_edge(clk_4x_logic_i) then
				s_FIFO_wr(i+2) <= (edge_rise_i(i) or edge_fall_i(i)) and s_enable_edges(i) and not s_FIFO_full(i+2);
			end if;
		end process;
	end generate;

	gen_FIFO_i : for i in 1 to 3+g_NUM_EDGE_INPUTS-1 generate
		p_fifo_i_n : process (clk_4x_logic_i)
		begin  
			if rising_edge(clk_4x_logic_i) then
				s_FIFO_i(i) <= s_evttype(i) & s_var(i) & std_logic_vector(s_coarse_timestamp_h_d2) & std_logic_vector(s_coarse_timestamp_l_d2);
			end if;
		end process;
  end generate gen_FIFO_i;


-------------------------------------------------------------------------------
-- first level of FIFOs
-------------------------------------------------------------------------------
  
  gen_FIFOs : for i in 0 to 3+g_NUM_EDGE_INPUTS-1 generate
  begin
  
    FIFO_i : entity work.FIFO
      PORT MAP (
        clk => clk_4x_logic_i,
        rst => rst_fifo_i, --logic_reset_i,
        din => s_FIFO_i(i), 
        wr_en => s_FIFO_wr(i), 
        rd_en => s_FIFO_rd(i), 
        dout => s_FIFO_o(i), 
        full => open,
		  prog_full => s_FIFO_full(i),
        empty => s_FIFO_empty(i)
	   );
		
  end generate gen_FIFOs;
  


-------------------------------------------------------------------------------
-- Reading FIFOs and multiplexing them to the output
-------------------------------------------------------------------------------
  
  -- NOTE: Rewrite this
  -- Mux to send the read signal to only one FIFO. Priority order: trigger, shutter, edge, spill
  -- every trigger word will be read before jump to other data
   
  p_FIFO_rd: process (rst_fifo_i, s_FIFO_empty, buffer_full_i)
  begin  -- process p_generate_strobes
	 s_FIFO_rd <= (others=>'0');
	 if buffer_full_i = '0' and rst_fifo_i = '0' then
		l_FIFO_rd: for i in 0 to 3+g_NUM_EDGE_INPUTS-1 loop
			if s_FIFO_empty(i) = '0' then
				s_FIFO_rd <= std_logic_vector(c_FIFO_rd_mask sll i);
				exit l_FIFO_rd;
			end if;
		end loop;
	 end if;
  end process;		  
					
	 
	p_data_o : process (clk_4x_logic_i)
	begin  
		if rising_edge(clk_4x_logic_i) then
			if s_FIFO_rd_d1 = "0000001" then
				s_data_o <= s_FIFO_o(0);
			elsif s_FIFO_rd_d1 = "0000010" then
				s_data_o <= s_FIFO_o(1);
			elsif s_FIFO_rd_d1 = "0000100" then
				s_data_o <= s_FIFO_o(2);
			elsif s_FIFO_rd_d1 = "0001000" then
				s_data_o <= s_FIFO_o(3);
			elsif s_FIFO_rd_d1 = "0010000" then
				s_data_o <= s_FIFO_o(4);
			elsif s_FIFO_rd_d1 = "0100000" then
				s_data_o <= s_FIFO_o(5);
			elsif s_FIFO_rd_d1 = "1000000" then
				s_data_o <= s_FIFO_o(6);
			else
				s_data_o <= (others=>'0');
			end if;
		end if;
	end process;
  
  
  -- Send out the data and the strobe signal
  event_data_o <= s_data_o;
  data_strobe_o <= '0' when s_FIFO_rd_d2 = std_logic_vector(to_unsigned(0,s_FIFO_rd_d2'length)) else
                   '1';

  -- purpose: Keep track of 40MHz timestamp
  -- type   : sequential
  -- inputs : clk_4x_logic_i
  -- outputs: 
  p_timestamp_l: process (clk_4x_logic_i, logic_reset_i)
  begin  -- process p_timestamp
    if rising_edge(clk_4x_logic_i) then  -- rising clock edge
      if logic_reset_i = '1' then
        s_coarse_timestamp_l <= ( others => '0');
      elsif ( logic_strobe_i = '1' )  then
        s_coarse_timestamp_l <= s_coarse_timestamp_l + 1;
      end if;
    end if;
  end process p_timestamp_l;
  
  s_timestamp_h_en <= '1' when s_coarse_timestamp_l = x"ffff" else
								'0';
								
  p_timestamp_h: process (clk_4x_logic_i, logic_reset_i)
  begin  -- process p_timestamp
    if rising_edge(clk_4x_logic_i) then  -- rising clock edge
      if logic_reset_i = '1' then
        s_coarse_timestamp_h <= ( others => '0');
      elsif ( logic_strobe_i = '1' ) and (s_timestamp_h_en='1') then
        s_coarse_timestamp_h <= s_coarse_timestamp_h + 1;
      end if;
    end if;
  end process p_timestamp_h;
  
  -- Generate data in format decided at DESY. Put out two strobes for the
  -- two 64 bit words.
  -- get trigger inputs to also generate a global time-stamp ??
  -- add trigger_inputs_active_i array (to indicate which triggers fired)
  
END ARCHITECTURE rtl;

