----------------------------------------------------------------------------------
-- Company: APC
-- Engineer: CC
-- 
-- Create Date:    11:49:52 28/02/2017
-- Design Name: 
-- Module Name:    data_out_fsm - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: gather data to be sent: TDC, SPI
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Revision 0.02 - new data format add busy trigger
-- Revision 0.03 - sync data tdcns with fsm, sync event counters and busy counters
-- Revision 0.04 - in cnt_proces only one condition for counters and move busy flag to tdc_process
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;



-- Data format 96 bits bits ---- SPI 16bits

--	95        80       		 	72            64  			 62          60    	59     58	      	 32  	  		4		  3         0     
--	-------------------------------------------------------------------------------------------------------------------------------
--	|   SPI    | event counter	| busy counter | PPS counter | seconds   | busy | time  |clock counter | 8ns tag | spare | 1ns tag |
--	|  16bits  |  8bits lsb  	|  8bits lsb   |   2bits 	  | 2bits lsb |   	| valid |	26bits 	  | 28 bits |	'0'  |  3bits	|
--	-------------------------------------------------------------------------------------------------------------------------------



entity data_out_nofsm is

	generic(
		 g_spi_timeout_val : natural := 50 	--	~800ns @ 62.5MHz enough ?? 
		 );

    Port ( clk_i 						: in  STD_LOGIC;
			  clk_125m_pllref_i		: in  STD_LOGIC;
           rst_i 						: in  STD_LOGIC;
			  event_flag_i				: in  STD_LOGIC;
			  busy_flag_i				: in  STD_LOGIC;
			  spi_en_i					: in  STD_LOGIC;
			  event_cnt_i				: in  STD_LOGIC_VECTOR(7 downto 0);		--event counter 8bits lsb
			  busy_cnt_i				: in  STD_LOGIC_VECTOR(7 downto 0);		--busy trigger counter 8bits lsb
			  pps_cnt_i					: in  STD_LOGIC_VECTOR(1 downto 0);		--PPS counter 2bits lsb
			  clk_cnt_i					: in  STD_LOGIC_VECTOR(25 downto 0);	--clock counter 26bits
			  tx_tag_tai_evt_i		: in  STD_LOGIC_VECTOR(1 downto 0);		--seconds 2bits lsb
			  tx_tag_cycles_evt_i 	: in  STD_LOGIC_VECTOR(27 downto 0);	---8ns tag 28bits
			  tx_tag_tai_bsy_i		: in  STD_LOGIC_VECTOR(1 downto 0);		--seconds 2bits lsb
			  tx_tag_cycles_bsy_i 	: in  STD_LOGIC_VECTOR(27 downto 0);	---8ns tag 28bits
			  tdc_data_evt_i			: in  STD_LOGIC_VECTOR(2 downto 0);		-- 1ns timestamp 3bits event trigger
			  tdc_data_bsy_i			: in  STD_LOGIC_VECTOR(2 downto 0);		-- 1ns timestamp 3bits busy trigger
			  data_rx_spi_i			: in  STD_LOGIC_VECTOR(15 downto 0);	-- Rx SPI data 16bits
			  tdc_evt_rdy_i			: in  STD_LOGIC;
			  tdc_bsy_rdy_i			: in  STD_LOGIC;
			  tm_time_valid_i			: in  STD_LOGIC;
			  tx_tag_valid_evt_i		: in  STD_LOGIC;	
			  tx_tag_valid_bsy_i		: in  STD_LOGIC;	
           data_r_spi_i 			: in  STD_LOGIC;
			  tx_data_o					: out STD_LOGIC_VECTOR(95 downto 0);
           tx_ready_o 				: out STD_LOGIC
--			  tdc_en_o 					: out STD_LOGIC:= '1'
			  --TRIG0 : out std_logic_vector(31 downto 0)
			 );
end data_out_nofsm;

architecture Behavioral of data_out_nofsm is

	component time_out_gen is
	generic(
		 g_timeout_val : integer := 65500 --	~1ms @ 62.5MHz
		 );
    Port (
		clk_i				: in std_logic;
		rst_i				: in std_logic;
		timeout_en_i 	: in std_logic;
		timeout_hit_o	: out std_logic
	 );
	end component;

	signal tx_data_rdy, cnt_rdy, data_r_spi : std_logic;
	signal tdc_data_buf : std_logic_vector(5 downto 0);
	signal data_rdy : std_logic_vector(2 downto 0):=(others => '0');
--	signal tx_data : STD_LOGIC_VECTOR(95 downto 0):=(others => '0');
	---timeout signals ---
  signal timeout_hit  : std_logic := '0';
  signal timeout_en   : std_logic := '0';
--  signal timeout_cnt  : natural := 0;	
  
	
begin

	tx_ready_o 	<= tx_data_rdy;
	tx_data_rdy <= data_rdy(2) and data_rdy(1) and data_rdy(0);
	timeout_en 	<= data_rdy(2);	
	cnt_rdy 		<= event_flag_i or busy_flag_i;

