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

entity registros_vme is port(
-- general
	clk, sysreset, etr, enw, cs: in std_logic;
	sda, scl: inout std_logic;
	I2C_Add_in: out  STD_LOGIC_VECTOR (1 downto 0);
	Reset_J2: out std_logic;
	rst_brdsel: out std_logic_vector(11 downto 0);
	local_reset_p: out std_logic;
	add: in std_logic_vector(3 downto 0);
	Spare_J2_int, Read_J2_int: out std_logic;  --25junio2013
--	db_in: in std_logic_vector(15 downto 0);
--	db_out: out std_logic_vector(15 downto 0);
	db_in: in std_logic_vector(7 downto 0);
	db_out: out std_logic_vector(7 downto 0);
--ofcu
   SignalDetect_1: in std_logic_vector(2 downto 0);
   SignalDetect_2: in std_logic_vector(2 downto 0);
   SignalDetect_3: in std_logic_vector(2 downto 0);
   SignalDetect_4: in std_logic_vector(2 downto 0);
   SignalDetect_5: in std_logic_vector(2 downto 0);
   SignalDetect_6: in std_logic_vector(2 downto 0);
   SignalDetect_7: in std_logic_vector(2 downto 0);
   SignalDetect_8: in std_logic_vector(2 downto 0);
   SignalDetect_9: in std_logic_vector(2 downto 0);
   SignalDetect_10: in std_logic_vector(2 downto 0);
   SignalDetect_11: in std_logic_vector(2 downto 0);
   SignalDetect_12: in std_logic_vector(2 downto 0);
	force_led: out std_logic;--4july2013
-- interrupciones
	int_rst, etr_ivec: in std_logic;
	interrupt: out std_logic;  
	int_lev_p: out std_logic_vector(2 downto 0)
 	);
end registros_vme ;

architecture arch of registros_vme is

-- direcciones
constant reg1_vme: std_logic_vector (3 downto 0):=   "0000"; -- $00 test
constant int_add_1: std_logic_vector (3 downto 0):=  "0001"; -- $02 interruptions1
constant int_add_2: std_logic_vector (3 downto 0):=  "0010"; -- $04 interruptions2
constant scl_reg_1: std_logic_vector (3 downto 0):=  "0011"; -- $06 scl_1
constant sda_reg_1: std_logic_vector (3 downto 0):=  "0100"; -- $08 sda_1
constant I2C_select: std_logic_vector (3 downto 0):= "0101"; -- $0A I2C_select

constant regSignalDetect_1: std_logic_vector (3 downto 0):=  "0110"; -- $0C signal detect 1-2
constant regSignalDetect_3: std_logic_vector (3 downto 0):=  "0111"; -- $0E signal detect 3-4
constant regSignalDetect_5: std_logic_vector (3 downto 0):=  "1000"; -- $10 signal detect 5-6
constant regSignalDetect_7: std_logic_vector (3 downto 0):=  "1001"; -- $12 signal detect 7-8
constant regSignalDetect_9: std_logic_vector (3 downto 0):=  "1010"; -- $14 signal detect 9-10
constant regSignalDetect_11: std_logic_vector (3 downto 0):=  "1011"; -- $16 signal detect 11-12

constant regResetOFCU: std_logic_vector (3 downto 0):=  "1100"; -- $18 resetOFCU

-- señales
signal int_lev: std_logic_vector(2 downto 0);
signal int_vect: std_logic_vector(7 downto 0);
signal int_ena_test: std_logic;  
--signal sda_r,scl_r: std_logic_vector(3 downto 0);
signal sda_r,scl_r, sda_w,scl_w: std_logic; --30oct2013
signal reg1_data: std_logic_vector(2 downto 0); --4july2013
signal reg2_data: std_logic_vector(5 downto 0);

signal db_mux: std_logic_vector (7 downto 0);
signal ena_evres: std_logic;
signal ros_w0, ros_waiting_reg, mem_d0, mem_done_reg: std_logic;
signal ena_rst_prgm, ena_evres_prgm: std_logic;

signal local_reset,resetj2: std_logic;
signal reset_1,reset_2: std_logic;

signal SD_data_1,SD_data_3,SD_data_5: std_logic_vector (7 downto 0);
signal SD_data_7,SD_data_9,SD_data_11: std_logic_vector (7 downto 0);
signal I2C_Add: std_logic_vector(1 downto 0);

signal OFCU_to_rst,OFCU_to_rst_int: std_logic_vector(7 downto 0);

signal borra: std_logic;
--signal cont: std_logic_vector(1 downto 0);
signal prerstJ2, rst_all: std_logic;
signal rst_brdsel_i: std_logic_vector(11 downto 0);	
signal rstcount,rstmaqest: std_logic;
signal aux1, aux2, aux3, aux4, aux5: std_logic;

