labor-mst/src/delay_line.vhd
2021-03-26 23:56:28 +01:00

97 lines
3.2 KiB
VHDL

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;