library ieee; use ieee.std_logic_1164.all; -- this fifo is meant to be used -- as a entity dfifo is generic ( SIZE_2LOG : natural; WIDTH : natural := 32); port ( rst_in : in std_logic; wr_clk_i : in std_logic; wr_en_i : in std_logic; wr_data_i : in std_logic_vector(WIDTH - 1 downto 0); rd_clk_i : in std_logic; rd_en_i : in std_logic; rd_data_o : out std_logic_vector(WIDTH - 1 downto 0); empty_o : out std_logic; -- valid on rd_clk? full_o : out std_logic); -- valid on wr_clk? end entity dfifo; architecture a1 of dfifo is constant SIZE : natural := 2**SIZE_2LOG; signal wr_pos : std_logic_vector(SIZE_2LOG - 1 downto 0); -- signal wr_pos_gray : std_logic_vector(SIZE_2LOG - 1 downto 0); signal wr_next_pos_gray : std_logic_vector(SIZE_2LOG - 1 downto 0); -- register of wr_pos and wr_next_pos sampled at rd_clock -- signal wr_pos_gray_rsync : std_logic_vector(SIZE_2LOG - 1 downto 0); signal wr_next_pos_gray_rsync : std_logic_vector(SIZE_2LOG - 1 downto 0); signal rd_pos : std_logic_vector(SIZE_2LOG - 1 downto 0); signal rd_pos_gray : std_logic_vector(SIZE_2LOG - 1 downto 0); -- register of rd_pos_gray sampled at wr_clock signal rd_pos_gray_wsync : std_logic_vector(SIZE_2LOG - 1 downto 0); signal wr_en : std_logic; signal rd_en : std_logic; signal empty : std_logic; signal full : std_logic; begin -- architecture a1 write_counter_gray : entity work.bin2gray generic map ( WIDTH => SIZE_2LOG) port map ( bin_i => std_logic_vector(unsigned(wr_pos) + 1), gray_o => wr_next_pos_gray); write_counter : entity work.counter generic map ( WIDTH => SIZE_2LOG, MAX => SIZE) port map ( clk_i => wr_clk_i, rst_in => rst_in, increment_i => wr_en, count_o => wr_pos); read_counter_gray : entity work.bin2gray generic map ( WIDTH => SIZE_2LOG) port map ( bin_i => rd_pos, gray_o => rd_pos_gray); read_counter : entity work.counter generic map ( WIDTH => SIZE_2LOG, MAX => SIZE) port map ( clk_i => rd_clk_i, rst_in => rst_in, increment_i => rd_en, count_o => rd_pos); ram : entity work.dual_port_ram generic map ( SIZE => SIZE, SIZE_2LOG => SIZE_2LOG, WIDTH => WIDTH) port map ( wr_clk_i => wr_clk_i, wr_addr_i => wr_pos, wr_en_i => wr_en, wr_data_i => wr_data_i, rd_clk_i => rd_clk_i, rd_addr_i => rd_pos, rd_data => rd_data_o); -- resynchronizer_wr_pos_gray_rsync: entity work.resynchronizer -- port map ( -- orig_clk_i => wr_clk_i, -- target_clk_i => rd_clk_i, -- sig_i => wr_pos_gray, -- sig_o => wr_pos_gray_rsync); resynchronizer_wr_pos_next_gray_rsync: entity work.resynchronizer port map ( orig_clk_i => wr_clk_i, target_clk_i => rd_clk_i, sig_i => wr_next_pos_gray, sig_o => wr_next_pos_gray_rsync); resynchronizer_rd_pos_gray_wsync: entity work.resynchronizer port map ( orig_clk_i => wr_clk_i, target_clk_i => rd_clk_i, sig_i => rd_pos_gray, sig_o => rd_pos_gray_wsync); -- NOTE: this is meant to be used in write domain full <= '1' when rd_pos_gray_wsync = wr_next_pos_gray else '0'; -- NOTE: this is meant to be used in read domain empty <= '1' when rd_pos_gray = wr_pos_gray_rsync else '0'; rd_en <= rd_en_i and not empty; wr_en <= wr_en_i and not full; empty_o <= empty; full_o <= empty; end architecture a1;