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

--Cambios de abril, registro las direcciones con el flanco de subida de ttc_sel

entity timttc is port(
-- general VME
	clk, etr, enw, ttc_sel_p, reset_p: in std_logic;
	add_p: in std_logic_vector (4 downto 0);
	db: inout std_logic_vector (15 downto 0);
	interrupt: out std_logic;
-- TTC
	brcst_str_1, brcst_str_2, sinerr_str, dberr_str, dout_str, ttc_ready: in std_logic;
	bcnt_str, evcntl_str, evcnth_str: in std_logic;
	subaddr: in std_logic_vector (7 downto 0);
	dout: in std_logic_vector (7 downto 0);
	dq: in std_logic_vector (3 downto 0);
	brcst:in std_logic_vector (7 downto 2);
	bcnt:in std_logic_vector (11 downto 0);
	reset_b: out std_logic;
--QPLL
	qpll_error, qpll_locked: in std_logic;
	qpll_reset: out std_logic;
--TIMBUS
	cmd: out std_logic_vector (3 downto 0);
	cmy:out std_logic;
--I2C
	i2c_rst, i2c_rd, i2c_wr: out std_logic;
	i2c_int: in std_logic;
-- otros
	int_led, ttc_on, on_245: out std_logic;
	spare, tp1, tp2, tp3: out std_logic
	);
end timttc ;

architecture arch of timttc is

-- general
signal db_out: std_logic_vector (15 downto 0);
signal error: std_logic;
-- addresses
constant ttc_add:        std_logic_vector(4 downto 0) := "00000";  --$40
constant iac_command_add: std_logic_vector(4 downto 0) := "00001";   --$42
constant brcst1_reg_add:  std_logic_vector(4 downto 0) := "00010";   --$44
constant brcst2_reg_add:  std_logic_vector(4 downto 0) := "10000";   --$60
constant bcnt_reg_add:   std_logic_vector(4 downto 0) := "00011";    --$46
constant evcntl_reg_add: std_logic_vector(4 downto 0) := "00100";    --$48
constant evcnth_reg_add: std_logic_vector(4 downto 0) := "00101";    --$4A
constant qpll_add:       std_logic_vector(4 downto 0) := "00110";  --$4C

--DOUT BUS
constant add_DQ_4E: std_logic_vector(4 downto 0) := "00111"; --$4E
constant add_DQ_50: std_logic_vector(4 downto 0) := "01000"; --$50
constant add_DQ_52: std_logic_vector(4 downto 0) := "01001"; --$52
constant add_DQ_54: std_logic_vector(4 downto 0) := "01010"; --$54
constant add_DQ_56: std_logic_vector(4 downto 0) := "01011"; --$56
constant add_DQ_58: std_logic_vector(4 downto 0) := "01100"; --$58


--QPLL
signal seu_counter: std_logic_vector (7 downto 0);
signal seu_reset: std_logic;
-- TTC
signal brcst1_reg: std_logic_vector (7 downto 2);
signal brcst2_reg: std_logic_vector (7 downto 2);
signal bcnt_reg: std_logic_vector (11 downto 0);
signal evcntl_reg: std_logic_vector (11 downto 0);
signal evcnth_reg: std_logic_vector (11 downto 0);
signal qpll_reset_aux:std_logic;
signal rst_counter: std_logic_vector (10 downto 0);

signal reg_DQ_4E: std_logic_vector(11 downto 0);
signal reg_DQ_50: std_logic_vector(11 downto 0);
signal reg_DQ_52: std_logic_vector(11 downto 0);
signal reg_DQ_54: std_logic_vector(11 downto 0);
signal reg_DQ_56: std_logic_vector(7 downto 0);
signal reg_DQ_58: std_logic_vector(7 downto 0);

signal sinerr_str_reg, dberr_str_reg: std_logic;
signal qpll_unlocked_reg, ttc_notready_reg: std_logic;

signal iac_subadd, iac_data: std_logic_vector(7 downto 0);
signal add: std_logic_vector (4 downto 0);
signal ttc_sel,reset: std_logic;
 
begin
ttc_on <= '1';
on_245 <= '0';
error <= sinerr_str or dberr_str or qpll_error or not qpll_locked or not ttc_ready;
int_led <= not error;
interrupt <= error;
tp1 <= etr; --P7 
tp2 <= enw; --P151 
tp3 <= brcst_str_2;
--spare <= '0' when subaddr="00000000" else '1';
spare <= '0';
cmy <= '1'; --seņal que va al led del front-pannel y no se para que sirve


--	brcst_str_1, brcst_str_2, sinerr_str, dberr_str, dout_str, ttc_ready: in std_logic;
--	bcnt_str, evcntl_str, evcnth_str

