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_control is
	port (
-- general
	clk, reset, reset_largo: in std_logic;
	soft_reset:in std_logic;
	orbit_rst:in std_logic;
	db_in: in std_logic_vector (15 downto 0);

-- transmiter + control
	valen, is_trigger_p, valen_sc: out std_logic;
	token_p: out std_logic_vector (5 downto 0);
	ceros_done: in std_logic_vector (5 downto 0);
	txena: out std_logic;
	txena_in: in std_logic;
	evid: out std_logic_vector (11 downto 0);
	s_data: out std_logic_vector (15 downto 0);
	reg_ROSWpar_p: out std_logic; --12enero2011
-- TIM
	event_reset:in std_logic;
	bcnt_res, bcnt_strobe, L1A, SC_L1A, local_L1A: in std_logic; 
	evcnt_high_strobe, evcnt_low_strobe: in std_logic;
	bcnt: in std_logic_vector(11 downto 0);
--feb08	enw_trg_counter: in std_logic;
	--enw_orbit_counter_h, enw_orbit_counter_l: in std_logic;
	enw_evint_counter:in std_logic;
--feb 08	trigger_counter_p: out std_logic_vector(15 downto 0);
	orbit_counter_p: out std_logic_vector(23 downto 0);--(29 downto 0);
	event_int_counter_p: out std_logic_vector(11 downto 0);
	fblock_full_p: out std_logic_vector(2 downto 0);
	resynch_L1A_FF: in std_logic;
	resynch_ceros_to: in std_logic;
-- mascaras, registros, time out
	enw_crtimed_out, dis_crtimo_mask, ena_sc_trigger, dis_L1A: in std_logic;
	ena_send_bunch, ena_send_orbit, sel_local_evid: in std_logic; 
	ceros_mask: in std_logic_vector (5 downto 0);
	sc_timed_out: in std_logic;
	ceros_timed_out_p: out std_logic_vector (5 downto 0);
	lives: in std_logic_vector(5 downto 0);
	cr_timeout_value: in std_logic_vector (11 downto 0);
	enw_bcnt, enw_evcnt_h, enw_evcnt_l: in std_logic;
	fblock_count_2_p, fblock_count_1_p, fblock_count_0_p: out std_logic_vector (7 downto 0); 
	bunch_number_p: out std_logic_vector (11 downto 0);
	event_number_p: out std_logic_vector (23 downto 0);
	ev_size: out std_logic_vector (15 downto 0); --feb08
    load_evsize:out std_logic; --dec2010
	L1A_threshold: in std_logic_vector(7 downto 0);
	dis_send_cerosdebug: in std_logic; --feb09
	ros_waiting: out std_logic
	);		
end rc_control;

-- tareas de transmision
-- enviar event header
-- pasar token de 0 a 5, chequeando mascaras, timed out (y paridad de envíos)
-- enviar event trailer

architecture arch of rc_control is
--FSM
type state_type is (
	wait_trigger, --wait_ttc_1, wait_ttc_2,
	adv_fblock_1, adv_fblock_2,
	start_event, 
	send_L1A_FF_1,send_L1A_FF_2,
	send_header_1,	send_header_2,
     send_orbit_1, send_orbit_2,
     send_orbit_3, send_orbit_4,
	send_bunch_1,	send_bunch_2,
	apago_txena,
	first_ceros, next_ceros, check_id, wait_crdone,
	send_errorw1,send_errorw2,
	send_errorw3, --feb09,
	send_trailer_1, send_trailer_2, 
	send_trailer_3,   --2feb09  15ene09
	timeout_1a,timeout_1b,
	timeout_1, timeout_2, timeout_3, timeout_4 
	);
signal state: state_type;

--señales
signal token, this_ceros_done, this_mask, this_ceros_timed_out: std_logic;
signal ceros_id: std_logic_vector (6 downto 0);
signal ceros_timed_out: std_logic_vector (5 downto 0);
signal is_trigger: std_logic;
signal bunch_number: std_logic_vector (11 downto 0);	 
signal event_number: std_logic_vector (23 downto 0);	 
--signal time_counter: std_logic_vector (12 downto 0);
signal time_counter: std_logic_vector (13 downto 0); --dic cris


