library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity ctrl_x is 
	generic(time_600:  integer:= 750; tim_bits_600: integer:= 10;  --600us
		time_90:   integer:=  84; tim_bits_90:  integer:=  7;  --67us
		time_10:   integer:=  12; tim_bits_10:  integer:=  4;  --10us
		time_60:   integer:= 100; tim_bits_60:  integer:=  7;  --80new--60us
		time_5:    integer:=   6;  tim_bits_5:  integer:=  3;  --5 us
                time_7:    integer:=   8;  tim_bits_7:  integer:=  4); --7 us
	port(
-- general
	clkin_p, sysreset, brd_sel: in std_logic;
	iack, iackin, ds0, ds1, as: in std_logic;
	write, lword: in std_logic;
	am0, am1, am3, am4, am5: in std_logic;
	dtack, g245, iackout, locked: out std_logic;
	add_in: in std_logic_vector(6 downto 0);
	db: inout std_logic_vector(15 downto 0);
	irq: out std_logic_vector(7 downto 1);
	--
-- minicrate TTC
	mctrg, mcbcrst, mcevrst: out std_logic;
-- trigger
	trgnim, trgttl: in std_logic;
	trgttc, trganal, trgros, trgled: out std_logic;
-- pulses
	plsttl: in std_logic_vector(1 downto 0);
	pulse: out std_logic_vector(1 downto 0);
-- interrupt
	int_ext: in std_logic_vector(1 downto 0);
	intled: out std_logic;
-- ROB
	difbcr, diftrg, difrst, difevr: out std_logic;
	jtrktm, jtrkadv, jtrkrst, jtck, jtms, jtdi: out std_logic;
	jtadd: out std_logic_vector (3 downto 0);
	ron: out std_logic_vector(6 downto 0);
	jtdo, fltb, jroberr: in std_logic;
	tdio: inout std_logic;
-- otros
	bcrsttl, evrsttl, robrsttl: in std_logic;
	delay_0, delay_1: out std_logic_vector(6 downto 0);
	veto, done_in: in std_logic;
	done_out: out std_logic;
	trg_dly_p, tp1, tp2, tp3: out std_logic);
end ctrl_x ;

architecture arch of ctrl_x is

signal enw, etr, ds0_clk: std_logic;
signal add_int: std_logic_vector(2 downto 0);
signal add: std_logic_vector(1 downto 0);
signal grp: std_logic_vector(4 downto 0); 
--interrupt
signal int_trg: std_logic;
signal int_ena: std_logic_vector(2 downto 0);  
signal int_lev_0: std_logic_vector(2 downto 0);
signal int_lev_1: std_logic_vector(2 downto 0);
signal int_lev_2: std_logic_vector(2 downto 0);
signal int_vec_0: std_logic_vector(7 downto 0);
signal int_vec_1: std_logic_vector(7 downto 0);
signal int_vec_2: std_logic_vector(7 downto 0);
signal etr_ivec: std_logic_vector(2 downto 0);
signal rst_int: std_logic_vector(2 downto 0);
signal irq_0: std_logic_vector(7 downto 1); 
signal irq_1: std_logic_vector(7 downto 1); 
signal irq_2: std_logic_vector(7 downto 1); 
signal iackout_int0, iackout_int1: std_logic;
--
signal db_in, db_out: std_logic_vector (15 downto 0);
signal reset, trg_bypass, ena_tm: std_logic;
signal ron_reg, jtag_reg: std_logic_vector (6 downto 0);
signal v_bcrst, v_trg, v_robrst, v_evrst, v_tmadv, v_tmrst: std_logic;
signal set_trgin: std_logic; --new
signal v_pulse: std_logic_vector(1 downto 0);
signal fltb_reg: std_logic;
--
signal trigger_in, trigger_out: std_logic;
-- DLL
signal CLKIN, CLK, CLK0, GND : std_logic;
signal not_sysreset: std_logic;

signal dtack_int, dtack_int0, dtack_int1, dtack_int2: std_logic;
signal ack_int, ack_int0, ack_int1, ack_int2: std_logic;

signal veto_long, veto_i, endveto: std_logic;

  component CLKDLL
      port (CLKIN, CLKFB, RST : in STD_LOGIC;
      CLK0, LOCKED : out std_logic);
