Y. Harshavardhan Reddy
B.Tech – Electronics and Communication Engineering
This project presents the design and functional verification of a parameterized synchronous First-In First-Out (FIFO) memory using Verilog HDL. The FIFO operates in a single clock domain and supports configurable depth and data width. A circular buffer architecture is employed using read and write pointers with an extra most significant bit (MSB) to accurately detect full and empty conditions. The design is fully synthesizable and verified using a structured, task-based testbench.
Synchronous FIFO, Verilog HDL, RTL Design, Circular Buffer, Full and Empty Logic, Digital Design
FIFO memories are fundamental components in digital systems and are widely used for buffering, flow control, and data synchronization between modules. A synchronous FIFO is used when both read and write operations occur in the same clock domain.
This project aims to design a clean and reusable synchronous FIFO using parameterized Verilog HDL, focusing on core RTL concepts such as pointer arithmetic, memory indexing, and status flag generation.
| Signal / Parameter | Description |
|---|---|
| FIFO_DEPTH | Number of FIFO entries |
| DATA_WIDTH | Width of each data word |
| clk | System clock |
| rst_n | Active-low asynchronous reset |
| cs | Chip select |
| wr_en | Write enable |
| rd_en | Read enable |
| data_in | Input data bus |
| data_out | Output data bus |
| empty | FIFO empty flag |
| full | FIFO full flag |
The following block diagram illustrates the top-level architecture of the synchronous FIFO.
It shows the control signals, data interface, and status flags used in the design.
clk: System clock (single clock domain)rst_n: Active-low asynchronous resetcs: Chip selectwr_en: Write enablerd_en: Read enabledata_in: Input data busdata_out: Output data busfull: FIFO full indicatorempty: FIFO empty indicator
The lower bits are used for addressing FIFO memory, while the MSB helps differentiate between full and empty states.
A write operation occurs when:
cs = 1wr_en = 1full = 0
On a successful write:
- Input data is stored at the write pointer location
- The write pointer is incremented
A read operation occurs when:
cs = 1rd_en = 1empty = 0
On a successful read:
- Data is read from FIFO memory
- The read pointer is incremented
The FIFO is considered empty when no valid data is available to be read.
This occurs when the read pointer and write pointer are equal.
Mathematically: empty = (read_pointer == write_pointer);
- Initially, both pointers are reset to zero
- Each write operation increments the write pointer
- Each read operation increments the read pointer
- When both pointers match, all written data has been read
The following diagram illustrates different FIFO states and the empty condition.

The FIFO is considered full when no more data can be written without overwriting unread data.
To detect this condition, an extra MSB is used in both read and write pointers.
The FIFO becomes full when: full = (read_pointer == {~write_pointer[MSB], write_pointer[LSBs]});
- Lower bits of both pointers match (same memory location)
- MSBs are different, indicating a complete wrap-around
- This technique differentiates full and empty conditions even when pointer values appear equal
The following diagram shows how the FIFO reaches the full state.

- Clock generation
- Parameterized FIFO instantiation
- Task-based read and write operations
- Multiple verification scenarios
- Console-based result monitoring
- Basic write and read operations
- Sequential write followed by sequential read
- FIFO full condition
- FIFO empty condition
- Verilog HDL
- Vivado Simulator
- Data buffering
- Producer–consumer systems
- SoC interconnects
- Streaming data interfaces
- RTL design practice
This project strengthened understanding of:
- FIFO architecture
- Pointer-based memory management
- Full and empty flag generation
- Parameterized RTL design
- Testbench development using tasks
The project successfully demonstrates the design of a robust synchronous FIFO using Verilog HDL. The modular and parameterized approach makes the FIFO scalable and reusable for real-world digital systems. This project serves as a strong foundation for advanced FIFO designs and SoC-level buffering solutions.
- Asynchronous (dual-clock) FIFO
- Almost-full and almost-empty flags
- Gray-code pointer synchronization
- Formal verification
- FPGA synthesis and timing analysis
