library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all; 
use ieee.std_logic_misc.all;
use work.pack.all;

entity rc_trg_ros is
	port (
-- general
	clk, reset,soft_reset: in std_logic;
	--reset_largo,: in std_logic;
	db_in: in std_logic_vector (15 downto 0);
	enw_fblock: in std_logic;

-- transmiter + control
	valen, token, valen_sc: in std_logic;
	trg_done: out std_logic;
	lives_sc: out std_logic;
	txena: out std_logic;
	evid: in std_logic_vector (11 downto 0);
	s_data: out std_logic_vector (15 downto 0);

-- TIM
	ros_ready: out std_logic;
	trg_strobe_in: in std_logic;
	trg_data_in: in std_logic_vector (15 downto 0);

-- mascaras, registros, time out
	enw_crtimed_out, dis_crtimo_mask, ena_trg_data, read_int_scfifo: in std_logic;
	sc_timed_out_p, sc_fblock_full: out std_logic;
	cr_timeout_value: in std_logic_vector (11 downto 0);
	sc_fblock_count_p: out std_logic_vector (8 downto 0) 
	);		
end rc_trg_ros;

-- esto es como una ceros para los datos del trigger
-- tareas:
-- 1. con valen pasamos los datos del SC a la fifo
-- 2. con token los transmitimos
--
-- esto no funciona con superposición de triggers
--
architecture arch of rc_trg_ros is

--FSMs
	-- lectuta de datos del SC
type secol_type is (
	wait_valen, send_ready, wait_strobe_0, wait_to_transmit,
	fb_error,
	sc_timeout
	);

	-- envío de datos
type state_type is (
	start_event, 
	send_header_1,	send_header_2,
	send_timeout_1, send_timeout_2,
	send_SC_fifofull_1, send_SC_fifofull_2,
	send_data_1, send_data_2,
	send_trailer_1, send_trailer_2,
	wait_trg_valen_0
	);

signal secol: secol_type;
signal state: state_type;

-- timer
signal time_counter: std_logic_vector (12 downto 0);
signal time_out, time_start: std_logic;

-- sector collector
signal trg_strobe, sc_timed_out: std_logic;
signal trg_data: std_logic_vector (15 downto 0);

-- transmisión de datos
signal word_count: std_logic_vector (15 downto 0);

-- formatos
signal 	fmt_header_1, fmt_header_2, fmt_data_1, fmt_data_2,		
		fmt_trailer_1, fmt_trailer_2: std_logic_vector (15 downto 0);
signal fmt_timeout_1, fmt_timeout_2: std_logic_vector (15 downto 0);
signal fmt_fffull_1, fmt_fffull_2: std_logic_vector (15 downto 0);

-- componentes
--component fifo_255x16 port (
  --       clock_in:        IN  std_logic;
    --     read_enable_in:  IN  std_logic;
    --     write_enable_in: IN  std_logic;
    --     write_data_in:   IN  std_logic_vector(15 downto 0);
    --     fifo_gsr_in:     IN  std_logic;
    --     read_data_out:   OUT std_logic_vector(15 downto 0);
    --     full_out:        OUT std_logic;
    --     empty_out:       OUT std_logic;
    --     fifocount_out:   OUT std_logic_vector(7 downto 0));
--end component;
component sc_fifo512_cris port(
   		clock_in:        IN  std_logic;
         read_enable_in:  IN  std_logic;
         write_enable_in: IN  std_logic;
         write_data_in:   IN  std_logic_vector(15 downto 0);
         fifo_gsr_in:     IN  std_logic;
         read_data_out:   OUT std_logic_vector(15 downto 0);
         full_out:        OUT std_logic;
         empty_out:       OUT std_logic;
         fifocount_out:   OUT std_logic_vector(8 downto 0)); --ponia 7 to 0
END component;

-- señales de block fifo
signal fblock_read, fblock_write: std_logic;							
signal fblock_full, fblock_empty: std_logic;
signal fblock_data_in, fblock_data_out: std_logic_vector(15 downto 0);	
--signal fblock_count: std_logic_vector(7 downto 0);
signal fblock_count: std_logic_vector(8 downto 0);

begin