---- time out generator for SPI data ---	
	U_hold_off_gen : time_out_gen 
	generic map (g_timeout_val => g_spi_timeout_val)		
    Port map (
		clk_i				=> clk_i,
     	rst_i 		 	=> rst_i,
		timeout_en_i 	=> timeout_en,
		timeout_hit_o	=> timeout_hit
	 );
	 	
	
	cnt_proc: process (clk_i)
	begin
	if rising_edge(clk_i)then
		if (rst_i = '1') then
			tx_data_o(79 downto 72)  	<= (others => '0');			--event counter 8bits lsb
			tx_data_o(71 downto 64)  	<= (others => '0');			--busy trigger counter 8bits lsb
			tx_data_o(63 downto 62) 	<= (others => '0');			--PPS counter	2bits 
			tx_data_o(57 downto 32)  	<= (others => '0');			--clock counter 26bits
			data_rdy(2)						<= '0';
		elsif (cnt_rdy = '1' and data_rdy(2) = '0' ) then			--event or busy counter data ready
			tx_data_o(79 downto 72)  	<= event_cnt_i;				--event counter 8bits lsb
			tx_data_o(71 downto 64)  	<= busy_cnt_i;					--busy trigger counter 8bits lsb
			tx_data_o(63 downto 62) 	<= pps_cnt_i;					--PPS counter	2bits 
			tx_data_o(57 downto 32)  	<= clk_cnt_i;					--clock counter 26bits	
			data_rdy(2)						<= '1';
		elsif data_rdy	= "111" then 										--all TX data sent to FIFO
			data_rdy(2)						<= '0';	
		end if;
	end if;
	end process;
		
	
	tdc_proc: process (clk_i)
	begin
	if rising_edge(clk_i)then
		if (rst_i = '1') then
			tx_data_o(61 downto 60)  	<= (others => '0');					--seconds 2bitslsb 
			tx_data_o(58)   			 	<= '0';									--flag for SPLL locked & local time synchronyzed to Master			
			tx_data_o(31 downto 4)   	<= (others => '0'); 					--8ns tag 28bits
			tx_data_o(2 downto 0)      <= (others => '0');  				--TDC 1ns 	
			tx_data_o(59)   				<= '0';									--busy trigger flag		
			data_rdy(1)						<= '0';
		elsif (tx_tag_valid_evt_i = '1' and data_rdy(1) = '0') then		--coarse TDC data ready	
			tx_data_o(61 downto 60)  	<= tx_tag_tai_evt_i;					--seconds 2bits lsb 
			tx_data_o(58)   			 	<= tm_time_valid_i;					--flag for SPLL locked & local time synchronyzed to Master			
			tx_data_o(31 downto 4)   	<= tx_tag_cycles_evt_i; 			--8ns tag 28bits
			tx_data_o(2 downto 0)      <= tdc_data_buf(5 downto 3);  	--TDC 1ns 
			tx_data_o(59)   				<= '0';									--busy trigger flag, '0' if event trigger
			data_rdy(1)						<= '1';
		elsif (tx_tag_valid_bsy_i = '1' and data_rdy(1) = '0') then		--coarse TDC data ready		
			tx_data_o(61 downto 60)  	<= tx_tag_tai_bsy_i;					--seconds 2bits lsb 
			tx_data_o(58)   			 	<= tm_time_valid_i;					--flag for SPLL locked & local time synchronyzed to Master			
			tx_data_o(31 downto 4)   	<= tx_tag_cycles_bsy_i; 			--8ns tag 28bits
			tx_data_o(2 downto 0)      <= tdc_data_buf(5 downto 3);  	--TDC 1ns precision
			tx_data_o(59)   				<= '1';									--busy trigger flag, '1' if busy trigger
			data_rdy(1)						<= '1';
		elsif data_rdy	= "111" then 				--all TX data sent to FIFO
			data_rdy(1)						<= '0';
		end if;								
	end if;
	end process;
	
	spi_proc: process (clk_i)
	begin
	if rising_edge(clk_i)then
		if (rst_i = '1') then
			tx_data_o(95 downto 80) <= (others => '0');  	
			data_rdy(0)					<= '0';
		elsif (spi_en_i = '0')	then			-- SPI off 
			tx_data_o(95 downto 80) <= (others => '0');  --SPI disabled, data set to 0
			data_rdy(0)					<= '1';	
		--elsif data_rdy(0) = '0' then
		elsif (data_r_spi_i = '1' and data_rdy = "110") then		--and data_rdy(0) = '0') then						-- data SPI ready and data counter or data tdc in Tx buffer
				tx_data_o(95 downto 80) <= data_rx_spi_i;  	--SPI data
				data_rdy(0)					<= '1';
		elsif timeout_hit = '1' then		--and data_rdy(0) = '0') then						-- and data_rdy(0) = '0'
				tx_data_o(95 downto 80) <= x"AAAA";				 	--SPI data are late
				data_rdy(0)					<= '1';			
		elsif data_rdy	= "111" then 				--all TX data sent to FIFO
			data_rdy(0)			<= '0';			
		end if;	
	end if;
	end process;
	
	----Process hold TDC data
	tdc_buf_proc: process(clk_125m_pllref_i)
		BEGIN	  
			if rising_edge(clk_125m_pllref_i) then
				if (tdc_evt_rdy_i = '1') then								--event TDC 1ns ready
					tdc_data_buf(2 downto 0)  <= tdc_data_evt_i;  	--TDC 1ns event trigger
				elsif (tdc_bsy_rdy_i = '1') then							--busy TDC 1ns ready
					tdc_data_buf(2 downto 0)  <= tdc_data_bsy_i;		--TDC 1ns busy trigger
				end if;
			end if;
  end process;
  
   --- sync different clock domains			--use async FIFO or in SPI state of FSM  ???
	sync_tdc_proc: process(clk_i)
		BEGIN	
			if rising_edge(clk_i) then 
					tdc_data_buf(5 downto 3)  <= tdc_data_buf(2 downto 0);  	---TDC 1ns precision	
			end if;
  end process;
		

end Behavioral;

