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

entity timvme1 is port(
-- general VME
	clk, sysreset: in std_logic;
	iack, iackin, ds0, ds1, as: in std_logic;
	write, lword, brd_sel: in std_logic;
	am0, am1, am3, am4, am5: in std_logic;
	dtack, g245, w245, on245, iackout: out std_logic;--quito qs3on
	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);
	--
	local_clk: in std_logic;
-- interrupt
	int_ttc, i2c_int: in std_logic;
	intled: out std_logic;
-- TTC
	ttc_on: in std_logic;
	enw_p, etr_p, ttc_sel, reset_p: out std_logic;
-- I2C
	i2c_rst, i2c_ce0, i2c_ce1, i2c_rd, i2c_wr: out std_logic; 
	pca_add: out std_logic_vector(1 downto 0);
	pca_db: inout std_logic_vector(7 downto 0);
-- otros
	spare, tp1, tp3: out std_logic
	);
end timvme1;

architecture arch of timvme1 is
signal etr, enw, vme_sel: std_logic;
signal add_ck: std_logic; 
signal glb_add: std_logic_vector (6 downto 0);
signal add: std_logic_vector (4 downto 0);
signal db_out: std_logic_vector (15 downto 0);
signal reset: std_logic;
signal was_off: std_logic;
signal local_clk_reg: std_logic;


--interrupt
signal int_ena: std_logic;  
signal int_lev: std_logic_vector(2 downto 0);
signal int_vec: std_logic_vector(7 downto 0);
signal etr_ivec: std_logic;
signal rst_int: std_logic;
signal dtack_int: std_logic;
signal ack_int: std_logic;
signal interrupt: std_logic;


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;

--addresses
-- A6,A5
-- 00 VME	 (00xx xxx0)
-- 01 TTC	 (01xx xxx0)
-- 10 I2C	 (1000 0xx0 => I2C_0)
--         (1000 1xx0 => I2C_1)

constant ctrl_reg_add: std_logic_vector (4 downto 0) := "00000";	--$00
constant int_reg_add:  std_logic_vector (4 downto 0) := "00001";	 --$02

signal pca_db_in:std_logic_vector(7 downto 0);
signal i2c_sel: std_logic;
signal dtack_i: std_logic;
signal brd_sel_r: std_logic;

begin

--tp1 <= etr_ivec; --etr; --J3 P125 
tp1 <=  enw; --etr; --J3 P125 
--tp2 <= vme_sel; --enw; --J4 P28 
tp3 <= or_reduce (db(15 downto 11));--J5 p87
spare <= '0';
w245 <= write;
on245 <= '0';
interrupt <= int_ttc;
intled <= not(rst_int);	 --a 0 enciende el led


-- TTC
etr_p <= etr;
enw_p <= enw;
reset_p <= reset;

--ttc_sel <= '1' when brd_sel_r='0' and glb_add(6 downto 5)="01" else '0';
ttc_sel <= '1' when brd_sel_r='0' and glb_add(6 downto 5)="01" and add_ck='0' else '0';

dtack <= dtack_i;

-- I2C
i2c_ce0 <= '0' when brd_sel_r='0' and glb_add(6 downto 2)="10000" else '1';	 --tim_vme $80
i2c_ce1 <= '0' when brd_sel_r='0' and glb_add(6 downto 2)="10001" else '1'; --timttc $88

i2c_sel <= '1' when brd_sel_r='0' and glb_add(6 downto 2)="10000" else '0';

i2c_rst <= '0' when reset='1' else
             not db(6) when vme_sel='1' and add="00000" and enw='1' else '1';
i2c_rd <= etr when i2c_sel='1' else '1';
i2c_wr <= not(enw) when i2c_sel='1' else '1';

--pca_add <= add_in(1 downto 0);
pca_add <= glb_add(1 downto 0);

pca_db <= db (7 downto 0) when enw='1' and i2c_sel='1' else (others=>'Z');
pca_db_in <= pca_db when etr='0' and i2c_sel='1' else (others=>'Z');

	    
-- VME
vme_sel <= '1' when brd_sel_r='0' and glb_add(6 downto 5)="00" else '0';

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_r, lword=>lword, --: in std_logic;
	am0=>am0, am1=>am1, am3=>am3, am4=>am4, am5=>am5, --: in std_logic;
	etr=>etr, enw=>enw, dtack=>dtack_i, g245=>g245 --: out std_logic 
	);

