-- -------------------------------------------------------------------------- -- -- TRASHERNET - A Trashy Ethernet Stack for FPGAs -- -- -------------------------------------------------------------------------- -- -- fifo.vhd : Basic single-clock FIFO -- Implements a basic single-clock FIFO -- -------------------------------------------------------------------------- -- -- Author : Markus Koch -- Contributors : None -- License : Mozilla Public License (MPL) Version 2 -- -------------------------------------------------------------------------- -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity fifo is generic( DEPTH : natural -- Number of elements the FIFO can hold ); port( -- Global clk : in std_logic; -- Global clock rst : in std_logic; -- Asynchronous reset -- FIFO clear : in std_logic; -- Synchronous reset (clear FIFO) data_in : in std_logic_vector; -- Data into the FIFO (automatically constrains width) push : in std_logic; -- Push `data_in` into the FIFO full : out std_logic; -- No further elements can be pushed into the FIFO data_out : out std_logic_vector; -- Data out of the FIFO pop : in std_logic; -- Get an element from the FIFO empty : out std_logic -- FIFO is empty ); end entity fifo; architecture rtl of fifo is type memory_t is array (natural range <>) of std_logic_vector(data_in'range); signal memory : memory_t(0 to DEPTH - 1); subtype memory_pointer_t is integer range 0 to DEPTH - 1; subtype usage_counter_t is integer range 0 to DEPTH; signal read_pointer : memory_pointer_t; signal write_pointer : memory_pointer_t; signal usage_counter : usage_counter_t; begin fifo_proc : process(clk, rst) is procedure increment_pointer(signal pointer : inout memory_pointer_t) is begin if pointer = pointer'subtype'high then pointer <= 0; else pointer <= pointer + 1; end if; end procedure increment_pointer; variable pushed : boolean; variable popped : boolean; begin if rst then read_pointer <= 0; write_pointer <= 0; usage_counter <= 0; elsif rising_edge(clk) then pushed := false; popped := false; if push and not full then memory(write_pointer) <= data_in; increment_pointer(write_pointer); usage_counter <= usage_counter + 1; pushed := true; end if; if pop and not empty then increment_pointer(read_pointer); usage_counter <= usage_counter - 1; popped := true; end if; if pushed and popped then usage_counter <= usage_counter; end if; if clear then read_pointer <= 0; write_pointer <= 0; usage_counter <= 0; end if; end if; end process fifo_proc; data_out <= memory(read_pointer); empty <= '1' when usage_counter = 0 else '0'; full <= '1' when usage_counter = DEPTH else '0'; end architecture rtl;