library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ARBITER is
	generic (
      C_START_ADDR         : integer   := 0;
      C_RST_FIFO           : integer   := 799;
      C_ZERO_OUT_END       : integer   := 7199;
      C_TOP_END            : integer   := 79199;
      C_END_ADDR           : integer   := 79999;
      
      C_DATA_WIDTH         : integer   := 32
   );
	port (                        
      CLK               : in  std_logic;
      ARST_N            : in  std_logic;
      GEN_EN            : in  std_logic;
      
      FOR_SPLIT_DATA    : out std_logic_vector(C_DATA_WIDTH-1 downto 0);
      FROM_FIFO_DATA    : in  std_logic_vector(C_DATA_WIDTH-1 downto 0);
      
      DA_FIFO_READ_EN   : out std_logic;
      AD_FIFO_WRITE_EN  : out std_logic;
      
      RST_FIFO       : out std_logic
      
	);
end ARBITER;

architecture implementation of ARBITER is

--	function clogb2 (bit_depth : integer) return integer is            
--	 	variable depth  : integer := bit_depth;                               
--	 	variable count  : integer := 1;                                       
--	 begin                                                                   
--	 	 for clogb2 in 1 to bit_depth loop  -- Works for up to 32 bit integers
--	      if (bit_depth <= 2) then                                           
--	        count := 1;                                                      
--	      else                                                               
--	        if(depth <= 1) then                                              
--	 	       count := count;                                                
--	 	     else                                                             
--	 	       depth := depth / 2;                                            
--	          count := count + 1;                                            
--	 	     end if;                                                          
--	 	   end if;                                                            
--	   end loop;                                                             
--	   return(count);        	                                              
--	 end;                                                                    
--   -- user constants
   
   
   -- user signals
   signal count_d	   : unsigned(16 downto 0);
   signal count_q	   : unsigned(16 downto 0);
   

begin
   
   ----------------------------------------------------------------------------
   --                        INCREMENTATION REGISTER
   ----------------------------------------------------------------------------                                
   P_INCR_REG:process(CLK)                                                                                        
   begin                                                                                                      
      if (rising_edge (CLK)) then
         if (ARST_N = '0') then
           count_q <= to_unsigned(C_START_ADDR,count_q'length);            
         elsif(GEN_EN = '1')  then                                                                                                
           count_q <= count_d;                                                           
         end if;                                                                                                
      end if;                                                                                                  
   end process P_INCR_REG;
   
   ----------------------------------------------------------------------------
   --                        INCREMENTATION LOGIC
   ----------------------------------------------------------------------------                                
   P_INCR_LOG:process(count_q, GEN_EN)
   begin
      count_d <= count_q;
      if(GEN_EN = '1') then 
         count_d <= count_q +1;
         if (count_q >= to_unsigned(C_END_ADDR,count_q'length)) then
            count_d <= to_unsigned(C_START_ADDR,count_d'length);
         end if;
      end if;
   end process P_INCR_LOG;
   
   ----------------------------------------------------------------------------
   --               		 DA_DATA
   ----------------------------------------------------------------------------
   P_DA_DATA:process(clk)
   begin 
      if(rising_edge(clk))then
      FOR_SPLIT_DATA <= (others => '0');
			if(GEN_EN = '1') then 
				if (count_q <= to_unsigned(C_END_ADDR,count_q'length)) then
					if (count_q >= to_unsigned(C_ZERO_OUT_END,count_q'length)) then
						FOR_SPLIT_DATA <= FROM_FIFO_DATA;
					end if;
				end if;
      	end if;
      end if;
   end process P_DA_DATA;  
   
   ----------------------------------------------------------------------------
	--               		 DA FIFO READ ENABLE
	----------------------------------------------------------------------------
	P_DA_EN:process(clk)
	begin 
		if(rising_edge(clk))then     
			DA_FIFO_READ_EN <= '0';
			if(GEN_EN = '1') then 
				if (count_q <= to_unsigned(C_END_ADDR,count_q'length)) then
					if (count_q > to_unsigned(C_ZERO_OUT_END,count_q'length)) then
						DA_FIFO_READ_EN <= '1';
					end if;
				end if;
			end if;
		end if;
	end process P_DA_EN;  

   ----------------------------------------------------------------------------
   --                      AD_FIFO_WRITE_ENABLE
   ----------------------------------------------------------------------------
   P_AD_FIFO_EN:process(clk)
   begin
   	if(rising_edge(clk))then
			AD_FIFO_WRITE_EN <= '0';
			if(GEN_EN = '1') then 
				if (count_q <= to_unsigned(C_TOP_END,count_q'length)) then
					if (count_q >= to_unsigned(C_ZERO_OUT_END,count_q'length)) then
						AD_FIFO_WRITE_EN <= '1';
					end if;
				end if;
			end if;
		end if;
   end process P_AD_FIFO_EN;    

   ----------------------------------------------------------------------------
   --                      CLEAR AND RESET_AD
   ----------------------------------------------------------------------------
   P_AD_FIFO_RST:process(clk)
   begin
   if(rising_edge(clk))then
      RST_FIFO       <= '0';
      if(GEN_EN = '1') then          
         if (count_q < to_unsigned(10,count_q'length)) then
            if (count_q >= to_unsigned(0,count_q'length)) then
               RST_FIFO       <= '1';
            end if;
         end if;
      end if;
	end if;
   end process P_AD_FIFO_RST;

   
end implementation;