signal time_out, time_start: std_logic;
signal txena_par: std_logic;
--feb08 signal trigger_counter:std_logic_vector(15 downto 0); 
signal word_count: std_logic_vector(16 downto 0);

-- TTC
signal bcnt_reg: std_logic_vector (11 downto 0);
signal bcnt_strobe_reg, evcnt_high_strobe_reg, evcnt_low_strobe_reg: std_logic;
signal SC_L1A_reg: std_logic;

-- formatos
signal 	fmt_header_1, fmt_header_2, fmt_trailer_1, fmt_trailer_2,
		fmt_ceros_timeout_1, fmt_ceros_timeout_2,
		fmt_bunch_1, fmt_bunch_2,
          fmt_orbit_1, fmt_orbit_2, 
          fmt_orbit_3, fmt_orbit_4: std_logic_vector (15 downto 0);

constant fmt_ceros_fill: std_logic_vector (15 downto 0):= X"0000";

-- componentes
-- FIFO de 255x12
component fifo_255x12 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(11 downto 0);
         fifo_gsr_in:     IN  std_logic;
         read_data_out:   OUT std_logic_vector(11 downto 0);
         full_out:        OUT std_logic;
         empty_out:       OUT std_logic;
         fifocount_out:   OUT std_logic_vector(7 downto 0));
end component;

-- señales de block fifos
signal read_fblock: std_logic;							
signal fblock_full, fblock_empty: std_logic_vector (2 downto 0);	
signal fblock_not_empty, fblock_full_reg: std_logic;
signal w_bunch_number, w_event_high_counter, w_event_low_counter: std_logic;
signal fblock_data_in: std_logic_vector(11 downto 0);
signal fblock_count_2, fblock_count_1, fblock_count_0: std_logic_vector (7 downto 0); 

signal link_id: std_logic_vector(2 downto 0);
signal evid_p: std_logic_vector(11 downto 0);
signal this_lives: std_logic;
signal is_trigger_lev: std_logic;

signal event_int_counter: std_logic_vector(23 downto 0);
signal bcnt_res_reg: std_logic;

signal int_ev_str1: std_logic;
signal int_ev_str2: std_logic;
signal L1A_total_reg:std_logic;

signal orbit_counter: std_logic_vector(23 downto 0);--  (15 downto 0);
signal orbit_counter_long: std_logic_vector(23 downto 0);--(29 downto 0);
signal fmt_L1A_FF_1,fmt_L1A_FF_2:std_logic_vector(15 downto 0);
signal L1A_FF_send_error: std_logic;

signal liv_aux1,liv_aux2,liv_aux3: std_logic; --16dic08

signal fmt_cerrorw1,fmt_cerrorw2: std_logic_vector(15 downto 0); --15ene09
signal any_timedout: std_logic; --15ene09

signal reg_ROSWpar: std_logic; --12enero2011

begin

reg_ROSWpar_p <= reg_ROSWpar;  --12enero2011

-- FIFOS de event y bunch counters ---------------------------------------------------
-- bunch counter
FF0:  fifo_255x12 port map (
         clock_in=>clk,							--: IN  std_logic;
         read_enable_in=>read_fblock,				--: IN  std_logic;
         write_enable_in=>w_bunch_number,			--: IN  std_logic;
         write_data_in=>fblock_data_in,				--: IN  std_logic_vector(7 downto 0);
--16dic08         fifo_gsr_in=>reset,						--: IN  std_logic;
         fifo_gsr_in=>soft_reset,						--: IN  std_logic;
         read_data_out=>bunch_number,				--: OUT std_logic_vector(7 downto 0);
         full_out=>fblock_full(0),					--: OUT std_logic;
         empty_out=>fblock_empty(0),				--: OUT std_logic;
         fifocount_out=>fblock_count_0				--: OUT std_logic_vector(3 downto 0)
	    );