--      CLK0, CLK90, CLK180, CLK270, CLK2X, CLKDV, LOCKED : out std_logic);
  end component;
  component IBUFG
      port (I : in STD_LOGIC; O : out std_logic);
  end component;
  component BUFG
      port (I : in STD_LOGIC; O : out std_logic);
  end component;

component vmeifc port (
	clk: in std_logic;
	iack, ack_int, dtack_int, ds0, ds1: in std_logic;
	write, brd_sel, lword: in std_logic;
	am0, am1, am3, am4, am5: in std_logic;
	etr, enw, dtack, g245: out std_logic 
	);
end component;

component vmeint port (
	--interrupt
	interrupt, int_ena: in std_logic;  
	add, int_lev: in std_logic_vector(2 downto 0);
	iack, iackin, ds0, as, reset, clk: in std_logic;
	etr_ivec, rst_int, iackout: out std_logic;
	dtack_int, ack_int: out std_logic;
	irq: out std_logic_vector(7 downto 1)); 
end component;

component pulses port (
	clk, reset, etr, enw: in std_logic;
	plsttl, v_pulse: in std_logic_vector(1 downto 0);
	pulse_out: out std_logic_vector(1 downto 0);
	add: in std_logic_vector(1 downto 0);
	grp: in std_logic_vector(4 downto 0);
	db_in: in std_logic_vector(13 downto 0);
	db_out: out std_logic_vector (15 downto 0);
	delay_0, delay_1: out std_logic_vector(6 downto 0));
end component;

component trigger port (
	clk, reset, etr, enw, set_trgin, trigger_in, trg_bypass, veto_long: in std_logic;
	add: in std_logic_vector(1 downto 0);
	grp: in std_logic_vector(4 downto 0);
	db_in: in std_logic_vector(15 downto 0);
	db_out: out std_logic_vector (15 downto 0);
	int_trg, trigger_out, trg_dly_p: out std_logic);
end component;

component onew 
	generic(time_600:  integer:= 750; tim_bits_600: integer:= 10;  --600us
		time_90:   integer:=  84; tim_bits_90:  integer:=  7;  --67us
		time_10:   integer:=  12; tim_bits_10:  integer:=  4;  --10us
		time_60:   integer:=  75; tim_bits_60:  integer:=  7;  --60us
		time_5:    integer:=   6;  tim_bits_5:  integer:=  3;  --5 us
                time_7:    integer:=   8;  tim_bits_7:  integer:=  4); --7 us
	port (
	clk, reset, etr, enw: in std_logic;
	add: in std_logic_vector(1 downto 0);
	grp: in std_logic_vector(4 downto 0);
	db_in: in std_logic_vector (7 downto 0);
	db_out: out std_logic_vector (7 downto 0);
--	r_reg_p, w_reg_p: out std_logic;
	veto_i:in std_logic; 
	endveto: out std_logic;
	tdio: inout std_logic
	);
end component;

component startup_spartan2
  port(GSR: in std_logic);
end component;

begin
GND <= '0';
tp1 <= etr; --P7 
tp2 <= enw; --P151 
tp3 <= GND;

---- DLL
U10: IBUFG port map (I=>CLKIN_P, O=>CLKIN);
U11: CLKDLL port map (CLKIN=>CLKIN, CLKFB=>CLK, RST=>GND, CLK0=>CLK0, LOCKED=>LOCKED);
U12: BUFG port map (I=>CLK0, O=>CLK);
--U13: BUFG port map (I=>ds0, O=>ds0_clk);
ds0_clk<=ds0;	 --nov2011cris

U1: vmeifc port map(
	clk=>clk, --: in std_logic;
	iack=>iack, ack_int=>ack_int, dtack_int=>dtack_int, ds0=>ds0, ds1=>ds1, --: in std_logic;
	write=>write, brd_sel=>brd_sel, lword=>lword, --: in std_logic;
	am0=>am0, am1=>am1, am3=>am3, am4=>am4, am5=>am5, --: in std_logic;
	etr=>etr, enw=>enw, dtack=>dtack, g245=>g245 --: out std_logic 
	);

