library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity fifo_dc is generic ( G_DATA_WIDTH : natural := 8; G_ADDR_WIDTH : natural := 8 ); port ( i_reset : in std_logic; i_wr_clk : in std_logic; i_we : in std_logic; i_din : in std_logic_vector(G_DATA_WIDTH - 1 downto 0); o_full : out std_logic; i_rd_clk : in std_logic; i_re : in std_logic; o_dout : out std_logic_vector(G_DATA_WIDTH - 1 downto 0); o_valid : out std_logic; o_empty : out std_logic ); end fifo_dc; architecture rtl of fifo_dc is function f_bin2gray (s_slv : in std_logic_vector) return std_logic_vector is begin return s_slv xor '0' & s_slv(s_slv'left downto 1); end function; function f_gray2bin (s_slv : in std_logic_vector) return std_logic_vector is variable v_slv : std_logic_vector(s_slv'range) := (others => '0'); begin v_slv := s_slv; for i in s_slv'high - 1 downto 0 loop v_slv(i) := s_slv(i) xor v_slv(i + 1); end loop; return v_slv; end function; type T_ARRAY_STD_LOGIC_VECTOR is array (natural range <>) of std_logic_vector; signal s_ram : T_ARRAY_STD_LOGIC_VECTOR(2**G_ADDR_WIDTH - 1 downto 0)(G_DATA_WIDTH - 1 downto 0); signal s_write_reset_done : std_logic; signal s_write_reset_done_sr : std_logic_vector(1 downto 0); signal s_read_reset_done : std_logic; signal s_read_reset_done_sr : std_logic_vector(1 downto 0); signal s_wp_bin_wcd : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_wp_bin_wcd_next1 : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_wp_gray_wcd : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_wp_gray_wcd_next1 : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_wp_gray_wcd_next2 : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_wp_gray_rcd : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_rp_bin_rcd : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_rp_bin_rcd_next1 : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_rp_gray_rcd : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_rp_gray_rcd_next1 : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_rp_gray_wcd : std_logic_vector(G_ADDR_WIDTH downto 0); signal s_full1 : std_logic; signal s_full2 : std_logic; begin process (i_wr_clk, i_reset) begin if i_reset = '1' then s_write_reset_done <= '0'; s_read_reset_done_sr <= (others => '0'); s_wp_bin_wcd <= (others => '0'); s_rp_gray_wcd <= (others => '0'); else if rising_edge(i_wr_clk) then s_write_reset_done <= '1'; s_read_reset_done_sr <= s_read_reset_done_sr(0) & s_read_reset_done; s_rp_gray_wcd <= s_rp_gray_rcd; if s_read_reset_done_sr = "11" and s_write_reset_done = '1' then if s_full1 = '1' then NULL; else if i_we = '1' then s_ram(to_integer(unsigned(s_wp_bin_wcd(G_ADDR_WIDTH - 1 downto 0)))) <= i_din; s_wp_bin_wcd <= s_wp_bin_wcd_next1; else NULL; end if; end if; else NULL; end if; end if; end if; end process; s_wp_gray_wcd <= f_bin2gray(s_wp_bin_wcd); s_wp_bin_wcd_next1 <= std_logic_vector(unsigned(s_wp_bin_wcd) + 1); s_wp_gray_wcd_next1 <= f_bin2gray(s_wp_bin_wcd_next1); s_wp_gray_wcd_next2 <= f_bin2gray(std_logic_vector(unsigned(s_wp_bin_wcd) + 2)); s_full1 <= '1' when s_wp_gray_wcd_next1 = (not s_rp_gray_wcd(G_ADDR_WIDTH) & not s_rp_gray_wcd(G_ADDR_WIDTH - 1) & s_rp_gray_wcd(G_ADDR_WIDTH - 2 downto 0)) else '0'; s_full2 <= '1' when s_wp_gray_wcd_next2 = (not s_rp_gray_wcd(G_ADDR_WIDTH) & not s_rp_gray_wcd(G_ADDR_WIDTH - 1) & s_rp_gray_wcd(G_ADDR_WIDTH - 2 downto 0)) else '0'; o_full <= s_full1 or s_full2; process (i_rd_clk, i_reset) begin if i_reset = '1' then s_read_reset_done <= '0'; s_write_reset_done_sr <= (others => '0'); s_rp_bin_rcd <= (others => '0'); s_wp_gray_rcd <= (others => '0'); o_valid <= '0'; o_empty <= '0'; else if rising_edge(i_rd_clk) then s_read_reset_done <= '1'; s_write_reset_done_sr <= s_write_reset_done_sr(0) & s_write_reset_done; s_wp_gray_rcd <= s_wp_gray_wcd; -- read if s_write_reset_done_sr = "11" and s_read_reset_done = '1' then if s_rp_gray_rcd = s_wp_gray_rcd then o_valid <= '0'; o_empty <= '1'; else o_empty <= '0'; if i_re = '1' then s_rp_bin_rcd <= s_rp_bin_rcd_next1; o_valid <= '1'; else o_valid <= '0'; end if; end if; else o_valid <= '0'; o_empty <= '1'; end if; end if; end if; end process; s_rp_gray_rcd <= f_bin2gray(s_rp_bin_rcd); s_rp_bin_rcd_next1 <= std_logic_vector(unsigned(s_rp_bin_rcd) + 1); s_rp_gray_rcd_next1 <= f_bin2gray(s_rp_bin_rcd_next1); process begin wait until rising_edge(i_rd_clk); o_dout <= s_ram(to_integer(unsigned(s_rp_bin_rcd(G_ADDR_WIDTH - 1 downto 0)))); end process; end;