CodiodeCodiode
Home
Problem Solving
Skill Tracks
My Assignments
Contests
Leaderboard
Community
Settings
Codiode/Problems/Sequential Logic

FIFO Empty Condition Logic

HardVerilog / SystemVerilogBuild

Asynchronous FIFOs pass data safely between independent clock domains. To prevent reading invalid data (underflow), the read clock domain must accurately detect when the FIFO is empty. This is achieved by comparing the read pointer with a synchronized version of the write pointer.

The module maintains an internal 4-bit binary read pointer and outputs a 4-bit Gray-coded read pointer. When a read is requested (rinc is 1) and the FIFO is not empty, the internal binary pointer increments. The next Gray pointer is calculated from this next binary value. The FIFO is considered empty when the next Gray read pointer exactly matches the synchronized Gray write pointer (wq2_wptr).

The module is driven by the read clock (rclk) on the positive edge. An asynchronous active-low reset (rrst_n) initializes the internal binary pointer and the output Gray pointer (rptr) to 0, and asserts the empty flag (rempty to 1). Read requests must be ignored if rempty is currently 1.

Cycle-by-cycle execution trace: • Cycle 1: rrst_n=0 → rptr=0, rempty=1 • Cycle 2: rrst_n=1, rinc=1, wq2_wptr=0 → rptr=0, rempty=1 (read ignored because empty) • Cycle 3: rinc=0, wq2_wptr=1 → rptr=0, rempty=0 (write syncs in, FIFO no longer empty) • Cycle 4: rinc=1, wq2_wptr=1 → rptr=1, rempty=1 (read executes, FIFO empty again) • Cycle 5: rinc=0, wq2_wptr=1 → rptr=1, rempty=1 (hold state)

{ "signal": [
  { "name": "rclk",     "wave": "p...." },
  { "name": "rrst_n",   "wave": "01..." },
  { "name": "rinc",     "wave": "01010" },
  { "name": "wq2_wptr", "wave": "=====", "data": ["0", "0", "1", "1", "1"] },
  {},
  { "name": "rempty",   "wave": "1.01." },
  { "name": "rptr",     "wave": "=====", "data": ["0", "0", "0", "1", "1"] }
], "head": { "text": "Cycle 2: Read ignored. Cycle 3: Write syncs in. Cycle 4: Read executes." } }

| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | rclk | input | 1 | Positive-edge triggered read domain clock | | rrst_n | input | 1 | Asynchronous active-low reset | | rinc | input | 1 | Read request enable | | wq2_wptr | input | 4 | Synchronized write pointer in Gray code | | rempty | output | 1 | Registered empty flag; 1 when FIFO is empty | | rptr | output | 4 | Registered Gray-coded read pointer |

Constraints

  • The design must use posedge rclk for synchronous logic and negedge rrst_n for asynchronous resets.
  • On reset, rempty must be 1 and rptr must be 4'b0000.
  • If rempty is 1, any assertion of rinc must be ignored (the internal pointer must not increment).
  • The rempty flag must be evaluated combinationally using the *next* Gray read pointer, but the output rempty itself must be a registered signal updated on posedge rclk.
  • Both rempty and rptr must be registered outputs.

Topics

FIFOGray CodeCDCPointers

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.

Sign in to solveSee what Pro unlocks

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.

Related problems

  • Basic D Flip FlopEasy
  • Debug: Missing Edge in Sensitivity ListMedium
  • Read After Write Hazard DetectionEasy
  • Parameterized Interface with ModportsHard
  • Struct Array PipelineHard
  • T Flip Flop from D Flip Flop TemplateEasy
  • Recursive Generate Reduction TreeHard
  • Four Stage Shift RegisterEasy

Browse all problems · Learning tracks