-- FIFO de SC data ---------------------------------------------------
--FF0:  fifo_255x16 port map (
  --       clock_in=>clk,					--: IN  std_logic;
  --       read_enable_in=>fblock_read,		--: IN  std_logic;
  --       write_enable_in=>fblock_write,		--: IN  std_logic;
  --       write_data_in=>fblock_data_in,		--: IN  std_logic_vector(7 downto 0);
  --       fifo_gsr_in=>reset,				--: IN  std_logic;
  --       read_data_out=>fblock_data_out,	--: OUT std_logic_vector(7 downto 0);
  --       full_out=>fblock_full,			--: OUT std_logic;
  --       empty_out=>fblock_empty,			--: OUT std_logic;
  --       fifocount_out=>fblock_count		--: OUT std_logic_vector(3 downto 0)
--    );
FF0: sc_fifo512_cris port map (
			clock_in=> clk,
         read_enable_in=> fblock_read,
         write_enable_in=> fblock_write,
         write_data_in=> fblock_data_in,
         fifo_gsr_in=> soft_reset,  --feb09
         read_data_out=> fblock_data_out,
         full_out=> fblock_full,
         empty_out=> fblock_empty,
         fifocount_out=> fblock_count); --ponia 7 to 0
											  
	 -- queremos poder escribir en estas fifos desde el VME y leer la ocupación
--fblock_write	<= '0' when secol=fb_error else trg_strobe or enw_fblock;
fblock_write	<= '0' when secol=fb_error else ((trg_strobe or enw_fblock) and ena_trg_data);
fblock_data_in <= db_in when enw_fblock='1' else trg_data;

--------------------------------------------------------------------------------------
-- puertos
sc_timed_out_p <= sc_timed_out;
sc_fblock_full <= fblock_full; --domingo 9-4-06
sc_fblock_count_p <= fblock_count;
lives_sc <= '1'; --domingo 9-4-06   nunca da time out de sector collector, sólo da timeout de canal

-- formatos (hay que poner los buenos)
-- poner txena_par y fblock_full en alguna parte!!!
fmt_header_1	<= "000" & "11001" & evid(11 downto 4);
fmt_header_2	<= evid(3 downto 0) & "000" & fblock_count;
 
fmt_data_1	<= "100" & "11001" & X"00";
fmt_data_2	<= fblock_data_out;

fmt_trailer_1	<= "001" & "11001" & X"00";
fmt_trailer_2	<=  word_count;

fmt_timeout_1	<= "1101" & "1111" & "00011001"; --Esto es lo que se manda si nunca llega el trg_strobe
fmt_timeout_2	<=  "1000" & X"00" & fblock_empty & "00" & fblock_full; --SC timedout link ID 25

fmt_fffull_1	<= "1101" & "1111" & "01111001";
fmt_fffull_2	<=  "1000" & X"00" & "0001"; --SC fifo full link ID 25

	-- primero registramos todo
process (clk, soft_reset)
begin
	if soft_reset='1' then
	  trg_data <= (others => '0');
	  trg_strobe <= '0';
	elsif clk'event and clk='1' then
	  trg_data <= trg_data_in;
	  trg_strobe <= trg_strobe_in;
	end if;
end process;

-- secuencia de lectura de datos del SC
 
sc_pr: process (clk, soft_reset)
begin
	if soft_reset='1' then		    -- comprobar que están todas
	  ros_ready <= '0';
	  secol <= wait_valen;
     time_start <= '0';

	elsif clk'event and clk='1' then

	  case secol is

-- El SC podría:
-- no responder a ROS_READY: timeout -> inhabilitar canal
-- si reponder pero no bajar trg_strobe y llenar la fifo -> inhabilitar canal
-- NO, en principio no bloqueo el canal si me llenan la fifo.
	-- ena_trg_data es "disable SC trigger data" invertida	  
	  when wait_valen =>
	    time_start <= '0';
		 ros_ready <= '0'; --rosready valen abril 06
	    if valen_sc='1' then  --rosready valen abril 06		 
	      if ena_trg_data='1' and read_int_scfifo='1' then
	          secol <= wait_to_transmit;
	      elsif ena_trg_data='1' and (sc_timed_out='0' or dis_crtimo_mask='1') then
	          secol <= send_ready;
	      end if;
	    end if;

    	when send_ready =>
	      time_start <= '1';
		   ros_ready <= '1'; 	--rosready valen abril 06
	      if trg_strobe='1' then
	          secol <= wait_strobe_0;
	      elsif time_out='1' then
	          secol <= sc_timeout;
	      end if;

    	when wait_strobe_0 =>
	     time_start <= '0';
	     if trg_strobe='0' then
	        secol <= wait_to_transmit;
	     elsif fblock_full='1' then
	         secol <= fb_error;
	     end if;

	  when wait_to_transmit =>
	    time_start <= '0';
	    ros_ready<='0';--feb08
	    if valen_sc='0' then 	 --rosready valen abril 06
	     secol <= wait_valen;	--de momento no
	    end if;

	  when sc_timeout =>
	    time_start <= '0';
	    if valen_sc='0' then 	 --rosready valen abril 06
	      secol <= wait_valen;	
	    end if;

      when fb_error =>   
	    time_start <= '0';
    	    ros_ready<='0';--feb08
	    if valen_sc='0' then 	 --rosready valen abril 06
	      secol <= wait_valen;	
	    end if;

	  end case;
	end if;
