------------------------------------------------------------------------------- -- Title : FIFO for 8 bit data -- Project : VHDL FLAC Decoder ------------------------------------------------------------------------------- -- File : flacdec_byte_fifo.vhd -- Author : Mario Huettel -- Company : -- Created : 2023-10-05 -- Last update: 2023-10-05 -- Platform : -- Standard : VHDL'93/02 ------------------------------------------------------------------------------- -- Description: This is a generic FIFO implementation for 8 bit Data. This -- implementation should be able to map to a dual ported BRAM in an FPGA. If an -- ASIC Design is used, decide weather to use a RAM instance or let the -- synthesis generate a FIFO out of Flip Flops. -- The FIFO is 64 bytes large. ------------------------------------------------------------------------------- -- Copyright (c) 2023 Mario Huettel ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity flacdec_byte_fifo is port ( clk : in std_logic; -- Clock rst_n : in std_logic; -- async. low-active reset data_in : in std_logic_vector(7 downto 0); data_in_wstrb : in std_logic; -- Write strobe to push data into the FIFO data_out : out std_logic_vector(7 downto 0); -- Output data. 1 cycle delayed after read strobe. data_rstrb : in std_logic; fifo_full : out std_logic; -- FIFO is full fifo_empty : out std_logic; -- FIFO is empty fifo_32_free : out std_logic); -- FIFO has at least 32 bytes free end entity flacdec_byte_fifo; architecture RTL of flacdec_byte_fifo is type fifo_mem_t is array(natural range <>) of std_logic_vector(data_in'range); signal mem : fifo_mem_t(0 to 63); signal read_ptr : unsigned(6 downto 0); signal write_ptr : unsigned(6 downto 0); signal write_strb_s : std_logic; signal read_strb_s : std_logic; signal write_addr : unsigned(5 downto 0); signal read_addr : unsigned(5 downto 0); signal fifo_fill_level : integer range 0 to 64; signal wrapped_around : std_logic; signal fifo_full_s : std_logic; signal fifo_empty_s : std_logic; begin -- architecture RTL fifo_full <= fifo_full_s; fifo_empty <= fifo_empty_s; -------------------------------------------------------------------------- -- FIFO memory implementation -------------------------------------------------------------------------- -- FIFO memory process. Should allow BRAM infer. fifo_mem_proc : process is begin wait until rising_edge(clk); if write_strb_s = '1' then mem(to_integer(write_addr)) <= data_in; end if; if read_strb_s = '1' then data_out <= mem(to_integer(read_addr)); end if; end process fifo_mem_proc; -------------------------------------------------------------------------- -- FIFO fill level and address logic -------------------------------------------------------------------------- -- Addresses to memory are the pointers except for the MSB, which is used -- for wrap around detection read_addr <= read_ptr(read_ptr'high - 1 downto read_ptr'low); write_addr <= write_ptr(write_ptr'high - 1 downto write_ptr'low); wrapped_around <= '1' when read_ptr(read_ptr'high) /= write_ptr(write_ptr'high) else '0'; fill_level_proc : process(wrapped_around, read_addr, write_addr) is begin fifo_fill_level <= 0; if wrapped_around = '0' then fifo_fill_level <= to_integer(write_addr - read_addr); else fifo_fill_level <= to_integer(64 - read_addr + write_addr); end if; end process fill_level_proc; fifo_full_s <= '1' when read_addr = write_addr and wrapped_around = '1' else '0'; fifo_empty_s <= '1' when read_addr = write_addr and wrapped_around = '0' else '0'; fifo_32_free <= '1' when fifo_fill_level >= 32 else '0'; --------------------------------------------------------------------------- -- FIFO write pointer --------------------------------------------------------------------------- write_strb_s <= data_in_wstrb and (not fifo_full_s); write_ptr_proc : process(clk, rst_n) is begin if rst_n = '0' then write_ptr <= (others => '0'); elsif rising_edge(clk) then if write_strb_s = '1' then -- Wrap around expected write_ptr <= write_ptr + 1; end if; end if; end process write_ptr_proc; --------------------------------------------------------------------------- -- FIFO read pointer --------------------------------------------------------------------------- read_strb_s <= data_rstrb and (not fifo_empty_s); read_ptr_proc : process(clk, rst_n) is begin if rst_n = '0' then read_ptr <= (others => '0'); elsif rising_edge(clk) then if read_strb_s = '1' then -- Wrap around expected read_ptr <= read_ptr + 1; end if; end if; end process read_ptr_proc; end architecture RTL;