--event counter high
FF1:  fifo_255x12 port map (
         clock_in=>clk, 							--: IN  std_logic;
         read_enable_in=>read_fblock, 				--: IN  std_logic;
         write_enable_in=>w_event_high_counter, 		--: IN  std_logic;
         write_data_in=>fblock_data_in, 			--: IN  std_logic_vector(7 downto 0);
--16dic08         fifo_gsr_in=>reset,						--: IN  std_logic;
         fifo_gsr_in=>soft_reset,						--: IN  std_logic;
         read_data_out=>event_number(23 downto 12),	--: OUT std_logic_vector(7 downto 0);
         full_out=>fblock_full(1), 				--: OUT std_logic;
         empty_out=>fblock_empty(1), 				--: OUT std_logic;
         fifocount_out=>fblock_count_1 				--: OUT std_logic_vector(3 downto 0)
	    );

-- event counter low
FF2:  fifo_255x12 port map (
         clock_in=>clk, 							--: IN  std_logic;
         read_enable_in=>read_fblock, 				--: IN  std_logic;
         write_enable_in=>w_event_low_counter, 		--: IN  std_logic;
         write_data_in=>fblock_data_in,				--: IN  std_logic_vector(7 downto 0);
--16dic08         fifo_gsr_in=>reset,						--: IN  std_logic;
         fifo_gsr_in=>soft_reset,						--: IN  std_logic;
         read_data_out=>event_number(11 downto 0), 	--: OUT std_logic_vector(7 downto 0);
         full_out=>fblock_full(2), 				--: OUT std_logic;
         empty_out=>fblock_empty(2), 				--: OUT std_logic;
         fifocount_out=>fblock_count_2 				--: OUT std_logic_vector(3 downto 0)
	    );

	 -- queremos poder escribir en estas fifos desde el VME y leer la ocupación
w_bunch_number	 <= (not dis_L1A and bcnt_strobe_reg) or enw_bcnt;
w_event_high_counter <= (not dis_L1A and evcnt_high_strobe_reg and not(sel_local_evid)) or enw_evcnt_h or int_ev_str2;
w_event_low_counter	 <= (not dis_L1A and evcnt_low_strobe_reg and not(sel_local_evid)) or enw_evcnt_l or int_ev_str1;
fblock_data_in <= db_in (11 downto 0) when enw_bcnt='1' or enw_evcnt_h='1' or enw_evcnt_l='1' else 
--			bcnt_reg when sel_local_evid='0' else
  			event_int_counter(11 downto 0) when int_ev_str1='1' else
  			event_int_counter(23 downto 12) when int_ev_str2='1' else
			bcnt_reg;

--w_event_high_counter <= (not dis_L1A and evcnt_high_strobe_reg and not(sel_local_evid)) or enw_evcnt_h;
--w_event_low_counter	 <= (not dis_L1A and evcnt_low_strobe_reg and not(sel_local_evid)) or enw_evcnt_l;
--fblock_data_in <= db_in (11 downto 0) when enw_bcnt='1' or enw_evcnt_h='1' 
--			or enw_evcnt_l='1' else bcnt_reg;
-- puertos
ceros_timed_out_p <= ceros_timed_out;
bunch_number_p <= bunch_number;
event_number_p <= event_number;
ros_waiting <= '1' when state=wait_trigger else '0';
fblock_count_2_p <=	fblock_count_2;
fblock_count_1_p <=	fblock_count_1;
fblock_count_0_p <=	fblock_count_0;
--feb 08 trigger_counter_p <= trigger_counter;
fblock_full_p <= fblock_full;
valen_sc <= is_trigger_lev; --rosready valen abril 06
is_trigger_p <= is_trigger_lev;
event_int_counter_p <= event_int_counter(11 downto 0);