signal Spare_J2_int2, Read_J2_int2: std_logic; --25junio2013
	
signal force_led_in: std_logic; --4july2013	
	
	
type state_type_1 is (
	nada, 
	rst0, rst1, rst2, rst3, rst4,
	rst5, rst6, rst7, rst8, rst9,
	rst10, rst11
);

signal state: state_type_1;
	
	
begin

force_led <= force_led_in; --4july2013

int_lev_p <= int_lev;

local_reset_p <= local_reset;

I2C_Add_in(0) <= I2C_Add(0);
I2C_Add_in(1) <= I2C_Add(1);

Spare_J2_int <= Spare_J2_int2; --25 junio2013
Read_J2_int <= Read_J2_int2; --25 junio2013

--sda<= sda_r;
--scl<= scl_r;

sda <= 'Z' when sda_w='1' else '0'; --infer open-drain --30oct2013
scl <= 'Z' when scl_w='1' else '0'; --infer open-drain --30oct2013

-----------------------------------------------
-- cs y etr están puestos en el 3-estados
db_out <=   int_vect when etr_ivec='0' else  -- interrupt vector
         db_mux;

process (add, reg1_data, reg2_data, scl_r, sda_r, I2C_Add(0),I2C_Add(1),
         SD_data_1, SD_data_3, SD_data_5,
         SD_data_7, SD_data_9, SD_data_11,
         int_vect, int_lev, int_rst, int_ena_test,Spare_J2_int2, Read_J2_int2,force_led_in)
begin

     case add is

     when reg1_vme =>
	     db_mux <= "00" & Spare_J2_int2 & Read_J2_int2 & force_led_in & reg1_data;
 
     when int_add_1 =>
	     db_mux <=  reg2_data & int_rst & int_ena_test;

	  when int_add_2 =>
        db_mux <= int_vect;

     when scl_reg_1 =>
        db_mux <= "000000" & scl_r & '0';--30oct2013

     when sda_reg_1 =>
        db_mux <= "000000" & sda_r & '0';--30oct2013

     when  I2C_select =>
        db_mux <= "000" & I2C_Add(1) & "000" & I2C_Add(0);

     when regSignalDetect_1 =>
        db_mux <= SD_data_1;

     when regSignalDetect_3 =>
        db_mux <= SD_data_3;

     when regSignalDetect_5 =>
        db_mux <= SD_data_5;

     when regSignalDetect_7 =>
        db_mux <= SD_data_7;

     when regSignalDetect_9 =>
        db_mux <= SD_data_9;

     when regSignalDetect_11 =>
        db_mux <= SD_data_11;

	  when others => 
        db_mux <= (others => '0');

     end case;
end process;


local_reset <= '1' when sysreset='1'
                   or (db_in (7)='1' and add=reg1_vme and cs='1' and enw='1')  
                   else '0';

--Spares reg 1   25junio2013
process (clk, local_reset)
begin
if local_reset='1' then 	
    Spare_J2_int2 <='0';
    Read_J2_int2  <='0';
elsif clk'event and clk='1' then
	  if add=reg1_vme and cs='1' and enw='1' then 
		Spare_J2_int2 <=db_in(5);
		Read_J2_int2  <=db_in(4);
	  end if;
end if;
end process;
		
-- interrupciones
interrupt <=  '1' when (int_ena_test='1') else '0';	  -- alguna esta a 1
--'1' when (or_reduce(spaf)???='1' and int_ena_test='1') else '0';	  -- alguna esta a 1

int_lev <= "111"; --Interrupt level is always 7

--Interruptions reg 1
process (clk, local_reset)
begin
	if local_reset='1' then 	
     int_ena_test <= '0';  
	  reg2_data <= (others => '0');
  elsif clk'event and clk='1' then
	  if int_rst='1' then
	    int_ena_test <= '0';  
	  elsif add=int_add_1 and cs='1' and enw='1' then  
	    int_ena_test  <= db_in (0);  
  	    reg2_data <= db_in(7 downto 2);
	  end if;
	end if;
end process;

--Interruptions reg 2
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  int_vect <= (others => '0');
	elsif clk'event and clk='1' then
	  if add=int_add_2 and cs='1' and enw='1' then  
	    int_vect <= db_in;
	  end if;
	end if;
end process;

--Reg_1
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  reg1_data <= (others => '0');
	  force_led_in <= '0'; --4july2013
	elsif clk'event and clk='1' then
	  if add=reg1_vme and cs='1' and enw='1' then 	  
  	    reg1_data <= db_in(2 downto 0);
		 force_led_in <= db_in(3); --4july2013
	  end if;
	end if;
end process;



--***************************++++
--***************************++++
--*********** i2c  ****************++++
--***************************++++

