0
0
VhdlHow-ToBeginner · 4 min read

VHDL Code for FIFO: Syntax, Example, and Common Pitfalls

A FIFO in VHDL is a memory buffer that stores data in a first-in-first-out order using signals and processes. It typically uses pointers for read and write operations and flags for full and empty states. You can implement it with a RAM array and control logic for enqueue and dequeue.
📐

Syntax

A FIFO in VHDL uses a RAM array to store data, read_ptr and write_ptr signals to track positions, and control signals like full and empty. The main parts are:

  • RAM array: Holds the data elements.
  • Write pointer: Points to where new data is stored.
  • Read pointer: Points to where data is read from.
  • Full and empty flags: Indicate FIFO status.
  • Write enable and read enable: Control data input and output.
vhdl
type fifo_array is array (0 to FIFO_DEPTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal fifo_mem : fifo_array;
signal write_ptr : integer range 0 to FIFO_DEPTH-1 := 0;
signal read_ptr : integer range 0 to FIFO_DEPTH-1 := 0;
signal full, empty : std_logic := '0';
💻

Example

This example shows a simple synchronous FIFO with parameterized depth and data width. It supports write and read operations with full and empty flags.

vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity fifo is
  generic (
    DATA_WIDTH : integer := 8;
    FIFO_DEPTH : integer := 16
  );
  port (
    clk       : in  std_logic;
    rst       : in  std_logic;
    write_en  : in  std_logic;
    read_en   : in  std_logic;
    data_in   : in  std_logic_vector(DATA_WIDTH-1 downto 0);
    data_out  : out std_logic_vector(DATA_WIDTH-1 downto 0);
    full      : out std_logic;
    empty     : out std_logic
  );
end fifo;

architecture rtl of fifo is
  type fifo_array is array (0 to FIFO_DEPTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
  signal fifo_mem : fifo_array := (others => (others => '0'));
  signal write_ptr : integer range 0 to FIFO_DEPTH-1 := 0;
  signal read_ptr  : integer range 0 to FIFO_DEPTH-1 := 0;
  signal count     : integer range 0 to FIFO_DEPTH := 0;
begin
  process(clk, rst)
  begin
    if rst = '1' then
      write_ptr <= 0;
      read_ptr <= 0;
      count <= 0;
      data_out <= (others => '0');
    elsif rising_edge(clk) then
      -- Write operation
      if write_en = '1' and count < FIFO_DEPTH then
        fifo_mem(write_ptr) <= data_in;
        write_ptr <= (write_ptr + 1) mod FIFO_DEPTH;
        count <= count + 1;
      end if;

      -- Read operation
      if read_en = '1' and count > 0 then
        data_out <= fifo_mem(read_ptr);
        read_ptr <= (read_ptr + 1) mod FIFO_DEPTH;
        count <= count - 1;
      end if;
    end if;
  end process;

  full <= '1' when count = FIFO_DEPTH else '0';
  empty <= '1' when count = 0 else '0';
end rtl;
Output
No direct console output; the FIFO stores and outputs data on signals with full and empty flags indicating status.
⚠️

Common Pitfalls

Common mistakes when coding a FIFO in VHDL include:

  • Not handling the full and empty conditions properly, causing data overwrite or invalid reads.
  • Incorrect pointer wrap-around logic, leading to out-of-range errors.
  • Not synchronizing read and write operations on the clock edge.
  • Forgetting to reset pointers and counters on reset.

Always use modulo arithmetic for pointers and check count limits before read/write.

vhdl
---- Wrong: No check for full before write
if write_en = '1' then
  fifo_mem(write_ptr) <= data_in;
  write_ptr <= write_ptr + 1; -- No modulo, no full check
end if;

---- Right: Check full and use modulo
if write_en = '1' and count < FIFO_DEPTH then
  fifo_mem(write_ptr) <= data_in;
  write_ptr <= (write_ptr + 1) mod FIFO_DEPTH;
  count <= count + 1;
end if;
📊

Quick Reference

Signal/ConceptDescription
fifo_memArray storing FIFO data elements
write_ptrIndex where new data is written
read_ptrIndex where data is read from
countNumber of elements currently in FIFO
fullFlag indicating FIFO is full
emptyFlag indicating FIFO is empty
write_enSignal to enable writing data
read_enSignal to enable reading data

Key Takeaways

Use pointers with modulo arithmetic to manage FIFO read and write positions safely.
Always check full and empty conditions before writing or reading to avoid data loss or invalid reads.
Reset pointers and counters properly to initialize the FIFO state.
Synchronize all operations on the clock edge for reliable behavior.
Use a counter to track the number of stored elements for easy full/empty detection.