orbit_counter_p <= orbit_counter_long;
--orbit_counter_long <= "0000000000000000" & orbit_counter;
orbit_counter_long <= orbit_counter;					  

-----------------------------------------------------------------------------
-- este is_trigger es para que RosMEM se entere que empezamos un nuevo suceso
--
--is_trigger_p <= '1' when state=adv_fblock_1 else '0'; asi es un pulso
--pero no quiero eso, quiero que sea un nivel para saber cuando empieza y cuando acaba
--la transmisión de cada suceso
------------------------------------------------------------------------------

-- formatos (hay que poner los buenos)
--fmt_header_1        <= "00011111" & event_number (23 downto 16) when sel_local_evid='0' else "00011111" & "00000000";
--fmt_header_2        <=  event_number (15 downto 0) when sel_local_evid='0' else "0000" & evid_p;
fmt_header_1        <= "00011111" & event_number (23 downto 16);
fmt_header_2        <=  event_number (15 downto 0);

fmt_trailer_1       <= "00111111" & fblock_full_reg & txena_par & 
				fblock_count_0(7 downto 2);  
--				fblock_count_2(7 downto 6) & 
--				fblock_count_1(7 downto 6) & 
--				fblock_count_0(7 downto 6);  
fmt_trailer_2       <=  word_count(16 downto 1);	-- este es el event word count

fmt_ceros_timeout_1 <= "110" & "11111" & "100" & "11111";
--fmt_ceros_timeout_2	<= X"80" & "00000" & link_id;
fmt_ceros_timeout_2	<= '1' & resynch_ceros_to & "00" & "0000" & "00000" & link_id;

link_id <= 
 "000" when ceros_id="0000001" else --CEROS 0
 "001" when ceros_id="0000010" else --CEROS 1
 "010" when ceros_id="0000100" else --CEROS 2
 "011" when ceros_id="0001000" else --CEROS 3
 "100" when ceros_id="0010000" else --CANAL 24
 "101" when ceros_id="0100000" else --SECTOR COLLECTOR
 "111";  --en teoria esto nunca sale

fmt_L1A_FF_1 <= "110" & "11111" & "110" & "11111";
fmt_L1A_FF_2 <= '1' & resynch_L1A_FF & "00" & X"000";

fmt_bunch_1 <=         "111" & "11111" & "000" & "11111";	 -- formato debug
fmt_bunch_2 <=         "1000" & bunch_number;

fmt_orbit_1 <=         "111" & "11111" & "001" & "11111";
fmt_orbit_3 <=         "111" & "11111" & "010" & "11111";
fmt_orbit_2 <=         '1' & orbit_counter_long (14 downto 0);
fmt_orbit_4 <=         '1' & "000000" & orbit_counter_long (23 downto 15);

fmt_cerrorw1 <=       "111" & "11111" & "100" & "11111";
fmt_cerrorw2 <=	    "0000000000" & ceros_timed_out;
-- trigger
-- funciona con SC_L1A, local_L1A y con los STROBES

--------------------------------------------
-- los datos del SC se almacenan en una fifo para
-- poderlos leer de 16 en 16 bits intercalando los 
-- formatos correspondientes (en trg_ros)
--------------------------------------------

	-- primero registramos todo
process (clk, soft_reset)
begin
	if soft_reset='1' then
	    bcnt_strobe_reg       <= '0';
	    bcnt_reg              <= (others => '0');
	    SC_L1A_reg            <= '0';
	    int_ev_str1 <='0';
	    int_ev_str2 <='0';
		 L1A_total_reg <= '0';
	elsif clk'event and clk='1' then
		L1A_total_reg <= ((not dis_L1A) and L1A) or (SC_L1A and ena_sc_trigger) or local_L1A;
	    bcnt_strobe_reg       <= bcnt_strobe;
	    bcnt_reg              <= bcnt;
	    if ena_sc_trigger='1' then	    -- se puede inhabilitar el trigger del SC 
	      SC_L1A_reg <= SC_L1A;		    -- e independientemente la lectura de los datos del SC
	    end if;
	    if sel_local_evid='1' then
		 	int_ev_str1 <=  L1A_total_reg;
			int_ev_str2 <=int_ev_str1;
	    else 
    		int_ev_str1 <= '0';
			int_ev_str2 <= '0';
	    end if;
	end if;
