CodiodeCodiode
Home
Problem Solving
Skill Tracks
My Assignments
Contests
Leaderboard
Community
Settings
Codiode/Problems/Memory Design

Pointer Wrapping with MSB Toggle

MediumVerilog / SystemVerilogBuild

Synchronous FIFOs require a mechanism to distinguish between completely full and completely empty states, as the read and write pointers will point to the exact same physical memory address in both scenarios. The industry-standard solution to this ambiguity uses an extra Most Significant Bit (MSB) in the pointers to track the wrap-around status of the memory array.

The module maintains two pointers, a write pointer and a read pointer. Each pointer increments by 1 when its respective enable signal is asserted and the operation is valid. The pointers are ADDR_WIDTH + 1 bits wide. The lower ADDR_WIDTH bits represent the physical memory address, while the MSB acts as a toggle bit.

The FIFO is empty when both pointers are exactly equal across all bits. The FIFO is full when the lower ADDR_WIDTH bits are equal, but the MSB toggle bits are different. This indicates the write pointer has wrapped around exactly one more time than the read pointer.

Positive-edge triggered clock (clk). Asynchronous active-low reset (rst_n). On reset, both pointers become 0, empty becomes 1, and full becomes 0.

Cycle 1: rst_n=0 → wr_ptr=0, rd_ptr=0, full=0, empty=1 Cycle 2: rst_n=1, wr_en=1, rd_en=0 → wr_ptr=1, rd_ptr=0, full=0, empty=0 Cycle 3: wr_en=1, rd_en=0 → wr_ptr=2, rd_ptr=0, full=0, empty=0 Cycle 4: wr_en=1, rd_en=0 → wr_ptr=3, rd_ptr=0, full=0, empty=0 Cycle 5: wr_en=1, rd_en=0 → wr_ptr=4, rd_ptr=0, full=1, empty=0 Cycle 6: wr_en=1, rd_en=0 → wr_ptr=4, rd_ptr=0, full=1, empty=0 (overflow prevented)

{ "signal": [
  { "name": "clk",    "wave": "p......" },
  { "name": "rst_n",  "wave": "01....." },
  { "name": "wr_en",  "wave": "01...0." },
  { "name": "rd_en",  "wave": "0......" },
  {},
  { "name": "wr_ptr", "wave": "=.====.", "data": ["0","1","2","3","4"] },
  { "name": "rd_ptr", "wave": "=......", "data": ["0"] },
  { "name": "full",   "wave": "0....1." },
  { "name": "empty",  "wave": "10....." }
], "head": { "text": "Cycle-by-cycle trace of writing to a full state (ADDR_WIDTH=2)" } }

| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset; pointers reset to 0, empty to 1, full to 0 | | wr_en | input | 1 | Write enable; increments wr_ptr on posedge clk unless full | | rd_en | input | 1 | Read enable; increments rd_ptr on posedge clk unless empty | | wr_ptr | output | ADDR_WIDTH+1 | Write pointer including MSB toggle bit | | rd_ptr | output | ADDR_WIDTH+1 | Read pointer including MSB toggle bit | | full | output | 1 | Asserted when FIFO is full (MSBs differ, lower bits match) | | empty| output | 1 | Asserted when FIFO is empty (all bits match) |

Constraints

  • The ADDR_WIDTH must be parameterized with a default value of 3.
  • The testbench will override ADDR_WIDTH during testing; you must use it to size your registers and logic dynamically.
  • wr_ptr and rd_ptr must be exactly ADDR_WIDTH + 1 bits wide.
  • Clock edge is posedge, reset is asynchronous active-low.
  • Do not increment wr_ptr if full is 1, even if wr_en is 1 (overflow protection).
  • Do not increment rd_ptr if empty is 1, even if rd_en is 1 (underflow protection).
  • full and empty must reflect the state of the pointers in the current clock cycle.

Topics

FIFOMemoryPointers

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

  • Shift Register Based FIFOMedium
  • Asymmetric Data Width FIFOHard
  • True Dual Port RAM 2RWHard
  • Circular Buffer with OverwriteMedium
  • Synchronous Single Port RAMEasy
  • Stack Overflow and Underflow ProtectionMedium
  • Circular Buffer Pointer MathMedium
  • Read First Single Port RAMMedium

Browse all problems · Learning tracks