From 57164c1ac461d3eda6d5915ad5f94b41351634b5 Mon Sep 17 00:00:00 2001 From: rs <> Date: Thu, 11 Dec 2025 02:46:46 -0600 Subject: [PATCH] Add sample delay entities --- libraries/dsp/delay_bram.vhd | 82 +++++++++++++ libraries/dsp/delay_srl.vhd | 86 ++++++++++++++ libraries/dsp/tests/test_delay_bram.vhd | 79 +++++++++++++ libraries/dsp/tests/test_delay_srl.vhd | 151 ++++++++++++++++++++++++ 4 files changed, 398 insertions(+) create mode 100644 libraries/dsp/delay_bram.vhd create mode 100644 libraries/dsp/delay_srl.vhd create mode 100644 libraries/dsp/tests/test_delay_bram.vhd create mode 100644 libraries/dsp/tests/test_delay_srl.vhd diff --git a/libraries/dsp/delay_bram.vhd b/libraries/dsp/delay_bram.vhd new file mode 100644 index 0000000..e58157b --- /dev/null +++ b/libraries/dsp/delay_bram.vhd @@ -0,0 +1,82 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +library unisim; +use unisim.vcomponents.all; + + +entity delay_bram is + generic ( + WIDTH: positive := 16; + DELAY: positive := 2048 + ); + port ( + rst_i: in std_logic; + clk_i: in std_logic; + + en_i: in std_logic; + + dat_i: in std_logic_vector(WIDTH-1 downto 0); + dat_o: out std_logic_vector(WIDTH-1 downto 0) + ); +end delay_bram; + + +architecture behavioral of delay_bram is + + constant COUNT_WIDTH: integer := 10; --integer(ceil(log2(real(DELAY)))); + + signal ptr_head_reg: unsigned(COUNT_WIDTH-1 downto 0); + signal ptr_tail_reg: unsigned(COUNT_WIDTH downto 0); + +begin + + process (rst_i, clk_i, en_i, ptr_head_reg, ptr_tail_reg) + variable tail_sign: std_logic; + begin + if rising_edge(clk_i) then + if rst_i = '1' then + ptr_tail_reg <= unsigned(to_signed(-DELAY, COUNT_WIDTH+1)); + ptr_head_reg <= (others => '0'); + elsif en_i = '1' then + tail_sign := ptr_tail_reg(COUNT_WIDTH); + ptr_tail_reg <= ptr_tail_reg + 1; + if tail_sign = '0' then + ptr_tail_reg(COUNT_WIDTH) <= '0'; + end if; + + ptr_head_reg <= ptr_head_reg + 1; + end if; + end if; + end process; + + e_fifo: ramb16_s18_s18 + port map ( + -- Head port (insertion) + WEA => '1', + ENA => en_i, + SSRA => '0', + CLKA => clk_i, + ADDRA => std_logic_vector(ptr_head_reg), + DIA => dat_i(15 downto 0), + DIPA => (others => '0'), + + DOA => open, + DOPA => open, + + -- Tail port (removal) + WEB => '0', + ENB => en_i, + SSRB => ptr_tail_reg(COUNT_WIDTH), + CLKB => clk_i, + ADDRB => std_logic_vector(ptr_tail_reg(9 downto 0)), + DIB => (others => '0'), + DIPB => (others => '0'), + + DOB => dat_o(15 downto 0), + DOPB => open + ); + +end behavioral; diff --git a/libraries/dsp/delay_srl.vhd b/libraries/dsp/delay_srl.vhd new file mode 100644 index 0000000..bbb6beb --- /dev/null +++ b/libraries/dsp/delay_srl.vhd @@ -0,0 +1,86 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + + +entity delay_srl is + generic ( + WIDTH: positive := 16; + DELAY: natural := 16 + ); + port ( + rst_i: in std_logic; + clk_i: in std_logic; + + en_i: in std_logic; + dat_i: in std_logic_vector(WIDTH-1 downto 0); + dat_o: out std_logic_vector(WIDTH-1 downto 0) + ); +end delay_srl; + + +architecture behavioral of delay_srl is + + constant NUM_FULL_SRLS: natural := DELAY / 16; + constant NUM_EXTRA_STAGES: natural := DELAY mod 16; + + signal extra_tap: std_logic_vector(3 downto 0) := std_logic_vector(to_signed(NUM_EXTRA_STAGES-1, 4)); + + type word_array_t is array(natural range <>) of std_logic_vector(WIDTH-1 downto 0); + + signal shift: std_logic; + + signal srl_in: word_array_t(NUM_FULL_SRLS downto 1); + signal srl_out: word_array_t(NUM_FULL_SRLS downto 0); + signal extra_in: std_logic_vector(WIDTH-1 downto 0); + signal extra_out: std_logic_vector(WIDTH-1 downto 0); + +begin + + shift <= en_i or rst_i; + + srl_out(0) <= dat_i; + + g_full: for i in 1 to NUM_FULL_SRLS generate + srl_in(i) <= (others => '0') when rst_i = '1' else srl_out(i-1); + g_bits: for j in WIDTH-1 downto 0 generate + e_srl: srlc16e + port map ( + D => srl_in(i)(j), + CE => shift, + CLK => clk_i, + A0 => '0', + A1 => '0', + A2 => '0', + A3 => '0', + Q => open, + Q15 => srl_out(i)(j) + ); + end generate; + end generate; + + g_end_n: if NUM_EXTRA_STAGES > 0 generate + extra_in <= (others => '0') when rst_i = '1' else srl_out(NUM_FULL_SRLS); + g_bits: for j in WIDTH-1 downto 0 generate + e_last: srl16e + port map ( + D => extra_in(j), + CE => shift, + CLK => clk_i, + A0 => extra_tap(0), + A1 => extra_tap(1), + A2 => extra_tap(2), + A3 => extra_tap(3), + Q => extra_out(j) + ); + end generate; + dat_o <= extra_out; + end generate; + g_end_0: if NUM_EXTRA_STAGES = 0 generate + dat_o <= srl_out(NUM_FULL_SRLS); + end generate; + +end behavioral; diff --git a/libraries/dsp/tests/test_delay_bram.vhd b/libraries/dsp/tests/test_delay_bram.vhd new file mode 100644 index 0000000..f947d94 --- /dev/null +++ b/libraries/dsp/tests/test_delay_bram.vhd @@ -0,0 +1,79 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; + + +entity test_delay_bram is +end test_delay_bram; + + +architecture behavior of test_delay_bram is + + constant CLK_I_PERIOD: time := 20 ns; + + signal rst_i: std_logic; + signal clk_i: std_logic; + + signal en: std_logic; + + signal dat_i: std_logic_vector(15 downto 0); + signal dat_o: std_logic_vector(15 downto 0); + +begin + + p_test: process + begin + -- Initial values + en <= '0'; + + -- Reset + rst_i <= '1'; + wait for CLK_I_PERIOD; + rst_i <= '0'; + + -- Test + en <= '1'; + dat_i <= x"0001"; + wait for CLK_I_PERIOD; + dat_i <= x"0002"; + wait for CLK_I_PERIOD; + dat_i <= x"0003"; + wait for CLK_I_PERIOD; + dat_i <= x"0004"; + wait for CLK_I_PERIOD; + dat_i <= x"0005"; + wait for CLK_I_PERIOD; + dat_i <= x"0006"; + wait for CLK_I_PERIOD; + dat_i <= x"0007"; + wait for CLK_I_PERIOD; + dat_i <= x"0008"; + wait for CLK_I_PERIOD; + + -- Done + wait; + end process; + + e_uut: entity work.delay_bram + generic map ( + WIDTH => 16, + DELAY => 4 + ) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => en, + dat_i => dat_i, + dat_o => dat_o + ); + + p_clk: process + begin + clk_i <= '0'; + wait for CLK_I_PERIOD/2; + clk_i <= '1'; + wait for CLK_I_PERIOD/2; + end process; + +end; diff --git a/libraries/dsp/tests/test_delay_srl.vhd b/libraries/dsp/tests/test_delay_srl.vhd new file mode 100644 index 0000000..3501d0b --- /dev/null +++ b/libraries/dsp/tests/test_delay_srl.vhd @@ -0,0 +1,151 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; + + +entity test_delay_srl is +end test_delay_srl; + + +architecture behavior of test_delay_srl is + + constant CLK_I_PERIOD: time := 20 ns; + + signal rst_i: std_logic; + signal clk_i: std_logic; + + signal en: std_logic; + + signal dat_i: std_logic_vector(7 downto 0); + signal dat_o_15: std_logic_vector(7 downto 0); + signal dat_o_16: std_logic_vector(7 downto 0); + signal dat_o_17: std_logic_vector(7 downto 0); + signal dat_o_31: std_logic_vector(7 downto 0); + signal dat_o_32: std_logic_vector(7 downto 0); + signal dat_o_33: std_logic_vector(7 downto 0); + +begin + + p_test: process + begin + -- Initial values + en <= '0'; + + -- Reset + rst_i <= '1'; + wait for CLK_I_PERIOD*17; + rst_i <= '0'; + + -- Test + en <= '1'; + dat_i <= x"01"; + wait for CLK_I_PERIOD; + dat_i <= x"02"; + wait for CLK_I_PERIOD; + dat_i <= x"03"; + wait for CLK_I_PERIOD; + dat_i <= x"04"; + wait for CLK_I_PERIOD; + dat_i <= x"a5"; + wait for CLK_I_PERIOD; + + wait for CLK_I_PERIOD*33; + en <= '0'; + + -- Test reset + rst_i <= '1'; + wait for CLK_I_PERIOD*17; + rst_i <= '0'; + + -- Done + wait; + end process; + + e_uut_15: entity work.delay_srl + generic map ( + WIDTH => 8, + DELAY => 15 + ) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => en, + dat_i => dat_i, + dat_o => dat_o_15 + ); + + e_uut_16: entity work.delay_srl + generic map ( + WIDTH => 8, + DELAY => 16 + ) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => en, + dat_i => dat_i, + dat_o => dat_o_16 + ); + + e_uut_17: entity work.delay_srl + generic map ( + WIDTH => 8, + DELAY => 17 + ) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => en, + dat_i => dat_i, + dat_o => dat_o_17 + ); + + e_uut_31: entity work.delay_srl + generic map ( + WIDTH => 8, + DELAY => 31 + ) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => en, + dat_i => dat_i, + dat_o => dat_o_31 + ); + + e_uut_32: entity work.delay_srl + generic map ( + WIDTH => 8, + DELAY => 32 + ) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => en, + dat_i => dat_i, + dat_o => dat_o_32 + ); + + e_uut_33: entity work.delay_srl + generic map ( + WIDTH => 8, + DELAY => 33 + ) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => en, + dat_i => dat_i, + dat_o => dat_o_33 + ); + + p_clk: process + begin + clk_i <= '0'; + wait for CLK_I_PERIOD/2; + clk_i <= '1'; + wait for CLK_I_PERIOD/2; + end process; + +end; -- 2.43.0