--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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;