end process;

  process (clk, soft_reset)
begin
	if soft_reset='1' then
	    evcnt_high_strobe_reg <= '0';
	    evcnt_low_strobe_reg  <= '0';
	elsif clk'event and clk='1' then
	    evcnt_high_strobe_reg <= evcnt_high_strobe;
	    evcnt_low_strobe_reg  <= evcnt_low_strobe;
	end if;
end process;
	-- ahora generamos is_trigger
	-- avanzamos la lectura de las fifos con read_fblock en state: adv_fblock_1
	-- 
	-- el hacer el disparo con cualquier 'counter' permite que funcione en todos los modos 
	-- del TTC, pero ¿hay que esperar n CC antes de leer las fifos?
	-- 
fblock_not_empty <= not and_reduce(fblock_empty);	 -- alguna no está vacía
is_trigger <= ((not dis_L1A) and fblock_not_empty) or SC_L1A_reg or local_L1A;

-- secuencia del token
-- tenemos 4 ceros, 1 canal ROB local y el SC, o sea 6 fuentes de datos
-- la idea es tratarlas todas por igual
--
token_p 				<= multi_and (ceros_id (5 downto 0), token);
this_ceros_done 		<= sumprod (ceros_id (5 downto 0), ceros_done);
this_mask 			<= sumprod (ceros_id (5 downto 0), ceros_mask);
this_ceros_timed_out 	<= sumprod (ceros_id (5 downto 0), ceros_timed_out);
liv_aux3 		<= sumprod (ceros_id (5 downto 0), lives);

--15ene09
any_timedout <= or_reduce(ceros_timed_out);

--Modifico lives para que se active con la transición sólo
--16dic08
process (soft_reset,clk)
begin
	if soft_reset='1' then
		liv_aux1 <= '0';
		liv_aux2 <= '0';
	elsif clk'event and clk='1' then
		liv_aux1 <= liv_aux3;
		liv_aux2 <= liv_aux1;
	end if;
end process;

this_lives <= liv_aux1 and not(liv_aux2);

-- registrando bajamos 4 ns!
--
--evid <= trigger_counter (11 downto 0) when sel_local_evid='1' else
--		event_number (11 downto 0);
-- queremos que el evid quede fijado al empezar la lectura de un suceso, 
-- y que no cambie a medio camino por la llegada de otro trigger, que
-- sería el caso del evid local, por lo tanto...	
process (clk)
begin
	if clk'event and clk='1' then
	    evid_p <= event_number (11 downto 0);
	end if;
end process;
evid <= evid_p;

process (soft_reset,clk)
begin
	if soft_reset='1' then
			L1A_FF_send_error <= '0';
	elsif clk'event and clk='1' then
--feb08		if or_reduce (fblock_full)='1' then
		if (fblock_count_2 > L1A_threshold)then --feb08, cambio el FF por un warning overflow
			L1A_FF_send_error <= '1';
		elsif state=send_L1A_FF_1 then
			L1A_FF_send_error <= '0';
		end if;
	end if;
end process;

--12enero2011  registro paridad palabras
process (soft_reset,clk)
begin
	if soft_reset='1' then
			reg_ROSWpar <= '0';
	elsif clk'event and clk='1' then
		if (state=send_trailer_2 and word_count(0)='1')then 
			reg_ROSWpar <= '1';
	     elsif enw_crtimed_out='1' then
			reg_ROSWpar <= db_in(15);
		end if;
	end if;
end process;