--SDA_SCL_read --30oct2013
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  scl_r <= '1';
	  sda_r <= '1';
	elsif clk'event and clk='1' then
  	    scl_r <= scl;
  	    sda_r <= sda;
	end if;
end process;

--SDA_reg_write
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  scl_w <= '1'; --30oct2013
	elsif clk'event and clk='1' then
	  if add=scl_reg_1 and cs='1' and enw='1' then 	  
  	    scl_w <= db_in (0); --30oct2013
	  end if;
	end if;
end process;

--SCL reg_write
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  sda_w <= '1'; --30oct2013
	elsif clk'event and clk='1' then				   
	  if add=sda_reg_1 and cs='1' and enw='1' then 
  	    sda_w <= db_in (0); --30oct2013
	  end if;
	end if;
end process;


--I2C SELECT
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  I2C_Add <= (others => '0');
	elsif clk'event and clk='1' then
	  if add=I2C_select and cs='1' and enw='1' then 	  
  	    I2C_Add(0) <= db_in (0);
  	    I2C_Add(1) <= db_in (4);		 
	  end if;
	end if;
end process;


--******************************************************************************+
--******************************************************************************+
--************    SIGNAL DETECT                             ***************+
--******************************************************************************+
--******************************************************************************+
--******************************************************************************+

--regSignalDetect 1
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  SD_data_1 <= (others=>'0');
	elsif clk'event and clk='1' then				   
	  if add=regSignalDetect_1 and cs='1' and enw='1' then 
  	    SD_data_1 <= db_in;
	  else
  	    SD_data_1 <= "00" & SignalDetect_2 & SignalDetect_1;
	  end if;
	end if;
end process;

--regSignalDetect 3
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  SD_data_3 <= (others=>'0');
	elsif clk'event and clk='1' then				   
	  if add=regSignalDetect_3 and cs='1' and enw='1' then 
  	    SD_data_3 <= db_in;
	  else
  	    SD_data_3 <= "00" & SignalDetect_4 & SignalDetect_3;
	  end if;
	end if;
end process;

--regSignalDetect 5
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  SD_data_5 <= (others=>'0');
	elsif clk'event and clk='1' then				   
	  if add=regSignalDetect_5 and cs='1' and enw='1' then 
  	    SD_data_5 <= db_in;
	  else
  	    SD_data_5 <= "00" & SignalDetect_6 & SignalDetect_5;
	  end if;
	end if;
end process;
	

--regSignalDetect 7
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  SD_data_7 <= (others=>'0');
	elsif clk'event and clk='1' then				   
	  if add=regSignalDetect_7 and cs='1' and enw='1' then 
  	    SD_data_7 <= db_in;
	  else
  	    SD_data_7 <= "00" & SignalDetect_8 & SignalDetect_7;
	  end if;
	end if;
end process;
		

--regSignalDetect 9
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  SD_data_9 <= (others=>'0');
	elsif clk'event and clk='1' then				   
	  if add=regSignalDetect_9 and cs='1' and enw='1' then 
  	    SD_data_9 <= db_in;
	  else
  	    SD_data_9 <= "00" & SignalDetect_10 & SignalDetect_9;
	  end if;
	end if;
end process;		


--regSignalDetect 11
process (clk, local_reset)
begin
	if local_reset='1' then 	
	  SD_data_11 <= (others=>'0');
	elsif clk'event and clk='1' then				   
	  if add=regSignalDetect_11 and cs='1' and enw='1' then 
  	    SD_data_11 <= db_in;
	  else
  	    SD_data_11 <= "00" & SignalDetect_12 & SignalDetect_11;
	  end if;
	end if;
end process;		

	

--resetOFCU registr $18
process (clk, local_reset,borra)
begin
	if local_reset='1' or borra='1' then 	
	  OFCU_to_rst_int <= (others=>'0');
	  rstcount <= '0';
	elsif clk'event and clk='1' then				   
	  if add=regResetOFCU and cs='1' and enw='1' then 
  	     OFCU_to_rst_int <= db_in;
	     rstcount <= '1';
	   else 
	     rstcount <= '0';
	  end if;
 	end if;
end process;		

process (clk, local_reset,borra)
begin
	if local_reset='1' or borra='1' then 	
	  OFCU_to_rst <= (others=>'0');
	elsif clk'event and clk='1' then				   
  	  OFCU_to_rst <= OFCU_to_rst_int;
 	end if;
end process;		

--Hago que el reset dure 3-4 ciclos, la señal borra me resetea el registro $18
process (clk, local_reset)
begin
	if local_reset='1' then 	
	    aux1 <= '0';
		 aux2 <= '0';
		 aux3 <= '0';
		 aux4 <= '0';
		 aux5 <= '0';
	elsif clk'event and clk='1' then				   
	    aux1 <= rstcount or rstmaqest;
		 aux2 <= aux1;
		 aux3 <= aux2;
		 aux4 <= aux3;
		 aux5 <= aux4;
	end if;