-- broadcasts
--cmd(0) <= '1' when brcst="001010" else '0'; -- poner algo
--cmd(1) <= '1' when brcst="001011" else '0'; -- poner algo
--cmd(2) <= '1' when brcst="001100" else '0'; -- poner algo
--cmd(3) <= '1' when brcst="001101" else '0'; -- poner algo
--cmd(4) <= '1' when brcst="001111" else '0'; -- poner algo

--Si registro los cmd, salen con mala fase al TIMBUS
cmd(0) <= '1' when brcst_str_1='1' and brcst(2)='1' else '0'; -- BRD(2)
cmd(1) <= '1' when brcst_str_1='1' and brcst(3)='1' else '0'; -- BRD(3) 
cmd(2) <= '1' when brcst_str_1='1' and brcst(4)='1' else '0'; -- BRD(4) 
cmd(3) <= '1' when brcst_str_1='1' and brcst(5)='1' else '0'; -- BRD(5) 

--process (clk, reset)
--begin
  --   if reset='1' then
    --   cmd <= (others =>'0');
   --  elsif clk'event and clk='0' then
     --  if brcst_str_1='1' then
     --    cmd <= brcst (5 downto 2);
     --  else
     --    cmd <= (others =>'0');
   --    end if;
 --    end if;       
--end process;

--registro reset	(habia un glitch en la seņal en el cable TIMVME a TIMTTC)
process (clk)
begin
     if clk'event and clk='0' then
      reset <= reset_p;
    end if;       
end process;


ttc_sel <= ttc_sel_p;
--add <= add_p;

--registro las direcciones
process(ttc_sel,add_p)
begin
	if ttc_sel='0' then
		add <= add_p;
	else
		add <= add;
	end if;
end process;


 
-- lectura de registros
db <= db_out when ttc_sel='1' and etr='0' else (others => 'Z');

db_out <= "000000" & ttc_notready_reg & '0' & not(i2c_int) & dberr_str_reg & sinerr_str_reg &  dberr_str
				& sinerr_str & qpll_unlocked_reg & qpll_locked &  ttc_ready when add=ttc_add	else (others => 'Z');
db_out <= iac_subadd & iac_data when add=iac_command_add else (others => 'Z'); 
db_out <= "00000000" & brcst1_reg & "00" when add=brcst1_reg_add else (others => 'Z'); 
db_out <= "00000000" & brcst2_reg & "00"  when add=brcst2_reg_add else (others => 'Z'); 
db_out <= "0000" & bcnt_reg  when add=bcnt_reg_add else (others => 'Z'); 
db_out <= "0000" & evcntl_reg  when add=evcntl_reg_add else (others => 'Z'); 
db_out <= "0000" & evcnth_reg  when add=evcnth_reg_add else (others => 'Z'); 
db_out <= "00000" & seu_counter & qpll_error & qpll_unlocked_reg & qpll_locked  when add=qpll_add else (others => 'Z'); 
db_out <= "0000" & reg_DQ_4E  when add=add_DQ_4E else (others => 'Z'); 
db_out <= "0000" & reg_DQ_50  when add=add_DQ_50 else (others => 'Z'); 
db_out <= "0000" & reg_DQ_52  when add=add_DQ_52 else (others => 'Z'); 
db_out <= "0000" & reg_DQ_54  when add=add_DQ_54 else (others => 'Z'); 
db_out <= "0000" & "1001" & reg_DQ_56  when add=add_DQ_56 else (others => 'Z'); 
db_out <= "0000" & "1010" & reg_DQ_58  when add=add_DQ_58 else (others => 'Z'); 


-- escritura de registros --

-- reset del TTCrq  era demasiado corto 25ns, debe ser al menos 50 us
--reset_b <= not db(15) when ttc_sel='1' and enw='1' and add=ttc_add else '1';
    --'0' when reset='1' else	 '1'; no quiero que esto resetee

process (clk, reset)
begin
	if reset='1' then
	    reset_b <= '1';
	    rst_counter <= (others=>'1');
	elsif clk'event and clk='1' then
		if db(15)='1' and ttc_sel='1' and enw='1' and add=ttc_add then
		    	reset_b <= '0';
	    		rst_counter <= (others=>'0');
		elsif rst_counter/="11111111111" then
			rst_counter <= rst_counter+1;
			reset_b<='0';
		else reset_b <= '1';
		end if;
	end if;
end process;

process (clk, reset)
begin
	if reset='1' then
	  sinerr_str_reg <= '0';
	  dberr_str_reg <= '0';
	elsif clk'event and clk='0' then
	  if enw='1' and ttc_sel='1' and add=ttc_add then
		  sinerr_str_reg <= db(5);
		  dberr_str_reg <= db(6);
	   else
			if sinerr_str='1' then
			   sinerr_str_reg <= '1';
			end if;
			if dberr_str='1' then
	  			dberr_str_reg <= '1';
			end if;
	  end if;
	end if;
