FIFO Simultaneous Read Write when Empty
High-performance pipelines often use FIFOs to buffer data between stages. However, a standard FIFO introduces a one-cycle stall when a consumer attempts to read exactly as the FIFO becomes empty, even if a producer is writing new data in the same cycle. A bypass FIFO (sometimes called a fall-through FIFO) solves this by forwarding the incoming write data directly to the read port without writing it to memory.
The bypass_fifo module maintains a circular buffer of 8-bit words with a depth of exactly 8. Under normal operation, it functions as a standard synchronous FIFO. Data is written to memory when write_en is asserted, and read from memory into a registered output when read_en is asserted.
When the FIFO is empty and a simultaneous read and write occur, the module enters bypass mode. The write data is immediately passed to the output register, bypassing the memory array entirely, saving a clock cycle and preventing a pipeline stall.
Timing and Reset Rules
- Clock edge:
posedge clk - Reset type: Asynchronous, active-low (
rst_n) - Reset values:
empty= 1,full= 0,data_out= 8'h00. Internal pointers reset to 0. - Bypass condition: If
emptyis 1, and bothwrite_enandread_enare 1,data_outupdates todata_inon the next clock edge. The internal read/write pointers do not increment, andemptyremains 1. - Simultaneous read/write when full: If
fullis 1, and bothwrite_enandread_enare 1, both operations succeed. The read pointer increments, the write pointer increments, andfullremains 1. The new data is written into the location just vacated by the read. - Standard write: If
write_en= 1 andfull= 0, the write pointer increments and data is stored. - Standard read: If
read_en= 1 andempty= 0, the read pointer increments anddata_outupdates with the read data on the next clock edge. - Invalid operations: Read when empty (and
write_en= 0) does nothing to pointers, anddata_outholds its previous value. Write when full (andread_en= 0) does nothing to pointers.
Worked Trace
Cycle 1: rst_n=0 → empty=1, full=0, data_out=8'h00 Cycle 2: rst_n=1, write_en=0, read_en=0 → empty=1, full=0, data_out=8'h00 Cycle 3: write_en=1, read_en=1, data_in=8'hAA → empty=1, full=0, data_out=8'h00 (Bypass detected) Cycle 4: write_en=1, read_en=0, data_in=8'hBB → empty=1, full=0, data_out=8'hAA (Write BB; bypass data AA appears) Cycle 5: write_en=0, read_en=1 → empty=0, full=0, data_out=8'hAA (Read BB; FIFO was not empty) Cycle 6: write_en=1, read_en=1, data_in=8'hCC → empty=1, full=0, data_out=8'hBB (Bypass detected; read data BB appears) Cycle 7: write_en=0, read_en=0 → empty=1, full=0, data_out=8'hCC (Bypass data CC appears)
Diagram
{ "signal": [
{ "name": "clk", "wave": "p........" },
{ "name": "rst_n", "wave": "01......." },
{ "name": "write_en", "wave": "0.1101..." },
{ "name": "read_en", "wave": "0.1011..." },
{ "name": "data_in", "wave": "x.=.=x=..", "data": ["AA", "BB", "CC"] },
{},
{ "name": "empty", "wave": "1..01...." },
{ "name": "data_out", "wave": "=.=.=.=.=", "data": ["00", "AA", "AA", "BB", "CC"] }
], "head": { "text": "Bypass on cycle 3 and 6; normal write/read on 4/5." } }Port Table
| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset; resets pointers, sets empty to 1, full to 0, data_out to 0 | | write_en | input | 1 | Write enable; active high | | read_en | input | 1 | Read enable; active high | | data_in | input | 8 | Data input to be written to the FIFO | | data_out | output | 8 | Data output read from the FIFO; registered on posedge clk | | empty | output | 1 | High when the FIFO contains no data | | full | output | 1 | High when the FIFO contains 8 elements |
Constraints
- The FIFO depth must be exactly 8 elements.
data_outmust be a registered output, updating only onposedge clkor asynchronous reset.- The internal pointers must not change during a bypass operation (when
empty=1,write_en=1,read_en=1). - If
full=1, a simultaneous read and write must be permitted without dropping the write or corrupting unread data. - Underflow and overflow attempts must be ignored, preserving the current state and pointers.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.