end process sc_pr;

-----------------------------------------------------------------------


trpr: process (clk, soft_reset)
begin
	if soft_reset='1' then
	  txena <= '0';
	  trg_done <= '0';
	  state <= start_event;
  	  word_count <= (others=>'0');
	elsif clk'event and clk='1' then
	
	  case state is

	  when start_event =>
	      txena <= '0';
	      trg_done <= '0';
	 	 if token='1' then	
			if ena_trg_data='1' and secol=sc_timeout then
	        		state <= send_timeout_1;
	    	elsif ena_trg_data='1' and (secol=wait_to_transmit or secol=fb_error) then
	        		state <= send_header_1;
		   		word_count <= X"0" & "000" & fblock_count;   -- cuento 32-bit words
			end if;
	    end if;
--enviamos el timeout
	  when send_timeout_1 =>
	    txena <= '1';
	    s_data <= fmt_timeout_1;
	    state <= send_timeout_2;
  	    word_count <= word_count+1;

	  when send_timeout_2 =>
	    s_data <= fmt_timeout_2;
	    state <= wait_trg_valen_0;

-- enviamos event header
	  when send_header_1 =>
	    txena <= '1';
	    s_data <= fmt_header_1;
	    state <= send_header_2;
  	    word_count <= word_count+1;

	  when send_header_2 =>
	     s_data <= fmt_header_2;
  		  word_count <= word_count+1;  --Esta es para incluir la del trailer 
 	     if fblock_full='1' then  --se ha llenado
	      	 state <= send_SC_fifofull_1;
		      fblock_read <= '0';			  -- preparacion de datos
		 elsif fblock_empty='1' then	--esta vacia, paso a cabeceras
		      state <= send_trailer_1;
		      fblock_read <= '0';			  -- preparacion de datos
		 else 				    --ok, mando datos
		      state <= send_data_1;
			 fblock_read <= '1';			  -- preparacion de datos
		 end if;

--enviamos fifo full error
	  when send_SC_fifofull_1 =>
	      txena <= '1';
	      s_data <= fmt_fffull_1;
	      state <= send_SC_fifofull_2;
           fblock_read <= '0';			  -- preparacion de datos
  		 word_count <= word_count+1; --32 bits

	  when send_SC_fifofull_2 =>
	      txena <= '1';
	      s_data <= fmt_fffull_2;
	      state <= send_data_1;
           fblock_read <= '1';			  -- preparacion de datos
 
-- enviamos datos
	  when send_data_1 =>
	      fblock_read <= '0';
	      s_data <= fmt_data_1;	
	      state <= send_data_2;
	      
	  when send_data_2 =>
	    s_data <= fmt_data_2;
	    if fblock_empty='0' then
	      fblock_read <= '1';
	      state <= send_data_1;
	    else
	      state <= send_trailer_1;
	    end if;

-- enviamos trailer
	  when send_trailer_1 =>
	    s_data <= fmt_trailer_1;
	    state <= send_trailer_2;

	  when send_trailer_2 =>
	    s_data <= fmt_trailer_2;
	    state <= wait_trg_valen_0;

	  when wait_trg_valen_0 =>
	    trg_done <= '1';
	    txena <= '0';
	    if valen='0' then	    
	      state <= start_event;
	    end if;

       end case;
	end if;

end process trpr;

-- sector collector timmed out
process(clk, soft_reset)
begin
	if soft_reset='1' then
	  sc_timed_out <= '0';
	elsif (clk'event and clk='1') then
	  if enw_crtimed_out='1' then
	    sc_timed_out <= db_in (5); 
	  elsif secol=sc_timeout then
	    sc_timed_out <= '1';
	  end if;
	end if;
end process;

-- timer
process(clk, soft_reset) 
begin
	if soft_reset='1' then
	  time_counter <= (others => '0'); 
	elsif (clk'event and clk='1') then
	  if time_start='0' then
	    time_counter (time_counter'high-1 downto 0) <= cr_timeout_value; 
	    time_counter (time_counter'high) <= '0';
	  else 
	    if time_out='0' then
	      time_counter <= time_counter - 1;
	    end if;
	  end if;
	end if;
end process;

process(clk, time_start)
begin
	if time_start='0' then
	  time_out <= '0';
	elsif (clk'event and clk='1') then
	    time_out <= time_counter(time_counter'high);
	end if;
end process;


end arch;



	