end process;

process (clk, reset)
begin
	if reset='1' then
	  qpll_unlocked_reg <= '0';
	elsif clk'event and clk='0' then
	  if enw='1' and ttc_sel='1' and add=ttc_add then
	  	  qpll_unlocked_reg	<= db(2);
 	  elsif qpll_locked='0' then
			   qpll_unlocked_reg <= '1';
	  end if;			
	end if;
end process;
 
process (clk, reset)
begin
	if reset='1' then
	   ttc_notready_reg<= '0';
	elsif clk'event and clk='0' then
	  if enw='1' and ttc_sel='1' and add=ttc_add then
	  	   ttc_notready_reg	<= db(9);
 	  elsif ttc_ready='0' then
			    ttc_notready_reg <= '1';
	  end if;			
	end if;
end process;

-- iac command external register
process (clk, reset)
begin
	if reset='1' then
	  iac_subadd <= (others => '0');
	  iac_data <= (others => '0');
	elsif clk'event and clk='0' then
	  if enw='1' and ttc_sel='1' and add=iac_command_add then
	  	iac_subadd <= db(15 downto 8);
	  	iac_data <= db(7 downto 0);
	  elsif dout_str='1' then
	  	iac_subadd <= subaddr;
	  	iac_data <= dout;
	  end if;
	end if;
end process;

-- brcst register
process (clk, reset)
begin
	if reset='1' then
	  brcst1_reg <= (others => '0');
	elsif clk'event and clk='0' then	
	  if brcst_str_1='1' then
	    brcst1_reg <= brcst;
	  end if;
	end if;
end process;

process (clk, reset)
begin
	if reset='1' then
	  brcst2_reg <= (others => '0');
	elsif clk'event and clk='0' then  
	  if brcst_str_2='1' then
	    brcst2_reg <= brcst;
	  end if;
	end if;
end process;

-- bcnt register
process (clk, reset)
begin
	if reset='1' then
	  bcnt_reg <= (others => '0');
	elsif clk'event and clk='0' then 
	  if bcnt_str='1' then
	    bcnt_reg <= bcnt;
	  end if;
	end if;
end process;
-- evcntl register
process (clk, reset)
begin
	if reset='1' then
	  evcntl_reg <= (others => '1');
	elsif clk'event and clk='0' then 
	  if evcntl_str='1' then
	    evcntl_reg <= bcnt;
	  end if;
	end if;
end process;
-- evcnth register
process (clk, reset)
begin
	if reset='1' then
	  evcnth_reg <= (others => '1');
	elsif clk'event and clk='0' then	   
	  if evcnth_str='1' then
	    evcnth_reg <= bcnt;
	  end if;
	end if;
end process;

-- DQ
process (clk, reset)
begin
	if reset='1' then
	  reg_DQ_4E <= (others => '0');
	  reg_DQ_50 <= (others => '0');
	  reg_DQ_52 <= (others => '0');
	  reg_DQ_54 <= (others => '0');
	  reg_DQ_56 <= (others => '0');
	  reg_DQ_58 <= (others => '0');
	elsif clk'event and clk='0' then
	  if dout_str='1' then
          
          case dq is

          when "0001" | "0101" => 
		 	 reg_DQ_4E <= dq & dout;

          when "0010" | "0110" =>	 
		 	 reg_DQ_50 <= dq & dout;

          when "0011" | "0111" =>	 
		 	 reg_DQ_52 <= dq & dout;

          when "0100" | "1000" =>	 
		 	 reg_DQ_54 <= dq & dout;

          when "1001" =>	 
		 	 reg_DQ_56 <= dout;

          when "1010" =>	 
		 	 reg_DQ_58 <= dout;

          when others =>
		 	 null;
                               
          end case;
	  end if;
	end if;
end process;	  	
		

-- QPLL
-- qpll seu counter
seu_reset <= '1' when reset='1' else
             db(14) when ttc_sel='1' and enw='1' and add=qpll_add else '0';

process (qpll_error, seu_reset)
begin
	if seu_reset='1' then
	  seu_counter <= (others => '0');
	elsif qpll_error'event and qpll_error='1' then
	  seu_counter <= seu_counter +1;
	end if;
end process;
-- qpll reset
qpll_reset_aux <= db(15) when ttc_sel='1' and enw='1' and add=qpll_add else '0';

qpll_reset <= not(qpll_reset_aux);
--I2C
i2c_rst <= '0' when reset='1' else
           not db(14) when ttc_sel='1' and enw='1' and add=ttc_add  else '1'; 
i2c_rd <= etr;	  --OK, el chip enable lo genera TIM_VME 
i2c_wr <= not enw;

end arch;