From: rs <> Date: Fri, 12 Dec 2025 03:12:44 +0000 (-0600) Subject: Add pipeline stream sources and more tests X-Git-Url: https://git.the-white-hart.net/?a=commitdiff_plain;h=ba4f31a95d9f026cfbf24c6dbe7da530daa22e17;p=vhdl Add pipeline stream sources and more tests --- diff --git a/libraries/dsp/lfsr.vhd b/libraries/dsp/lfsr.vhd new file mode 100644 index 0000000..98f60e3 --- /dev/null +++ b/libraries/dsp/lfsr.vhd @@ -0,0 +1,47 @@ +library ieee; +use ieee.std_logic_1164.all; + +library unisim; +use unisim.vcomponents.all; + + +entity lfsr is + generic ( + INIT: std_logic_vector(15 downto 0) + ); + port ( + clk_i: in std_logic; + en_i: in std_logic; + dat_o: out std_logic + ); +end lfsr; + +architecture behavioral of lfsr is + + signal tap_10: std_logic; + signal tap_15: std_logic; + signal feedback: std_logic; + +begin + + -- This is the example from Xilinx WP271 + -- It's not the best, but it's simple enough to do with one SRL + e_srl: srlc16e + generic map (INIT => to_bitvector(INIT)) + port map ( + D => feedback, + CE => en_i, + CLK => clk_i, + A0 => '0', + A1 => '1', + A2 => '0', + A3 => '1', + Q => tap_10, + Q15 => tap_15 + ); + + feedback <= tap_10 xor tap_15; + dat_o <= tap_15; + +end behavioral; + diff --git a/libraries/dsp/src_counter.vhd b/libraries/dsp/src_counter.vhd new file mode 100644 index 0000000..347373a --- /dev/null +++ b/libraries/dsp/src_counter.vhd @@ -0,0 +1,41 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity src_counter is + generic ( + WIDTH: positive := 16 + ); + port ( + rst_i: in std_logic; + clk_i: in std_logic; + + stb_o: out std_logic; + rdy_i: in std_logic; + dat_o: out std_logic_vector(WIDTH-1 downto 0) + ); +end src_counter; + + +architecture behavioral of src_counter is + + signal count_reg: unsigned(WIDTH-1 downto 0); + +begin + + process(rst_i, clk_i, count_reg) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + count_reg <= (others => '0'); + elsif rdy_i = '1' then + count_reg <= count_reg + 1; + end if; + end if; + end process; + + stb_o <= '1'; + dat_o <= std_logic_vector(count_reg); + +end behavioral; diff --git a/libraries/dsp/src_fracstep.vhd b/libraries/dsp/src_fracstep.vhd new file mode 100644 index 0000000..69e3f92 --- /dev/null +++ b/libraries/dsp/src_fracstep.vhd @@ -0,0 +1,45 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity src_fracstep is + generic ( + WIDTH_OUT: positive := 16; + WIDTH_INC: natural := 16; + WIDTH_FRAC: natural := 8 + ); + port ( + rst_i: in std_logic; + clk_i: in std_logic; + + inc_i: in std_logic_vector(WIDTH_INC-1 downto 0); + + stb_o: out std_logic; + rdy_i: in std_logic; + dat_o: out std_logic_vector(WIDTH_OUT-1 downto 0) + ); +end src_fracstep; + + +architecture behavioral of src_fracstep is + + signal count_reg: unsigned(WIDTH_OUT+WIDTH_FRAC-1 downto 0); + +begin + + process (rst_i, clk_i, inc_i) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + count_reg <= (others => '0'); + elsif rdy_i = '1' then + count_reg <= count_reg + unsigned(inc_i); + end if; + end if; + end process; + + stb_o <= '1'; + dat_o <= std_logic_vector(count_reg(WIDTH_OUT+WIDTH_FRAC-1 downto WIDTH_FRAC)); + +end behavioral; diff --git a/libraries/dsp/src_noise.vhd b/libraries/dsp/src_noise.vhd new file mode 100644 index 0000000..9b341d2 --- /dev/null +++ b/libraries/dsp/src_noise.vhd @@ -0,0 +1,44 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; + + +entity src_noise is + generic ( + WIDTH: positive := 16 + ); + port ( + clk_i: in std_logic; + + stb_o: out std_logic; + rdy_i: in std_logic; + dat_o: out std_logic_vector(WIDTH-1 downto 0) + ); +end src_noise; + + +architecture behavioral of src_noise is + + constant X: std_logic_vector(15 downto 0) := x"0001"; + +begin + + g_bits: for i in WIDTH-1 downto 0 generate + e_lfsr: entity work.lfsr + generic map ( + -- First part guarantees at least one bit set + -- Second part is an attempt at pseudorandomness + INIT => std_logic_vector(rotate_left(unsigned(X), i)) or std_logic_vector(to_unsigned(i*13, 16) xor x"a5c3") + ) + port map ( + clk_i => clk_i, + en_i => rdy_i, + dat_o => dat_o(i) + ); + end generate; + + stb_o <= '1'; + +end behavioral; diff --git a/libraries/dsp/tests/test_delay2.vhd b/libraries/dsp/tests/test_delay2.vhd new file mode 100644 index 0000000..a3af16e --- /dev/null +++ b/libraries/dsp/tests/test_delay2.vhd @@ -0,0 +1,115 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; + + +entity test_delay2 is +end test_delay2; + + +architecture behavior of test_delay2 is + + constant CLK_I_PERIOD: time := 20 ns; + + signal rst_i: std_logic; + signal clk_i: std_logic; + + signal src_stb: std_logic; + signal src_rdy: std_logic; + signal src_dat: std_logic_vector(7 downto 0); + + signal split_a_stb: std_logic; + signal split_a_rdy: std_logic; + signal split_b_stb: std_logic; + signal split_b_rdy: std_logic; + signal split_dat: std_logic_vector(7 downto 0); + + signal delay_en: std_logic; + signal delay_dat: std_logic_vector(7 downto 0); + signal norm_dat: std_logic_vector(7 downto 0); + +begin + + p_test: process + begin + -- Reset + rst_i <= '1'; + wait for CLK_I_PERIOD*17; + rst_i <= '0'; + + -- Done + wait; + end process; + + e_src: entity work.src_counter + generic map (WIDTH => 8) + port map ( + rst_i => rst_i, + clk_i => clk_i, + stb_o => src_stb, + rdy_i => src_rdy, + dat_o => src_dat + ); + + e_split: entity work.pipectrl_split + generic map (WIDTH => 8) + port map ( + rst_i => rst_i, + clk_i => clk_i, + stb_i => src_stb, + rdy_o => src_rdy, + dat_i => src_dat, + a_stb_o => split_a_stb, + a_rdy_i => split_a_rdy, + b_stb_o => split_b_stb, + b_rdy_i => split_b_rdy, + dat_o => split_dat + ); + + e_norm: entity work.pipectrl + generic map (WIDTH => 8) + port map ( + rst_i => rst_i, + clk_i => clk_i, + stb_i => split_a_stb, + rdy_o => split_a_rdy, + dat_i => split_dat, + stb_o => open, + rdy_i => '1', + dat_o => norm_dat + ); + + e_delay_ctrl: entity work.pipectrl + generic map (WIDTH => 8) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_o => delay_en, + stb_i => split_b_stb, + rdy_o => split_b_rdy, + dat_i => split_dat, + stb_o => open, + rdy_i => '1', + dat_o => norm_dat + ); + + e_delay: entity work.delay_srl + generic map (WIDTH => 8, DELAY => 2) + port map ( + rst_i => rst_i, + clk_i => clk_i, + en_i => delay_en, + dat_i => split_dat, + dat_o => delay_dat + ); + + 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_pcm16_2ch_gain.vhd b/libraries/dsp/tests/test_pcm16_2ch_gain.vhd new file mode 100644 index 0000000..23f67e8 --- /dev/null +++ b/libraries/dsp/tests/test_pcm16_2ch_gain.vhd @@ -0,0 +1,98 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; + + +entity test_pcm16_2ch_gain is +end test_pcm16_2ch_gain; + + +architecture behavior of test_pcm16_2ch_gain is + + constant CLK_I_PERIOD: time := 20 ns; + + signal gain_l: std_logic_vector(17 downto 0); + signal gain_r: std_logic_vector(17 downto 0); + + signal rst_i: std_logic; + signal clk_i: std_logic; + signal dat_i: std_logic_vector(31 downto 0); + signal dat_o: std_logic_vector(31 downto 0); + +begin + + p_test: process + begin + -- Initial values + + -- Reset + rst_i <= '1'; + wait for CLK_I_PERIOD; + rst_i <= '0'; + + -- Test + gain_l <= "000000001" & "000000000"; + gain_r <= "000000001" & "000000000"; + dat_i <= x"0001" & x"0002"; + wait for CLK_I_PERIOD; + dat_i <= x"0003" & x"0004"; + wait for CLK_I_PERIOD; + dat_i <= x"0005" & x"0006"; + wait for CLK_I_PERIOD; + dat_i <= x"0007" & x"0008"; + wait for CLK_I_PERIOD; + dat_i <= x"ffff" & x"fffe"; + wait for CLK_I_PERIOD; + dat_i <= x"fffd" & x"fffc"; + wait for CLK_I_PERIOD; + dat_i <= x"fffb" & x"fffa"; + wait for CLK_I_PERIOD; + + gain_l <= "000000000" & "100000000"; + gain_r <= "000000000" & "100000000"; + dat_i <= x"0001" & x"0002"; + wait for CLK_I_PERIOD; + dat_i <= x"0003" & x"0004"; + wait for CLK_I_PERIOD; + dat_i <= x"0005" & x"0006"; + wait for CLK_I_PERIOD; + dat_i <= x"0007" & x"0008"; + wait for CLK_I_PERIOD; + dat_i <= x"ffff" & x"fffe"; + wait for CLK_I_PERIOD; + dat_i <= x"fffd" & x"fffc"; + wait for CLK_I_PERIOD; + dat_i <= x"fffb" & x"fffa"; + wait for CLK_I_PERIOD; + + -- Done + wait; + end process; + + e_uut: entity work.pcm16_2ch_gain + port map ( + rst_i => rst_i, + clk_i => clk_i, + + gain_l => gain_l, + gain_r => gain_r, + + stb_i => '1', + rdy_o => open, + dat_i => dat_i, + + stb_o => open, + rdy_i => '1', + 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_src_noise.vhd b/libraries/dsp/tests/test_src_noise.vhd new file mode 100644 index 0000000..5227242 --- /dev/null +++ b/libraries/dsp/tests/test_src_noise.vhd @@ -0,0 +1,37 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; + + +entity test_src_noise is +end test_src_noise; + + +architecture behavior of test_src_noise is + + constant CLK_I_PERIOD: time := 20 ns; + + signal clk_i: std_logic; + signal dat_o: std_logic_vector(15 downto 0); + +begin + + e_uut: entity work.src_noise + generic map (WIDTH => 16) + port map ( + clk_i => clk_i, + stb_o => open, + rdy_i => '1', + 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;