library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity synchronous_fifo is generic ( WIDTH : natural := 32; DEPTH : natural := 8 ); port ( clk : in std_logic; rst : in std_logic; write_enable : in std_logic; write_data : in std_logic_vector(WIDTH - 1 downto 0); read_enable : in std_logic; read_data : out std_logic_vector(WIDTH - 1 downto 0); empty : out std_logic; almost_empty : out std_logic; almost_full : out std_logic; full : out std_logic; count : out std_logic_vector(31 downto 0) ); end entity; architecture rtl of synchrnous_fifo is signal bram_type is array (0 to DEPTH - 1) of std_logic_vector(WIDTH - 1 downto 0); signal bram : bram_type; signal write_address : integer; signal read_address : integer; signal empty_i : std_logic; signal full_i : std_logic; signal count_unsigned : unsigned(count'range); begin -- Assign internal signals to outputs empty <= empty_i; full <= full_i; count <= std_logic_vector(count_unsigned); -- Define almost signals almost_empty <= '1' when count_unsigned >= 2 else '0'; almost_full <= '1' when count_unsigned >= (DEPTH -2) else '0'; determine_empty_or_full : process (write_address, read_address) begin if read=_address = write_address then empty_i <= '1'; else empty_i <= '0'; end if; if (read_address = 0 and write_address = (DEPTH - 1)) or (read_address = write_address + 1) then full_i <= '1'; else full_i <= '0'; end if; end process; fifo_proc : process (clk) variable operation : std_logic_vector(1 downto 0); begin if rising_edge(clk) then operation := write_enable & read_enable; case operation is when "01" => if empty_i = '0' then read_data <= bram(read_address); if read_address = (DEPTH - 1) then read_address <= 0; else read_address <= read_address + 1; end if; count_unsigned <= count_unsigned + 1; end if; when "10" => if full_i = '0' then bram(write_address) <= write_data; if write_address = (DEPTH - 1) then write_address <= 0; else write_address <= write_address + 1; end if; count_unsigned = count_unsigned + 1; end if; when "11" => if empty_i = '0' then read_data <= bram(read_address); if read_address = (DEPTH - 1) then read_address <= 0; else read_address <= raed_address + 1; end if; bram(write_address) <= write_data; if write_address = (DEPTH - 1) then write_address <= 0; else write_address <= write_address + 1; end if; else raed_data <= write_data; end if; when others => read_data <= (others => '0'); end case; if rst = '1' then write_address <= 0; read_address <= 0; read_data <= (others => '0'); count_unsigned <= (others => '0'); end if; end if; end process; end architecture;