U2: vmeint port map (
	interrupt=>interrupt, int_ena=>int_ena, --: in std_logic;  
	add=>add_in(2 downto 0), int_lev=>int_lev, --: 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, rst_int=>rst_int, iackout=>iackout, --: out std_logic;
	dtack_int=>dtack_int, ack_int=>ack_int, --: out std_logic;
	irq=>irq --: out std_logic_vector(7 downto 1)); 
	);

-- addresses
add_ck <= ds0 and ds1;-- and as; arreglo LINCO
--brd_sel_r <= brd_sel;
--process (add_ck, reset)
--begin
	--if reset='1' then
	  --glb_add <= (others => '0');
	--elsif add_ck'event and add_ck='0' then
	  --glb_add <= add_in;
--	end if;
--end process;

--Pongo un latch
process (add_ck, add_in,brd_sel)
begin
	if add_ck='1' then
	  	glb_add <= add_in;
		brd_sel_r <= brd_sel;
	else
	 	glb_add <= glb_add;
		brd_sel_r <= brd_sel_r;
	end if;
end process;

add <= glb_add(4 downto 0);


process (vme_sel, etr, etr_ivec, add, int_ena, rst_int, int_vec, int_lev,
         i2c_int, int_ttc, was_off, ttc_on, local_clk_reg,local_clk)
begin
	if vme_sel='1' then
	  if etr='0' then
	        case add is
	      	when ctrl_reg_add =>
	        	db_out <= (0 => int_ena, 
		   	         1 => rst_int,
				    2 => ttc_on,
				    3 => was_off,
				    4 => int_ttc,
				    5 => not i2c_int, 
				    7 => local_clk,
				    8 => local_clk_reg,
				    others =>'0');
 
	      	when int_reg_add =>
	        		db_out <= "00000" & int_lev & int_vec; -- 2..0 + 7..0

		 when others =>
		        db_out <= (others => '0');
	     	  end case;
	  else
	    db_out <= (others => 'Z');
	  end if;
	  elsif etr_ivec='0' then -- lo pongo para corregir que en interrupciones vmesel no esta a 1
	    db_out <= "00000000" & int_vec;
	  else
	  db_out <= (others => 'Z');
	end if;	    
end process;

-- lectura de registros
db(15 downto 8) <= db_out(15 downto 8) when vme_sel='1' and etr='0' 
          else (others => 'Z');
db(7 downto 0)  <= db_out(7 downto 0)  when (vme_sel='1' and etr='0') or etr_ivec='0' 
		else pca_db_in when i2c_sel='1' and etr='0' else (others => 'Z');

-- escritura de registros --
-- control
reset <= '1' when sysreset='0' else 
		db(15) when vme_sel='1' and add="00000" and enw='1' 
		else '0'; 

process (clk, reset)
begin
	if reset='1' then
	  int_ena <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and vme_sel='1' and add="00000" then
	    int_ena <= db(0);
	  else
	    int_ena <= int_ena and not rst_int;
	  end if;
	end if;
end process;
--local_clk
process (clk, reset)
begin
	if reset='1' then
	  local_clk_reg <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and vme_sel='1' and add="00000" then
	    local_clk_reg <= db(8);
	  elsif local_clk='1' then
	    local_clk_reg <= '1';
	  end if;
	end if;
end process;

process (clk, reset)
begin
	if reset='1' then
	  was_off <= '0';
	elsif clk'event and clk='1' then
	  if enw='1' and vme_sel='1' and add="00000" then
	    was_off <= db(3);
	  elsif ttc_on='0' then
	  	was_off<='1';
	  end if;
	end if;
end process;

-- Interrupt
process (clk, reset)
begin
	if reset='1' then
	  int_lev <= "001";
	  int_vec <= (others => '0');
	elsif clk'event and clk='1' then
	  if enw='1' and vme_sel='1' and add="00001" then
	    int_lev <= db (10 downto 8);
	    int_vec <= db (7 downto 0);
	  end if;
	end if;
end process;

end arch;

