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 rm_registros is
     port (
     clk, reset: in std_logic;
     txena_out_lfsr: out std_logic; 
     mem_done: in std_logic; 
     mem_is_full: out std_logic;

-- vme A16
     enw, cs: in std_logic;
     add: in std_logic_vector(5 downto 0);
     db_in: in std_logic_vector (15 downto 0);
     db_out: out std_logic_vector (15 downto 0);

     ena_word_count_p, ena_event_count_p:out std_logic;
	  ena_gol_test_p, ena_ceros_mem_p,ena_cycles_p, ena_random_p: out std_logic;
	  reset_pointer,inc_pointer: in std_logic;
	  mword_count_p: out std_logic_vector (17 downto 0);
	  mev_count_p,num_cycles_p: out std_logic_vector (15 downto 0);
-- registros
     mem_pointer_p: out std_logic_vector (17 downto 0)
     );		
end rm_registros;

architecture arch of rm_registros is

constant ctrl_add: std_logic_vector(5 downto 0):=      "000000";	-- status y control
constant pointerl_add: std_logic_vector(5 downto 0):=  "000001";	-- memory pointer low
constant pointerh_add: std_logic_vector(5 downto 0):=  "000010";	-- memory pointer high
constant wordl_add: std_logic_vector(5 downto 0):=     "000011";	-- max word counter low
constant wordh_add: std_logic_vector(5 downto 0):=     "000100";	-- max word counter high
constant event_add: std_logic_vector(5 downto 0):=     "000101";	-- max event counter low
constant cycle_add: std_logic_vector(5 downto 0):=     "000110";	-- cycle count

signal mem_pointer: std_logic_vector (17 downto 0);
signal mword_count: std_logic_vector (17 downto 0);
signal mevent_count: std_logic_vector (15 downto 0);
signal ena_word_count, ena_event_count, ena_fill_mem, 
     ena_cycles, ena_random: std_logic;
signal ena_ceros_mem, ena_gol_test, ena_word_count_reg: std_logic;
signal num_cycles: std_logic_vector (15 downto 0);

-- LFSR
signal lfsr_0: std_logic_vector (40 downto 0);
signal lfsr_1: std_logic_vector (30 downto 0);
--signal lfsr_2: std_logic_vector (20 downto 0);
--signal lfsr_3: std_logic_vector (10 downto 0);
signal ena_lfsr: std_logic_vector (3 downto 0);

--signal mem_is_full_p, mem_full: std_logic;
signal mem_is_full_p: std_logic;
signal rst_mpointer, rst_wcount: std_logic;
begin
-- puertos

ena_word_count_p <= ena_word_count;
ena_event_count_p <= ena_event_count;
ena_gol_test_p <= ena_gol_test;
ena_ceros_mem_p <= ena_ceros_mem;
ena_cycles_p <= ena_cycles;
ena_random_p <= ena_random;

mword_count_p <= mword_count;
mev_count_p <= mevent_count;
num_cycles_p <= num_cycles;
mem_pointer_p <= mem_pointer;

mem_is_full <= mem_is_full_p;

-- etr y cs en la salida
db_out <= "00000" & ena_lfsr & ena_random & ena_cycles & ena_fill_mem & ena_event_count 
               & ena_word_count & ena_ceros_mem & ena_gol_test when add=ctrl_add else

          mem_pointer (15 downto 0) when add=pointerl_add else
          X"000" & "00" & mem_pointer (17 downto 16) when add=pointerh_add else

          mword_count (15 downto 0) when add=wordl_add else
--          X"000" & "000" & mword_count (16) when add=wordh_add else
	       X"000" & "00" & mword_count (17 downto 16) when add=wordh_add else

          mevent_count when add=event_add else 
          
          num_cycles when add=cycle_add else

          (others => '0');

------------------
---- registros----
------------------

-- status & control
process (clk, reset)
begin
     if reset='1' then
               ena_gol_test <= '0';          
               ena_ceros_mem <= '0';          
               ena_word_count_reg <= '0';
               ena_event_count <= '0';
               ena_fill_mem <= '0';
               ena_cycles <= '0';
               ena_random <= '0';
               ena_lfsr <= (others => '0');
     elsif clk'event and clk='1' then
          if mem_done='1' then
               ena_gol_test <= '0';
               ena_ceros_mem <= '0';
               ena_fill_mem <= '0';
          elsif cs='1' and enw='1' and add=ctrl_add then
               ena_gol_test <= db_in (0) and not(db_in(1));
               ena_ceros_mem <= db_in (1);
               ena_word_count_reg <= db_in (2);
               ena_event_count <= db_in (3);
               ena_fill_mem <= db_in (4);
               ena_cycles <= db_in (5);
               ena_random <= db_in (6);
               ena_lfsr <= db_in (10 downto 7);
		end if;
     end if;
end process;

ena_word_count <= ena_word_count_reg or ena_fill_mem;


