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