--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+library utility;
+
+
+entity fifo_xclk is
+ port (
+ 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(7 downto 0);
+
+ tail_clk_i: in std_logic;
+ tail_stb_o: out std_logic;
+ tail_ack_i: in std_logic;
+ tail_dat_o: out std_logic_vector(7 downto 0)
+ );
+end fifo_xclk;
+
+
+architecture behavioral of fifo_xclk is
+
+ signal tail_adr_xclk: std_logic_vector(10 downto 0);
+ signal head_adr_reg: unsigned(10 downto 0) := (others => '0');
+ signal head_adr_next: unsigned(10 downto 0);
+ signal head_rdy: std_logic;
+ signal head_step: std_logic;
+ signal is_full: std_logic;
+
+ signal head_adr_xclk: std_logic_vector(10 downto 0);
+ signal tail_adr_reg: unsigned(10 downto 0) := (others => '0');
+ signal tail_adr_next: unsigned(10 downto 0);
+ signal tail_stb: std_logic;
+ signal tail_step: std_logic;
+ signal is_empty: std_logic;
+
+begin
+
+ -- Head logic
+
+ e_xclk_tail: entity utility.xclk_vec
+ port map (
+ a_sig_i => std_logic_vector(tail_adr_reg),
+ b_clk_i => head_clk_i,
+ b_sig_o => tail_adr_xclk
+ );
+
+ is_full <= '1' when std_logic_vector(head_adr_next) = tail_adr_xclk else '0';
+
+ head_rdy <= not is_full;
+ head_rdy_o <= head_rdy;
+
+ head_step <= head_stb_i and head_rdy;
+ head_adr_next <= head_adr_reg + 1;
+
+ process (head_clk_i)
+ begin
+ if rising_edge(head_clk_i) then
+ if head_step = '1' then
+ head_adr_reg <= head_adr_next;
+ end if;
+ end if;
+ end process;
+
+
+ -- Tail logic
+
+ e_xclk_head: entity utility.xclk_vec
+ port map (
+ a_sig_i => std_logic_vector(head_adr_reg),
+ b_clk_i => tail_clk_i,
+ b_sig_o => head_adr_xclk
+ );
+
+ is_empty <= '1' when std_logic_vector(tail_adr_reg) = head_adr_xclk else '0';
+
+ tail_stb <= not is_empty;
+ tail_stb_o <= tail_stb;
+
+ tail_step <= tail_stb and tail_ack_i;
+ tail_adr_next <= tail_adr_reg + 1 when tail_step = '1' else tail_adr_reg;
+
+ process (tail_clk_i)
+ begin
+ if rising_edge(tail_clk_i) then
+ if tail_step = '1' then
+ tail_adr_reg <= tail_adr_next;
+ end if;
+ end if;
+ end process;
+
+
+ -- FIFO memory
+
+ e_fifo: ramb16_s9_s9
+ generic map (
+ SIM_COLLISION_CHECK => "GENERATE_X_ONLY"
+ )
+ port map (
+ -- Port A is the FIFO head
+ wea => head_step,
+ ena => '1',
+ ssra => '0',
+ clka => head_clk_i,
+ addra => std_logic_vector(head_adr_reg),
+ dia => head_dat_i,
+ dipa => "0",
+ doa => open,
+ dopa => open,
+
+ -- Port B is the FIFO tail
+ web => '0',
+ enb => '1',
+ ssrb => '0',
+ clkb => tail_clk_i,
+ addrb => std_logic_vector(tail_adr_next),
+ dib => x"00",
+ dipb => "0",
+ dob => tail_dat_o,
+ dopb => open
+ );
+
+end behavioral;