-- memory pointer
process (clk, reset,rst_mpointer)
begin
   if reset='1' then
            mem_pointer <= (others => '0');
	elsif rst_mpointer='1' then
            mem_pointer <= (others => '0');
   elsif clk'event and clk='1' then
     if add=pointerl_add and enw='1' and  cs='1' then
            mem_pointer (15 downto 0) <= db_in;
  				mem_pointer(17 downto 16) <= mem_pointer(17 downto 16);
      elsif add=pointerh_add and enw='1' and  cs='1' then
	  	--		if db_in(2)='1' then
		  --			mem_pointer <= (others=>'0');
			--	else
  				mem_pointer(15 downto 0) <= mem_pointer(15 downto 0);
            	mem_pointer (17 downto 16) <= db_in (1 downto 0);
-- 				end if;
	   --elsif (mem_pointer/=("111111111111111111")) and inc_pointer='1' then
        elsif inc_pointer='1' and mem_is_full_p='0' then
            mem_pointer <= mem_pointer +1;
	  	else
			mem_pointer <= mem_pointer;
		end if;
   end if;
end process;
rst_mpointer <= '1' when add=pointerh_add and enw='1' and  cs='1' and db_in(2)='1' else reset_pointer;

--mem_full <= '1' when mem_is_full_p='1' and inc_pointer='1' else '0';
 
--Stop ceros to mem por events si mem full
process (clk, reset)
begin
   if reset='1' then
            mem_is_full_p <= '0';
   elsif clk'event and clk='1' then
	  if add=pointerh_add and enw='1' and  cs='1' and db_in(2) ='1'  then
--		   if db_in(2)='1' then
	    	  mem_is_full_p<= '0';
--			end if;
	  elsif (mem_pointer=("111111111111111110") and inc_pointer='1') then
		  mem_is_full_p<='1';
	  end if;
   end if;
end process;

-- max counts & counter
     -- max word count
-- mayo raro process (clk, reset)
--begin
   --if reset='1' then
    --    mword_count <= (others => '0');
  -- elsif clk'event and clk='1' then
--        if add=wordl_add and enw='1' and  cs='1' then
     --      mword_count (15 downto 0) <= db_in;
   --     elsif add=wordh_add and enw='1' and  cs='1' then
 --	  	     if db_in(2)='1' then
--			         mword_count <= (others=>'0');
--		     else
--	               mword_count (17 downto 16) <= db_in (1 downto 0);
--	    	  end if;
--       elsif ena_fill_mem='1' then
		--	         mword_count <= (others=>'1');
	 --   end if;
  --   end if;
--end process;

process (clk, reset, rst_wcount)
begin
   if reset='1' then
        mword_count <= (others => '0');
 	elsif rst_wcount='1' then 
	        mword_count <= (others => '0');
   elsif clk'event and clk='1' then
       if add=wordl_add and enw='1' and  cs='1' then
              mword_count (15 downto 0) <= db_in;
				  mword_count (17 downto 16) <= mword_count (17 downto 16);
       elsif add=wordh_add and enw='1' and  cs='1' then
 	  	 --    if db_in(2)='1' then
			--         mword_count <= (others=>'0');
		   --  else
	           mword_count (17 downto 16) <= db_in (1 downto 0);
				  mword_count (15 downto 0) <= mword_count (15 downto 0);
	    	 -- end if;
       elsif ena_fill_mem='1' then
			  mword_count <= (others=>'1');
	    else
		  	mword_count <= mword_count;
		 end if;
     end if;
end process;

rst_wcount <= '1' when add=wordh_add and enw='1' and  cs='1' and db_in(2)='1' else '0';

     -- max event count
process (clk, reset)
begin
     if reset='1' then
       mevent_count <= (others => '0');
     elsif clk'event and clk='1' then
       if add=event_add and enw='1' and  cs='1' then
         mevent_count <= db_in;
       end if;
     end if;
end process;
 
-- contador de ciclos
     -- número de ciclos
process (clk, reset)
begin
     if reset='1' then
       num_cycles <= (others => '0');
     elsif clk'event and clk='1' then
       if add=cycle_add and enw='1' and cs='1' then
         num_cycles <= db_in;             
       end if;
     end if;
end process;

-- segun carlos es asi, con or not y and LFSR: ver XAPP052.pdf
-- se trata de simular el ancho de banda real que vamos a tener
txena_out_lfsr <= (lfsr_0 (40) or not ena_lfsr(0)) and
        (lfsr_1 (30) or not ena_lfsr(1));
		  -- and 
 --       (lfsr_2 (20) or not ena_lfsr(2)) and 
   --     (lfsr_3 (10) or not ena_lfsr(3));

process (clk, reset)
begin
     if reset ='1' then
       lfsr_0 <= (others => '0');
       lfsr_1 <= (others => '0');
      --lfsr_2 <= (others => '0');
--       lfsr_3 <= (others => '0');
     elsif clk'event and clk='1' then
       lfsr_0 <= lfsr_0 (39 downto 0) & (lfsr_0 (40) xnor lfsr_0 (37)); -- 41: 41 y 38
       lfsr_1 <= lfsr_1 (29 downto 0) & (lfsr_1 (30) xnor lfsr_1 (27)); -- 31: 31 y 28
  --    lfsr_2 <= lfsr_2 (19 downto 0) & (lfsr_2 (20) xnor lfsr_2 (18)); -- 21: 21 y 19
    --   lfsr_3 <= lfsr_3 (9 downto 0)  & (lfsr_3 (10) xnor lfsr_3 (8));  -- 11: 11 y 9
     end if;
end process;


end arch;



	