tokenpr: process (clk, soft_reset)
begin
  if soft_reset='1' then		   
	  txena <= '0';
	  token <= '0';
	  ceros_id <= (others => '0');
	  valen <= '0';
	  is_trigger_lev <= '0';
	  read_fblock <= '0';
	  time_start <='0';
	  state <= wait_trigger;
	  ev_size <= (others=>'0');
       load_evsize <= '0'; --dec2010
	    
  elsif clk'event and clk='1' then

    case state is
	  when wait_trigger =>
	    ev_size <= (others=>'0');
	    txena <= '0';
	    token <= '0';
	    valen <= '0';
	    time_start <='0';
	    ceros_id <= (others => '0');
	    read_fblock <= '0';
	    is_trigger_lev <= '0';
	    load_evsize <= '0'; --dec2010
	    if is_trigger='1' then
	      state <= adv_fblock_1;
	    end if;

-- lectura de fifos, comprobar que no hay que esperar n CC antes de leer las TTC fifos
	  when adv_fblock_1 =>
	    ev_size <= (others=>'0');  --dec2010 ev_size register coge valores raros
	    read_fblock <= '1';
	    state <= adv_fblock_2;
    	    is_trigger_lev <= '1';

	  when adv_fblock_2 =>
	    fblock_full_reg <= or_reduce (fblock_full);  -- este es el punto de máximo llenado de las fifos
	    read_fblock <= '0';
	    state <= start_event;

	  when start_event =>
	    valen <= '1';			  		-- todo el mundo a trabajar
	    state <= send_header_1;

	  when send_header_1 =>
	    txena <= '1';
	    s_data <= fmt_header_1;
	    state <= send_header_2;

	  when send_header_2 =>
	    s_data <= fmt_header_2;
--	  	 if (or_reduce (fblock_full)='1') then 
		 --NO, justo ahora lo más probable es que no esté llena, porque acabo
		 --de sacar un L1A, quiero que si ha estado llena en algún momento 
		 --me envie el error, y luego resetee el error
		 if L1A_FF_send_error='1' then
		 	state <= send_L1A_FF_1;
	    elsif ena_send_orbit='1' then
	      state <= send_orbit_1;
       elsif ena_send_bunch='1' then 
	      state <= send_bunch_1;
       else
           state <= apago_txena;
	    end if;

	  when send_L1A_FF_1 =>
	    txena <= '1';
	    s_data <= fmt_L1A_FF_1;
	    state <= send_L1A_FF_2;

	  when send_L1A_FF_2 =>
	    txena <= '1';
	    s_data <= fmt_L1A_FF_2;
	    if ena_send_orbit='1' then
	      state <= send_orbit_1;
       elsif ena_send_bunch='1' then 
	      state <= send_bunch_1;
       else
           state <= apago_txena;
	    end if;

	   when send_orbit_1 =>
		s_data <= fmt_orbit_1;
		state <= send_orbit_2;

	   when send_orbit_2 =>
		s_data <= fmt_orbit_2;
      state <= send_orbit_3;

	   when send_orbit_3 =>
		s_data <= fmt_orbit_3;
		state <= send_orbit_4;

	   when send_orbit_4 =>
		s_data <= fmt_orbit_4;
          if ena_send_bunch='1' then
            state <= send_bunch_1;
          else
            state <= apago_txena;
          end if;

	   when send_bunch_1 =>
		s_data <= fmt_bunch_1;
		state <= send_bunch_2;

	   when send_bunch_2 =>
		s_data <= fmt_bunch_2;
		state <= apago_txena;

	   when apago_txena =>
	   	txena<= '0';
		state <= first_ceros;
	   		
-- leemos ceros si está habilitado (y no ha habido timeout o el timeout está inhabilitado)
	  when first_ceros =>
	    time_start <= '0';
	    txena <= '0';
	    ceros_id <= "0000001";
	    if ceros_mask(0)='1' 	 
	    			or (ceros_timed_out(0)='1' and dis_crtimo_mask='0') 
				or ceros_done(0)='1' then
	      state <= next_ceros;
	    else
	      token <= '1';
	      state <= wait_crdone;
	    end if; 

	  when next_ceros =>
	     time_start <= '0';
 	     txena <= '0';	--martes 11-4-06
	    	ceros_id <= ceros_id (5 downto 0) & '0';
		state <= check_id;

	  when check_id =>
	    time_start <= '0';
	    txena <= '0';  --martes 11-4-06
	    if ceros_id(6)='1' then
