From: rs <> Date: Thu, 8 Jan 2026 04:11:12 +0000 (-0600) Subject: Add SRL-based clock sync FIFO X-Git-Url: https://git.the-white-hart.net/?a=commitdiff_plain;h=3f71ebeedd336ead994da22d1b2403636df94db5;p=vhdl Add SRL-based clock sync FIFO --- diff --git a/libraries/utility/sync_fifo_16.vhd b/libraries/utility/sync_fifo_16.vhd new file mode 100644 index 0000000..877992f --- /dev/null +++ b/libraries/utility/sync_fifo_16.vhd @@ -0,0 +1,163 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +library work; + + +entity sync_fifo_16 is + generic ( + SYNC_STAGES: positive := 2; + WIDTH: positive := 16 + ); + port ( + head_rst_i: in std_logic; + head_clk_i: in std_logic; + head_stb_i: in std_logic; + head_rdy_o: out std_logic; + head_dat_i: in std_logic_vector(WIDTH-1 downto 0); + + tail_rst_i: in std_logic; + tail_clk_i: in std_logic; + tail_stb_o: out std_logic; + tail_rdy_i: in std_logic; + tail_dat_o: out std_logic_vector(WIDTH-1 downto 0) + ); +end sync_fifo_16; + + +architecture behavioral of sync_fifo_16 is + + signal head_rst_wait: std_logic; + signal tail_adr_sync: std_logic_vector(3 downto 0); + signal head_adr_reg: std_logic_vector(3 downto 0) := (others => '0'); + signal head_adr_next: std_logic_vector(3 downto 0); + signal head_rdy: std_logic; + signal head_step: std_logic; + signal is_full: std_logic; + + signal tail_rst_wait: std_logic; + signal head_adr_sync: std_logic_vector(3 downto 0); + signal tail_adr_reg: std_logic_vector(3 downto 0) := (others => '0'); + signal tail_adr_inc: std_logic_vector(3 downto 0); + signal tail_adr_next: std_logic_vector(3 downto 0); + signal tail_stb: std_logic; + signal tail_step: std_logic; + signal tail_dat: std_logic_vector(WIDTH-1 downto 0); + signal tail_dat_reg: std_logic_vector(WIDTH-1 downto 0); + signal is_empty: std_logic; + +begin + + -- Head logic + + e_sync_tail_rst: entity work.sync_sig + generic map (SYNC_STAGES => SYNC_STAGES) + port map ( + clk_i => head_clk_i, + sig_i => tail_rst_i, + sig_o => head_rst_wait + ); + + e_sync_tail: entity work.sync_vec + generic map (SYNC_STAGES => SYNC_STAGES) + port map ( + clk_i => head_clk_i, + sig_i => std_logic_vector(tail_adr_reg), + sig_o => tail_adr_sync + ); + + is_full <= '1' when std_logic_vector(head_adr_next) = tail_adr_sync or + head_rst_i = '1' or head_rst_wait = '1' + else '0'; + + head_rdy <= not is_full; + head_rdy_o <= head_rdy; + + head_step <= head_stb_i and head_rdy; + + e_head_adr: entity work.gray_counter + generic map (N => 4) + port map ( + rst_i => head_rst_i, + clk_i => head_clk_i, + ena_i => head_step, + gray => head_adr_reg, + inc => head_adr_next + ); + + + -- Tail logic + + e_sync_head_rst: entity work.sync_sig + generic map (SYNC_STAGES => SYNC_STAGES) + port map ( + clk_i => tail_clk_i, + sig_i => head_rst_i, + sig_o => tail_rst_wait + ); + + e_sync_head: entity work.sync_vec + generic map (SYNC_STAGES => SYNC_STAGES) + port map ( + clk_i => tail_clk_i, + sig_i => std_logic_vector(head_adr_reg), + sig_o => head_adr_sync + ); + + is_empty <= '1' when std_logic_vector(tail_adr_reg) = head_adr_sync or + tail_rst_i = '1' or tail_rst_wait = '1' + else '0'; + + tail_stb <= not is_empty; + tail_stb_o <= tail_stb; + + tail_step <= tail_stb and tail_rdy_i; + tail_adr_next <= tail_adr_inc when tail_step = '1' else tail_adr_reg; + + e_tail_adr: entity work.gray_counter + generic map (N => 4) + port map ( + rst_i => tail_rst_i, + clk_i => tail_clk_i, + ena_i => tail_step, + gray => tail_adr_reg, + inc => tail_adr_inc + ); + + + -- FIFO memory + + g_ram: for i in WIDTH-1 downto 0 generate + e_ram: ram16x1d + port map ( + WE => head_step, + D => head_dat_i(i), + WCLK => head_clk_i, + A0 => head_adr_reg(0), + A1 => head_adr_reg(1), + A2 => head_adr_reg(2), + A3 => head_adr_reg(3), + SPO => open, + + DPRA0 => tail_adr_next(0), + DPRA1 => tail_adr_next(1), + DPRA2 => tail_adr_next(2), + DPRA3 => tail_adr_next(3), + DPO => tail_dat(i) + ); + end generate; + + process (tail_clk_i, tail_dat) + begin + if rising_edge(tail_clk_i) then + tail_dat_reg <= tail_dat; + end if; + end process; + + tail_dat_o <= tail_dat_reg; + +end behavioral;