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

entity ADDR_GEN is
	generic (
      C_START_ADDR         : integer   := 0;
      C_END_ADDR           : integer   := 71992;
      C_ADDR_WIDTH         : integer   := 32;
      C_INCR_STEP          : integer   := 8
   );
	port (                        
      CLK               : in  std_logic;
      ARST_N            : in  std_logic;
      
      INCR_EN           : in  std_logic;
      
      CLEAR					: in  std_logic;
                        
      NEXT_ADDRESS      : out std_logic_vector(C_ADDR_WIDTH-1 downto 0)
	);
end ADDR_GEN;

architecture implementation of ADDR_GEN is                                                                 
    
   -- user signals
   signal count_d	   : unsigned(16 downto 0);
   signal count_q	   : unsigned(16 downto 0);
   
   signal s_clear     : std_logic;
   
   signal incr_1     : std_logic;
   signal incr_2     : std_logic;
   signal incr_pulse : std_logic;

begin
   ----------------------------------------------------------------------------
   --                            PULSE GENERATOR
   ----------------------------------------------------------------------------                                
   P_INCR_PULSE_G:process(CLK)                                                                                        
   begin                                                                                                      
      if (rising_edge (CLK)) then
         if (ARST_N = '0') then
           incr_1 <= '0';       
           incr_2 <= '0';  
           s_clear <= '0';     
         else                                                                                                   
           incr_2 <= incr_1;                                                           
           incr_1 <= INCR_EN;
           s_clear <= clear;                                                           
         end if;                                                                                                
      end if;                                                                                                  
   end process P_INCR_PULSE_G;
   
   incr_pulse <= incr_1 and (not incr_2);
   
   ----------------------------------------------------------------------------
   --                        INCREMENTATION REGISTER
   ----------------------------------------------------------------------------                                
   P_INCR_REG:process(CLK)                                                                                        
   begin                                                                                                      
      if (rising_edge(CLK)) then
         if (ARST_N = '0' or CLEAR = '1') then
           count_q <= to_unsigned(C_START_ADDR,count_q'length);
         else                                                                                                   
           count_q <= count_d;                                                           
         end if;                                                                                                
      end if;                                                                                                  
   end process P_INCR_REG;
   
   NEXT_ADDRESS <= std_logic_vector(resize(count_q,C_ADDR_WIDTH));
   
   ----------------------------------------------------------------------------
   --                        INCREMENTATION LOGIC
   ----------------------------------------------------------------------------                                
   P_INCR_LOG:process(count_q, incr_pulse)                                                                                        
   begin
   	
      count_d <= to_unsigned(C_START_ADDR,count_d'length);
      if(s_CLEAR = '0') then
         count_d <= count_q;
         if(incr_pulse = '1') then
            if(count_q < C_END_ADDR) then
               count_d <= count_q + to_unsigned(C_INCR_STEP,count_d'length);
            end if;
         end if;
      end if;
   end process P_INCR_LOG;   
   
end implementation;