--		      state <= send_trailer_1;--15ene09
			if (any_timedout='1' and dis_send_cerosdebug='0') then  --15ene09  ENVIO PALABRA DE ERROR DE CEROS TIMEOUT
		      	state <= send_errorw1;--15ene09
  			else
	      		state <= send_trailer_1;  --15ene09
			end if;
	      token <= '0';		 --feb09
	    elsif this_mask='1' 
	    			or (this_ceros_timed_out='1' and dis_crtimo_mask='0')
				or this_ceros_done='1' then
	      state <= next_ceros;
	      token <= '1';		 --feb09
	    else
	      token <= '1';		 --feb09
	      state <= wait_crdone;
	    end if;

--15ENE09 ESTOS DOS ESTADOS NUEVOS PARA ENVIAR PALABRA DEBUGGING 4 CEROS STATUS
	  when send_errorw1 =>
	      time_start <= '0';
	   	 state <= send_errorw2;--15ene09
	      token <= '0';
	      valen <= '0';
	      txena <= '1';		 
	      s_data <= fmt_cerrorw1;


	  when send_errorw2 =>
	      time_start <= '0';
--feb09 		 state <= send_trailer_1;--15ene09
 		 state <= send_errorw3;--15ene09
	      token <= '0';
	      valen <= '0';
	      txena <= '1';		 
	      s_data <= fmt_cerrorw2;

--feb09, no le daba tiempo a registrar el txena de send_errorw2
	  when send_errorw3 =>
	      time_start <= '0';
 		 state <= send_trailer_1;--15ene09
	      token <= '0';
	      valen <= '0';
	      txena <= '0';		 

	-- suponemos que si ceros termina bien la paridad de envios es 0
	  when wait_crdone =>
	    time_start <= '1';
	    if this_ceros_done='1' then
	      token <= '0';
	      state <= next_ceros;
	    elsif time_out='1' then
		 state <= timeout_1;	 -- ceros acaba mal, comprobar paridad de envíos
	    end if;

	  when send_trailer_1 =>
	    valen <= '0';
	    txena <= '1';		--martes 11-4-06	 
	    s_data <= fmt_trailer_1;
	    state <= send_trailer_2;

	  when send_trailer_2 =>
	    txena <= '1'; --martes 11-4-06
	    s_data <= fmt_trailer_2;
	    state <= send_trailer_3;
--2feb09	    state <= wait_trigger;  --15ene09
	    ev_size <= word_count(16 downto 1); --feb08
		load_evsize<='1';	 --dec2010 coge valores raros

--15ene09
--me gustaria quitar este estado, no hace falta no????
	  when send_trailer_3 =>
	    txena <= '0';
----	    if is_trigger='1' then  Lo quito para tener un is_trigger de nivel en rosmem
----	      state <= adv_fblock_1;
----	    else
	      state <= wait_trigger;
----	    end if;
		load_evsize<='0';	 --dec2010 coge valores raros

-- timeout de CEROS
-- poner fill si no estamos alineados
-- primero veamos si la paridad de envios ha sido 0
	  when timeout_1 =>
	    time_start <= '0';
	    token <= '0';
	    state <= timeout_1a;

	  when timeout_1a =>
	    state <= timeout_1b;

	  when timeout_1b =>
	    state <= timeout_2;
	    if txena_par='1' then
	      txena <= '1';
		   s_data <= fmt_ceros_fill;
	    end if;

	  when timeout_2 =>
	    txena <= '1';
	    s_data <= fmt_ceros_timeout_1;
	    state <= timeout_3;

	  when timeout_3 =>
	    s_data <= fmt_ceros_timeout_2;
	    state <= timeout_4;

	  when timeout_4 =>
	    txena <= '0';
	    state <= next_ceros;

      end case;
