-- -------------------------------------------------------------------------- -- -- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs -- -- -------------------------------------------------------------------------- -- -- TODO -- -------------------------------------------------------------------------- -- -- 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; use ieee.math_real.all; entity fifo is generic( SIZE : integer := 15 -- Entries in the FIFO (of size data), SIZE=(n^2)-1 recommended ); port( -- generic ports clk : in std_logic; -- System clock rst_a : in std_logic; -- Asynchronous reset clr : in std_logic; -- Remove all entries -- FIFO in data_in : in std_logic_vector; -- Data input into FIFO write : in std_logic; -- Data is latched when `data_in_valid and not full` full : out std_logic; -- FIFO is full -- FIFO out data_out : out std_logic_vector; -- Data output from FIFO empty : out std_logic; -- FIFO is empty. '0' means "data is available". read : in std_logic; -- Acknowledge that `data_out` was read. The word is removed and next one shifted from FIFO when `read and not empty`. -- FIFO meta usage : out integer range 0 to SIZE -- Usage counter ); end fifo; architecture rtl of fifo is constant MEMORY_WIDTH : integer := data_in'length; subtype pointer_t is integer range 0 to SIZE - 1; type memory_t is array (pointer_t) of std_logic_vector(MEMORY_WIDTH - 1 downto 0); signal memory : memory_t; signal read_pointer : pointer_t; signal write_pointer : pointer_t; signal read_pointer_last : pointer_t; begin fifo_p : process(rst_a, clk) is variable succesful_read : std_logic; variable succesful_write : std_logic; variable write_pointer_next : pointer_t; variable read_pointer_next : pointer_t; begin if rst_a then read_pointer <= 0; write_pointer <= 0; read_pointer_last <= SIZE - 1; usage <= 0; elsif rising_edge(clk) then succesful_read := read and not empty; succesful_write := write and (not full or succesful_read); write_pointer_next := write_pointer; read_pointer_next := read_pointer; if succesful_read then read_pointer_next := (read_pointer_next + 1) mod SIZE; read_pointer_last <= read_pointer; end if; if succesful_write then memory(write_pointer) <= data_in; write_pointer_next := (write_pointer_next + 1) mod SIZE; end if; if succesful_write xor succesful_read then if succesful_write then usage <= usage + 1; else usage <= usage - 1; end if; end if; read_pointer <= read_pointer_next; write_pointer <= write_pointer_next; if clr then read_pointer <= 0; write_pointer <= 0; read_pointer_last <= SIZE - 1; usage <= 0; end if; end if; end process fifo_p; full <= '1' when read_pointer_last = write_pointer else '0'; empty <= '1' when (read_pointer = write_pointer) else '0'; data_out <= memory(read_pointer); end rtl;