end process;		

borra <= aux5;

Reset_J2 <= prerstJ2 when state=nada else '1';

prerstJ2 <= '1' when OFCU_to_rst_int="00000001" or
							OFCU_to_rst_int="00000010" or 
							OFCU_to_rst_int="00000011" or 
							OFCU_to_rst_int="00000100" or 
							OFCU_to_rst_int="00000101" or
							OFCU_to_rst_int="00000110" or 
 							OFCU_to_rst_int="00000111" or 
 							OFCU_to_rst_int="00001000" or 
 							OFCU_to_rst_int="00001001" or 
 							OFCU_to_rst_int="00001010" or 
 							OFCU_to_rst_int="00001011" or 
 							OFCU_to_rst_int="00001100" else '0';

--ahora hay que activar el brdsel que corresponda
rst_brdsel_i(0) <= '1' when OFCU_to_rst="00000001" or state=rst0 else '0';
rst_brdsel_i(1) <= '1' when OFCU_to_rst="00000010" or state=rst1 else '0';
rst_brdsel_i(2) <= '1' when OFCU_to_rst="00000011" or state=rst2 else '0';
rst_brdsel_i(3) <= '1' when OFCU_to_rst="00000100" or state=rst3 else '0';
rst_brdsel_i(4) <= '1' when OFCU_to_rst="00000101" or state=rst4 else '0';
rst_brdsel_i(5) <= '1' when OFCU_to_rst="00000110" or state=rst5 else '0';
rst_brdsel_i(6) <= '1' when OFCU_to_rst="00000111" or state=rst6 else '0';
rst_brdsel_i(7) <= '1' when OFCU_to_rst="00001000" or state=rst7 else '0';
rst_brdsel_i(8) <= '1' when OFCU_to_rst="00001001" or state=rst8 else '0';
rst_brdsel_i(9) <= '1' when OFCU_to_rst="00001010" or state=rst9 else '0';
rst_brdsel_i(10) <= '1' when OFCU_to_rst="00001011" or state=rst10 else '0';
rst_brdsel_i(11) <= '1' when OFCU_to_rst="00001100" or state=rst11 else '0';

--lo registro, parece que tiene un glitch
process (clk, local_reset, borra)
begin
	if local_reset='1' or borra='1' then 	
	     rst_brdsel <= (others=>'0');
	elsif clk'event and clk='1' then				   
	      rst_brdsel <= rst_brdsel_i;
			--rst_brdsel <= (others=>'0');
	end if;
end process;		

--reseteo todas las tarjetas cuando escribo en el bit 6 del registro $00
rst_all <= '1' when (db_in (6)='1' and add=reg1_vme and cs='1' and enw='1') and state=nada else '0';

-- maquina estados
process (clk, local_reset, rst_all)
begin
	if local_reset='1' then
	     state <= nada; 	  
		  rstmaqest<='0';

	elsif clk'event and clk='1' then
	
  	case state is

	  when nada =>
 		  if (rst_all='1') then
 	         state <= rst0; 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst0 =>
	      if borra='1' then   
				state <= rst1; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst1 =>
	      if borra='1' then   
				state <= rst2; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst2 =>
	      if borra='1' then   
				state <= rst3; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst3 =>
	      if borra='1' then   
				state <= rst4; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst4 =>
	      if borra='1' then   
				state <= rst5; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst5 =>
	      if borra='1' then   
				state <= rst6; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst6 =>
	      if borra='1' then   
				state <= rst7; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst7 =>
	      if borra='1' then   
				state <= rst8; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst8 =>
	      if borra='1' then   
				state <= rst9; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst9 =>
	      if borra='1' then   
				state <= rst10; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst10 =>
	      if borra='1' then   
				state <= rst11; 	 
				rstmaqest<='1';
			else
				rstmaqest<='0';
			end if;

	  when rst11 =>
	      if borra='1' then   
				state <= nada; 	 
			end if;
	
	when others => 
		    state <= nada;
	end case;
	end if;
end process;


	
--resetj2 <= '1' when (db_in (6)='1' and add=reg1_vme and cs='1' and enw='1')  else '0';
				  
--august 11 2012 quito que el local_reset de vme_patch haga un OFCU reset					  
--ojo: OFCU solo responde al reset si su boardsel esta activa. 
--no quiero activar todas a la vez pues se habilitan todos los buffers,

--process(clk)
--begin
--	if clk'event and clk='1' then
--		reset_1 <= resetj2;
--		reset_2 <= reset_1;
--	end if;
--end process;

--Reset_J2 <= reset_1 or reset_2; --dura 50 ns	 
end arch;
	
