library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; -------------------------------------------------------------------------------- -- This is a behavioral model of FIFO (Fisrt In First Out) memory. -- -- All operations (except for reset) are synchronous to 'clk' rising edges. -- Reset makes fifo empty but actually does not change the content of memory. -- -- The generic parameter 'width' determines the width of address vector used to -- access memory and so the size of memory. -- -- When overflow occurs, the 'overflow' flag is set to 1 and the least recent -- data is rewritten by new data. -- -- Underflow is not handled currently and causes misfunction. -------------------------------------------------------------------------------- entity fifo is generic ( width : integer := 2 ); port ( clk : in std_logic; reset : in std_logic; we : in std_logic; -- write enable re : in std_logic; -- read enable clear_ow : in std_logic; -- clear overflow flag d_in : in std_logic_vector (7 downto 0); d_out : out std_logic_vector (7 downto 0); full : out std_logic; -- fifo is full hfull : out std_logic; -- fifo is half full empty : out std_logic; -- fifo is empty overflow : out std_logic := '0' ); end fifo; -------------------------------------------------------------------------------- architecture behavioral of fifo is subtype mem_addr_t is std_logic_vector (width-1 downto 0); type mem_t is array (3 downto 0) of std_logic_vector (7 downto 0); signal memory : mem_t; signal read_addr : mem_addr_t := (others => '0'); signal write_addr : mem_addr_t := (others => '0'); signal length : std_logic_vector (width downto 0) := (others => '0'); signal full_s : std_logic; -------------------------------------------------------------------------------- begin -- Handling of overflow output signal and internal length signal, storing -- the number of occupied memory positions. process (clk, reset) begin if (rising_edge(clk)) then if (reset = '1') then length <= (others => '0'); overflow <= '0'; else if ((re = '1') and (we = '0')) then length <= length - 1; elsif ((re = '0') and (we = '1')) then if (full_s = '1') then overflow <= '1'; else length <= length + 1; end if; end if; if (clear_ow = '1') then overflow <= '0'; end if; end if; end if; end process; -- Handling of address registers and writing to memory. process (clk, reset) begin if (reset = '1') then read_addr <= (others => '0'); write_addr <= (others => '0'); elsif (rising_edge(clk)) then if (re = '1') then read_addr <= read_addr + 1; end if; if (we = '1') then write_addr <= write_addr + 1; memory (conv_integer(write_addr)) <= d_in; if (full_s = '1') then read_addr <= read_addr + 1; end if; end if; end if; end process; -------------------------------------------------------------------------------- d_out <= memory (conv_integer(read_addr)); full_s <= '1' when (length >= 2**width) else '0'; full <= full_s; hfull <= '1' when (length >= 2**(width-1)) else '0'; empty <= '1' when (length = 0) else '0'; end behavioral;