--    end if;
  end if;

end process tokenpr;

-- CEROS timmed out
process(clk, soft_reset)
begin
	if soft_reset='1' then
	    ceros_timed_out <= (others =>'0');
	elsif (clk'event and clk='1') then
	  if enw_crtimed_out='1' then
	    ceros_timed_out <= db_in (5 downto 0); 
	  elsif state=timeout_1 then
	    ceros_timed_out <= ceros_timed_out or ceros_id (5 downto 0);
	  elsif ceros_id(6)='1' and sc_timed_out='1' then
	    ceros_timed_out(5) <= '1';
	  end if;
	end if;
end process;

-- timer (hay otra version mas reducida, decidir con una simulacion)

--diciembre 2014 cambio el timeout de las CEROS, dejo el registro solo para el TSC channel

process(clk, soft_reset) --time_start, cr_timeout_value)
begin
	if soft_reset='1' then
	  time_counter <= (others => '0'); 
	elsif (clk'event and clk='1') then
	  if (time_start='0' or this_lives='1') then ---es cualquier CEROS
	--	    	time_counter (time_counter'high-1 downto 0) <= cr_timeout_value & '0'; 
		   	time_counter (time_counter'high-1 downto 0) <= X"FFF" & '0'; 
	   	 	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;

-- paridad de envios: contamos txena_in
--
-- seguro que esto vale para algo? pues parece que si
--
process(clk, soft_reset)
begin
	if soft_reset='1' then
	  txena_par <= '0';	  
	elsif (clk'event and clk='1') then
	  if txena_in='1' then
	    txena_par <= not txena_par;
	  end if;
	end if;
end process;

-- word count por suceso (contamos txena_in)
-- o sea, word count de 16 bits
process (clk, soft_reset)
begin
	if soft_reset='1' then
	  word_count <= "00000000000000010";	  
	elsif (clk'event and clk='1') then
	  if (state=adv_fblock_1 or state=wait_trigger) then
	    word_count <= "00000000000000010"; 	-- para incluir el 2do trailer
	  elsif txena_in='1' then
	    word_count <= word_count +1;
	  end if;
	end if;

end process;

-- feb 08 lo quito trigger counter
--process(clk, reset)
--begin
--	if reset='1' then
--	  trigger_counter <= (others =>'0');	  
--	elsif (clk'event and clk='1') then
--	  if enw_trg_counter='1' then
--	    trigger_counter <= db_in;
--	  elsif L1A='1' or SC_L1A='1' or local_L1A='1' then
--	    trigger_counter <= trigger_counter +1;
--	  end if;
--	end if;
--end process;

-- Internal event counter
process(clk, soft_reset)
begin
	if soft_reset='1' then
	  event_int_counter <= (others =>'1');	  
	elsif (clk'event and clk='1') then
	  if event_reset='1' then
		  event_int_counter <= (others =>'1');	  
	  elsif enw_evint_counter='1' then
	      event_int_counter <= "000000000000" & db_in(11 downto 0);
	  elsif (L1A='1' and dis_L1A='0') or (SC_L1A='1' and ena_sc_trigger='1') or local_L1A='1' then
	    event_int_counter <= event_int_counter +1;
	  end if;
	end if;

end process;

process(clk, reset)
begin
	if reset='1' then
		bcnt_res_reg <= '0';
	elsif clk'event and clk='1' then
		bcnt_res_reg <= bcnt_res;
  end if;
end process;

process(clk, reset_largo,orbit_rst)
begin
	if reset_largo='1' or orbit_rst='1'then
--feb08 resetear orbitas a la vez.
	  orbit_counter <= (others =>'0');	  
	elsif (clk'event and clk='1') then
	  if bcnt_res_reg='1' then
	    orbit_counter <= orbit_counter +1;
	  end if;
	end if;
end process;


end arch;


