Shift Register Based FIFO
For very shallow queue depths, shift registers consume fewer routing resources and logic area than pointer-based block RAM FIFOs. A shift-register FIFO avoids managing separate wrapping read and write pointers by shifting data through an array from a fixed entrance to a dynamically multiplexed exit.
The module maintains an internal array of DEPTH registers. Data always enters at index 0. On a valid write, all existing data shifts to the next higher index. A counter tracks the number of valid elements in the FIFO. The output dout is continuously driven by the element at index count - 1 (the oldest data). On a valid read, the counter decrements, exposing the next oldest data on dout without needing to shift the internal array.
- Clock edge: posedge
clk - Reset: synchronous active-low
rst_n - On reset,
countbecomes 0, all data registers clear to 0,emptybecomes 1, andfullbecomes 0.
Worked Trace (DEPTH=4): Cycle 1: rst_n=0 → count=0, empty=1, full=0, dout=0 Cycle 2: rst_n=1, wr_en=1, din=10 → count=1, empty=0, data[0]=10, dout=10 Cycle 3: wr_en=1, din=20 → count=2, data[0]=20, data[1]=10, dout=10 Cycle 4: wr_en=1, din=30 → count=3, data[0]=30, data[1]=20, data[2]=10, dout=10 Cycle 5: rd_en=1, wr_en=0 → count=2, data array holds, dout=20 (data[1]) Cycle 6: rd_en=1, wr_en=1, din=40 → count=2, data[0]=40, data[1]=30, data[2]=20, dout=30 (data[1]) Cycle 7: rd_en=1, wr_en=0 → count=1, data array holds, dout=40 (data[0]) Cycle 8: rd_en=1, wr_en=0 → count=0, empty=1, dout=0
{ "signal": [
{ "name": "clk", "wave": "p......." },
{ "name": "rst_n", "wave": "01......" },
{ "name": "wr_en", "wave": "01110100" },
{ "name": "din", "wave": "x===x=xx", "data": ["10","20","30","40"] },
{ "name": "rd_en", "wave": "00001111" },
{ "name": "count", "wave": "========", "data": ["0","1","2","3","2","2","1","0"] },
{ "name": "dout", "wave": "========", "data": ["0","10","10","10","20","30","40","0"] }
], "head": { "text": "Cycle-by-cycle behavior of the shift-register FIFO" } }| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Synchronous active-low reset; all outputs and internal registers go to 0 | | wr_en | input | 1 | Write enable | | rd_en | input | 1 | Read enable | | din | input | WIDTH | Data input | | dout | output | WIDTH | Data output; continuously outputs the oldest valid data, or 0 if empty | | empty | output | 1 | Asserted when the FIFO contains no valid data | | full | output | 1 | Asserted when the FIFO contains DEPTH valid elements |
Constraints
- Clock edge and reset polarity: posedge
clk, synchronous active-lowrst_n. - Output values on reset:
dout,full, and all internal registers must be 0;emptymust be 1. - Priority when full or empty: A read on empty is ignored. A write on full without a simultaneous read is ignored.
- Simultaneous read and write: If full, the write and read both succeed;
countremainsDEPTH. If empty, the write succeeds, the read is ignored;countbecomes 1. Otherwise, data shifts in, a value is consumed, andcountremains unchanged. - Output
doutmust combinationally output the oldest valid data (at indexcount - 1), or 0 if empty. - On a valid write, data at index
ishifts toi+1, anddinis written to index 0. - On a valid read without a write, the internal data array must not shift. Only the valid counter decrements.
- Module must be parameterized with
WIDTH(default 8) andDEPTH(default 4).
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.