U2: vmeint port map (
	interrupt=>int_ext(0), int_ena=>int_ena(0), --: in std_logic;  
	add=>add_int, int_lev=>int_lev_0, --: in std_logic_vector(2 downto 0);
	iack=>iack, iackin=>iackin, ds0=>ds0, as=>as, reset=>reset, clk=>clk, --: in std_logic;
	etr_ivec=>etr_ivec(0), rst_int=>rst_int(0), iackout=>iackout_int0, --: out std_logic;
	dtack_int=>dtack_int0, ack_int=>ack_int0, --: out std_logic;
	irq=>irq_0 --: out std_logic_vector(7 downto 1)); 
	);
U3: vmeint port map (
	interrupt=>int_ext(1), int_ena=>int_ena(1), --: in std_logic;  
	add=>add_int, int_lev=>int_lev_1, --: in std_logic_vector(2 downto 0);
	iack=>iack, iackin=>iackout_int0, ds0=>ds0, as=>as, reset=>reset, clk=>clk, --: in std_logic;
	etr_ivec=>etr_ivec(1), rst_int=>rst_int(1), iackout=>iackout_int1, --: out std_logic;
	dtack_int=>dtack_int1, ack_int=>ack_int1, --: out std_logic;
	irq=>irq_1 --: out std_logic_vector(7 downto 1)); 
	);
U4: vmeint port map (
	interrupt=>int_trg, int_ena=>int_ena(2), --: in std_logic;  
	add=>add_int, int_lev=>int_lev_2, --: in std_logic_vector(2 downto 0);
	iack=>iack, iackin=>iackout_int1, ds0=>ds0, as=>as, reset=>reset, clk=>clk, --: in std_logic;
	etr_ivec=>etr_ivec(2), rst_int=>rst_int(2), iackout=>iackout, --: out std_logic;
	dtack_int=>dtack_int2, ack_int=>ack_int2, --: out std_logic;
	irq=>irq_2 --: out std_logic_vector(7 downto 1)); 
	);

U5: pulses port map (
	clk=>clk, reset=>reset, etr=>etr, enw=>enw, --: in std_logic;
	plsttl=>plsttl, v_pulse=>v_pulse, --: in std_logic_vector(1 downto 0);
	pulse_out=>pulse, --: out std_logic_vector(1 downto 0);
	add=>add, --: in std_logic_vector(1 downto 0);
	grp=>grp, --: in std_logic_vector(4 downto 0);
	db_in=>db_in(13 downto 0), --: in std_logic_vector(11 downto 0);
	db_out=>db_out, --: out std_logic_vector (15 downto 0);
	delay_0=>delay_0, delay_1=>delay_1); --: out std_logic_vector(4 downto 0));

U6: trigger port map (
	clk=>clk, reset=>reset, etr=>etr, enw=>enw, set_trgin=>set_trgin, 
	trigger_in=>trigger_in, trg_bypass=>trg_bypass, veto_long=>veto_long, --: in std_logic;
	add=>add, --: in std_logic_vector(1 downto 0);
	grp=>grp, --: in std_logic_vector(4 downto 0);
	db_in=>db_in, --: in std_logic_vector(15 downto 0);
	db_out=>db_out, --: out std_logic_vector (15 downto 0);
	int_trg=>int_trg, trigger_out=>trigger_out, trg_dly_p=>trg_dly_p); --: out std_logic);

U7:onew generic map(
		time_600, tim_bits_600,	time_90, tim_bits_90,
		time_10,  tim_bits_10,  time_60, tim_bits_60,
		time_5,   tim_bits_5,   time_7,  tim_bits_7)
	port map (
	clk=>clk, reset=>reset, etr=>etr, enw=>enw, --: in std_logic;
	add=>add, --: in std_logic_vector(1 downto 0);
	grp=>grp, --: in std_logic_vector(4 downto 0);
	db_in=>db_in(7 downto 0), --: in std_logic_vector (7 downto 0);
	db_out=>db_out(7 downto 0), --: out std_logic_vector (7 downto 0);
--	r_reg_p, w_reg_p: out std_logic;
	veto_i => veto_i, 
	endveto => endveto,
	tdio=>tdio --: inout std_logic
	);

dtack_int <= dtack_int0 or dtack_int1 or dtack_int2;
ack_int <= ack_int0 or ack_int1 or ack_int2;

not_sysreset <= not sysreset;
U8: startup_spartan2 port map (GSR=>not_sysreset);

