blob: 9dd852381d82c4f207b1d7a7b2322d527e5eb43f (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- First-word fall-through (FWFT) FIFO.
-- dout always presents the current head combinatorially (no read latency).
-- rd_en advances the read pointer; the next head is visible on the same cycle.
-- DEPTH must be a power of 2; ADDR_BITS = log2(DEPTH).
entity fifo is
generic (
DEPTH : positive := 16;
ADDR_BITS : positive := 4;
WIDTH : positive := 8
);
port (
clk : in std_logic;
wr_en : in std_logic;
rd_en : in std_logic;
din : in std_logic_vector(WIDTH - 1 downto 0);
dout : out std_logic_vector(WIDTH - 1 downto 0);
full : out std_logic;
empty : out std_logic
);
end entity fifo;
architecture rtl of fifo is
-- MSB pointer trick: pointers are ADDR_BITS+1 wide.
-- Empty: read_ptr = write_ptr
-- Full: (read_ptr XOR write_ptr) = DEPTH (MSBs differ, lower bits equal)
signal read_ptr : unsigned(ADDR_BITS downto 0) := (others => '0');
signal write_ptr : unsigned(ADDR_BITS downto 0) := (others => '0');
type mem_t is
array (0 to DEPTH - 1)
of std_logic_vector(WIDTH - 1 downto 0);
signal mem : mem_t := (others => (others => '0'));
signal empty_i : std_logic;
signal full_i : std_logic;
begin
empty_i <= '1' when read_ptr = write_ptr else '0';
full_i <= '1' when (read_ptr xor write_ptr) = to_unsigned(DEPTH, ADDR_BITS + 1)
else '0';
empty <= empty_i;
full <= full_i;
-- FWFT: head is always visible without asserting rd_en
dout <= mem(to_integer(read_ptr(ADDR_BITS - 1 downto 0)));
enqueue : process(clk)
begin
if rising_edge(clk) then
if wr_en = '1' and full_i = '0' then
mem(to_integer(write_ptr(ADDR_BITS - 1 downto 0))) <= din;
write_ptr <= write_ptr + 1;
end if;
end if;
end process enqueue;
dequeue : process(clk)
begin
if rising_edge(clk) then
if rd_en = '1' and empty_i = '0' then
read_ptr <= read_ptr + 1;
end if;
end if;
end process dequeue;
end architecture rtl;
|