99 lines
3.0 KiB
VHDL
99 lines
3.0 KiB
VHDL
|
-- -------------------------------------------------------------------------- --
|
||
|
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||
|
-- -------------------------------------------------------------------------- --
|
||
|
-- fifo.vhd : Basic single-clock FIFO
|
||
|
-- Implements a basic single-clock FIFO
|
||
|
-- -------------------------------------------------------------------------- --
|
||
|
-- Author : Markus Koch <markus@notsyncing.net>
|
||
|
-- 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;
|