irq <= irq_0 or irq_1 or irq_2;
db_in <= db;
db(15 downto 8) <= db_out(15 downto 8) when etr='0' else (others => 'Z');
db(7 downto 0) <= db_out(7 downto 0) when 
		etr='0' or etr_ivec(0)='0' or etr_ivec(1)='0' or etr_ivec(2)='0'
		else (others => 'Z');

--
trigger_in <= (trgnim or trgttl or v_trg) and (not veto or trg_bypass);
mctrg   <= trigger_out;
mcbcrst <= v_bcrst or bcrsttl; --new
mcevrst <= v_evrst or evrsttl; --new
trgttc  <= not trigger_out;
trganal <= trigger_in;
trgros  <= trigger_out;
trgled  <= trigger_out;
difbcr  <= v_bcrst or bcrsttl; --new
diftrg  <= trigger_out; 
difrst  <= v_robrst or robrsttl; --new
difevr  <= v_evrst or evrsttl; --new
jtrkadv <= v_tmadv;
jtrkrst <= v_tmrst;
jtrktm  <= ena_tm;
--
done_out <= not done_in;
intled <= rst_int(0) or rst_int(1) or rst_int(2);


add <= add_int(1 downto 0);
--nov2011 cris process (ds0_clk)
--nov2011 cris begin
	--nov2011 cris if ds0_clk'event and ds0_clk='0' then
	  --nov2011 cris add_int <= add_in(2 downto 0);
process (ds0_clk,clk)
begin

	if clk'event and clk='1' then
	  if ds0_clk='0' then
	    add_int <= add_in(2 downto 0);
	  
	  case add_in(6 downto 2) is
	    when "00000" => grp <= "00001";
	    when "00001" => grp <= "00010";
	    when "00010" => grp <= "00100";
	    when "00011" => grp <= "01000";
	    when "00100" => grp <= "10000";
	    when others  => grp <= "00000";
	  end case;
	  
	end if; --nov2011cris
	end if;
end process;

-- registro de status y control 0

db_out(2 downto 0) <= int_ena when etr='0' and grp(0)='1' and add=0 else (others => 'Z'); --0
reset <= db_in(11) when enw='1' and grp(0)='1' and add=0 else '0'; --0

process (clk, reset)
begin
	if reset='1' then
	  int_ena <= (others => '0');
	elsif clk'event and clk='1' then
	  if enw='1' and grp(0)='1' and add=0 then --0
	    int_ena <= db_in(2 downto 0);
	  else
	    int_ena <= int_ena and not rst_int;
	  end if;
	end if;
end process;

db_out(3) <= trg_bypass when etr='0' and grp(0)='1' and add=0 else 'Z'; --0
process (clk, reset)
begin
	if reset='1' then
	  trg_bypass <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and grp(0)='1' and add=0 then --0
	    trg_bypass <= db_in(3);
	  end if;
	end if;
end process;

db_out(4) <= ena_tm when etr='0' and grp(0)='1' and  add=0 else 'Z'; --0
db_out(7 downto 5) <=  not jroberr & not fltb & fltb_reg 
                       when etr='0' and grp(0)='1' and add=0 else (others => 'Z'); --0
db_out(10 downto 8) <= int_trg & int_ext when etr='0' and grp(0)='1' and add=0 else (others => 'Z'); --0
db_out(15 downto 11) <= "00000" when etr='0' and grp(0)='1' and add=0 else (others => 'Z'); --0

process (clk, reset)
begin
	if reset='1' then
	  ena_tm <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and grp(0)='1' and add=0 then --0
	    ena_tm <= db_in (4);
	  end if;
	end if;
end process;

process (clk, reset)
begin
	if reset='1' then
	  fltb_reg <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and grp(0)='1' and add=0 then --0
	    fltb_reg <= db_in (5);
	  elsif fltb='0' then
	    fltb_reg <= '1';
	  end if;
	end if;
end process;

-- Interrupt

