diff options
| author | Väinö Kauppila <vaino@vke.fi> | 2026-04-19 00:33:08 +0300 |
|---|---|---|
| committer | Väinö Kauppila <vaino@vke.fi> | 2026-04-19 00:33:08 +0300 |
| commit | 8bd8dd6ce07fb8e247f651b3c61c94bb1f00895a (patch) | |
| tree | 87bd95bd073d68efd0ad31a34f0d8926c32ff6db /PIC/fifo.vhd | |
| download | vhdl_pic-8bd8dd6ce07fb8e247f651b3c61c94bb1f00895a.tar.gz vhdl_pic-8bd8dd6ce07fb8e247f651b3c61c94bb1f00895a.zip | |
starting files and example programs
Diffstat (limited to 'PIC/fifo.vhd')
| -rw-r--r-- | PIC/fifo.vhd | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/PIC/fifo.vhd b/PIC/fifo.vhd new file mode 100644 index 0000000..9dd8523 --- /dev/null +++ b/PIC/fifo.vhd @@ -0,0 +1,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; |
