library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- Variable Size Delay Line -- This entity is based on a single port RAM from which every clock cycle the old contents of an address -- are read out and updated with new contents. By incrementing the addresses in a pre-defined loop we -- have effectively a ring buffer that we can vary in size (up to the maximum capacity of the memory). -- NOTE: Changing the 'delay' value may lead to glitches during the first "delay period", due to the -- way the address generation is made. More specifically, these glitches happen when the 'delay' is -- increased (which is unavoidable), and when it is decreased while the momentarily counter value is -- the same as the new delay value [single cycle glitch]. entity delay_line is generic ( DATA_WIDTH : integer := 12; MAX_DELAY : integer := 200; DELAY_WIDTH : integer := 8 ); port ( clk : in std_logic; reset : in std_logic; delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); data_in : in std_logic_vector(DATA_WIDTH-1 downto 0); data_out : out std_logic_vector(DATA_WIDTH-1 downto 0) ); end entity; architecture arch of delay_line is --*****COMPONENT DECLARATION***** component single_port_ram is generic ( ADDR_WIDTH : integer := 8; DATA_WIDTH : integer := 12 ); port ( clk : in std_logic; addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); wen : in std_logic; ren : in std_logic; wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0); rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0) ); end component; --*****SIGNAl DECLARATION***** signal cnt, cnt_next : integer range 0 to MAX_DELAY := 0; signal memory_out : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0'); begin --*****COMPONENT INSTANTIATION***** ram_inst : single_port_ram generic map ( ADDR_WIDTH => DELAY_WIDTH, DATA_WIDTH => DATA_WIDTH ) port map( clk => clk, addr => std_logic_vector(to_unsigned(cnt,DELAY_WIDTH)), wen => '1', ren => '1', wr_data => data_in, rd_data => memory_out ); ctrl : process(all) begin -- DEFAULT VALUES cnt_next <= cnt; if(to_integer(unsigned(delay)) = 0) then data_out <= data_in; else data_out <= memory_out; -- COUNT GENERATION if (cnt >= (to_integer(unsigned(delay)) - 1)) then cnt_next <= 0; else cnt_next <= cnt + 1; end if; end if; end process; sync : process(clk) begin if rising_edge(clk) then if (reset = '1') then cnt <= 0; else cnt <= cnt_next; end if; end if; end process; end architecture;