db_out(15 downto 0) <= "00000" & int_lev_0 & int_vec_0 when etr='0' and grp(2)='1' and add=0 else (others => 'Z'); --8
db_out(15 downto 0) <= "00000" & int_lev_1 & int_vec_1 when etr='0' and grp(2)='1' and add=1 else (others => 'Z'); --9
db_out(15 downto 0) <= "00000" & int_lev_2 & int_vec_2 when etr='0' and grp(2)='1' and add=2 else (others => 'Z'); --10
db_out(7 downto 0) <= int_vec_0 when etr_ivec(0)='0' else (others => 'Z');
db_out(7 downto 0) <= int_vec_1 when etr_ivec(1)='0' else (others => 'Z');
db_out(7 downto 0) <= int_vec_2 when etr_ivec(2)='0' else (others => 'Z');

process (clk, reset)
begin
	if reset='1' then
	  int_lev_0 <= (others => '0');
	  int_lev_1 <= (others => '0');
	  int_lev_2 <= (others => '0');
	  int_vec_0 <= (others => '0');
	  int_vec_1 <= (others => '0');
	  int_vec_2 <= (others => '0');
	elsif clk'event and clk='1' then
	  if enw='1' then
	    if grp(2)='1' and add=0 then --8
	      int_lev_0 <= db_in (10 downto 8);
	      int_vec_0 <= db_in (7 downto 0);
	    elsif grp(2)='1' and add=1 then --9
	      int_lev_1 <= db_in (10 downto 8);
	      int_vec_1 <= db_in (7 downto 0);
	    elsif grp(2)='1' and add=2 then --10
	      int_lev_2 <= db_in (10 downto 8);
	      int_vec_2 <= db_in (7 downto 0);
	    end if;
	  end if;
	end if;
end process;

-- RON

ron <= ron_reg;
db_out (15 downto 0) <= "000000000" & ron_reg when etr='0' and grp(3)='1' and add=1 else (others => 'Z'); --13

process (clk, reset)
begin
	if reset='1' then
	  ron_reg <= (others => '1');	 --CRIS august 2012 at start up all ROBs on
	elsif clk'event and clk='1' then
	  if enw='1' and grp(3)='1' and add=1 then --13
	    ron_reg <= db_in (6 downto 0);
	  end if;
	end if;
end process;

-- JTAG
jtck <= jtag_reg(0);
jtms <= jtag_reg(1);
jtdi <= jtag_reg(2);
jtadd <= jtag_reg(6 downto 3);

db_out(15 downto 0) <= "00000000" & jtdo & jtag_reg when etr='0' and grp(3)='1' and add=2 else (others => 'Z'); --14

process (clk, reset)
begin
	if reset='1' then
	  jtag_reg <= (others => '0');
	elsif clk'event and clk='1' then
	  if enw='1' and grp(3)='1' and add=2 then --14
	    jtag_reg (6 downto 0) <= db_in (6 downto 0);
	  end if;
	end if;
end process;

-- ROB 25ns pulses

process (clk, reset)
begin
	if reset='1' then
	  v_bcrst   <= '0';
	  v_trg     <= '0';
	  v_robrst  <= '0';
	  v_evrst   <= '0';
	  v_pulse(0)<= '0';
	  v_pulse(1)<= '0';
	  v_tmadv   <= '0';
	  v_tmrst   <= '0';
	  set_trgin  <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and grp(3)='1' and add=3 then --15
	    v_bcrst   <= db_in (0);
	    v_trg     <= db_in (1);
	    v_robrst  <= db_in (2);
	    v_evrst   <= db_in (3);
	    v_pulse(0)<= db_in (4);
	    v_pulse(1)<= db_in (5);
	    v_tmadv   <= db_in (6);
	    v_tmrst   <= db_in (7);
	    set_trgin  <= db_in (8);
	  else
	    v_bcrst   <= '0';
	    v_trg     <= '0';
	    v_robrst  <= '0';
	    v_evrst   <= '0';
	    v_pulse(0)<= '0';
	    v_pulse(1)<= '0';
	    v_tmadv   <= '0';
	    v_tmrst   <= '0';
	    set_trgin  <= '0';
	  end if;
	end if;
end process;


---CRIS 2012 hago el veto más largo
veto_i <= veto;

process (clk, reset)
begin
	if reset='1' then
	     veto_long <= '0';
	elsif clk'event and clk='1' then
	  if veto_i='1' then
		  veto_long <= '1';
     elsif endveto='1' then
	     veto_long<='0';
	  end if;
	end if;
end process;


end arch;
	
