← RTL Design Interviews

Interview Question · Project Defence

Defending the FIFO You Designed

L1 JuniorL2 Mid-LevelL3 Seniorfifoproject defenceverification

The Question

The interviewer asks

Walk me through the FIFO in your last project. What were the rare cases, and how do you know it handles them?

Reveal the Model Answer

Start with the spec: depth and why, widths, and what happens on a write at full and a read at empty. Then name the corners: write at full, read at empty, both at the same edge, wrap-around, and reset with data inside. For each, say what the design does and which test or assertion proves it. Finish with what you would add next, such as formal checks on the flags.

The Same Bench with 3-bit PointersEdges 2 to 13 of the lab bench after the fix, DEPTH 4. The top pointer bit is the wrap bit.
01234567891011clkwrite_enread_enwptr001010011100101110rptr000001010011100101110fullempty
  1. Cycle 3

    Edge 5: the write pointer reaches 100. Its address bits, 00, equal the read pointer's, but its wrap bit is 1: full rises.

  2. Cycle 4

    Edge 6: the fifth push is refused, so the write pointer stays at 100 and nothing is overwritten.

  3. Cycle 8

    Edge 10: the fourth read brings the read pointer to 100 as well. Equal pointers: empty.

  4. Cycle 10

    Edge 12: a push and a pop in one cycle. Both pointers move, so the FIFO still holds one word.

Measured in lesson R5.2: full, a refused push, empty, then a push and a pop together. Each event is a corner to defend.

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Junior)

A good junior answer states the depth and how it was chosen. It then lists the full and empty corners without being asked.

Cross-Questions

Where the interviewer goes next. Open a node to practise that follow-up.

What IfProve ItBreak ItCompareScale It

  1. Defending the FIFO You Designed
  2. Break ItA Read and a Write at the Same Edge When FullL1 JuniorL2 Mid-Level

    The FIFO is full, and a read and a write arrive at the same edge. What should happen?

    Reveal the Model Answer

    It is a design choice, and the spec must state it. The simple rule refuses the write, because full was high before the edge. A more efficient rule accepts it, because the read frees a slot in the same cycle. The second rule makes full depend on rd_en, which can create a long path back into the reader.

    Self-Check

    Tick each key point you covered in your answer.

    Spec Misquote

    "Both are always accepted."

    Only if the design says so. The R5.2 FIFO refuses the write, and a bench that expects otherwise reports a false bug.

    Source Lesson R5.2 and problem R5.2.2 brief: a write is accepted only when write_en is 1 and full is 0, a read only when read_en is 1 and empty is 0, both on the flags before the edge; a refused write changes nothing

  3. What IfA Read and a Write at the Same Edge When EmptyL1 JuniorL2 Mid-Level

    What if the FIFO is empty and a read and a write arrive at the same edge?

    Reveal the Model Answer

    With the usual rule, the read is refused, because empty was high before the edge, and the write goes in. The word comes out one cycle later. A first-word-fall-through design shows the new word on the output soon after. It still counts as read only when rd_en is high and the FIFO is not empty.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "The read returns the word being written."

    Only a bypass path would do that, and most FIFOs do not have one. Without it the read sees an empty FIFO.

    Source Lesson R5.2 and problem R5.2.2 brief: a write is accepted only when write_en is 1 and full is 0, a read only when read_en is 1 and empty is 0, both on the flags before the edge; a refused write changes nothing

  4. CompareFIFO Assertions Versus a ScoreboardL2 Mid-Level

    Compare checking your FIFO with assertions inside the RTL and with a scoreboard in the testbench.

    Reveal the Model Answer

    Assertions in the RTL check local rules every cycle: never full and empty together, and no pointer move on a refused write. They also go to formal tools. A scoreboard checks the data end to end: every word out equals the word in, in order. The two catch different bugs, so a solid FIFO has both.

    Three Pieces, Two ReadersArrows show which tool reads which code. The checks inside the design travel with it; the bound rules live in a bench file.
    Three pieces, two readersArrows show which tool reads which code. The checks inside the design travel with it; the bound rules live in a bench file. component Synthesizer defines SYNTHESIS design FIFO logic main.sv design Checks inside `ifndef SYNTHESIS component Simulator Verilator, --assert bench Bound rules bind sync_fifo ... readsreadsreadsreads
    1. Synthesize

      SYNTHESIS is defined, so the synthesizer reads the logic and skips the guarded checks. The bound rules are in another file and never reach it.

    2. Run

      The simulator defines nothing. It compiles the logic, the checks inside it and any bound rules, and runs them all.

    Read the diagram as text
    • Synthesizer: defines SYNTHESIS
    • FIFO logic: main.sv
    • Checks inside: `ifndef SYNTHESIS
    • Simulator: Verilator, --assert
    • Bound rules: bind sync_fifo ...
    • FIFO logic → Synthesizer: reads
    • FIFO logic → Simulator: reads
    • Checks inside → Simulator: reads
    • Bound rules → Simulator: reads

    A check inside the design goes wherever the design goes. A bound rule goes only where a bench attaches it.

    Self-Check

    Tick each key point you covered in your answer.

    Half-Truth

    "If the scoreboard passes, the flags are right."

    A scoreboard sees only the data. A full flag that rises a cycle early loses throughput and never corrupts data, so the scoreboard stays quiet.

    Source Mehta, SystemVerilog Assertions and Functional Coverage (3rd ed., 2020) ch. 2.7-2.9, as cited in lesson R7.2

  5. Prove ItSolve R5.2.2: The FIFO That Overflowed at FullSimulator-graded

    Show it, don't just say it: this Silicon Lab problem is graded by the simulator.

    Open Problem R5.2.2

  6. Scale ItResetting a FIFO That Holds DataL2 Mid-LevelL3 Senior

    Asked if they mention reset

    How do you reset a FIFO that still holds data, and what changes for an asynchronous FIFO?

    Reveal the Model Answer

    In one clock domain, resetting both pointers empties the FIFO. The RAM contents can stay, because nothing reads them. In an asynchronous FIFO, each side resets in its own domain. For a few cycles, one side may see the other's old pointer. Hold both sides in reset together, or block traffic until both resets have released.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Reset the RAM too, or old data comes out."

    Old data is never read, because empty is true after reset. Resetting a RAM costs area and is often impossible with library memories.

    Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 8.3 Modeling memory devices such as RAMs

What People Get Wrong

Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.

Missed Corner

"Writes at full are blocked, so that corner is safe."

Often only the pointer is blocked. If the RAM write is not, a refused write overwrites the oldest word. The twin shows it.

Run It

Four words in a 4-entry FIFO, then a fifth word offered at full.

RUNIcarus Verilog · in your browser
Edit the code, then run it
Expected: full=1, first word out=ee FAIL: a refused write at full still wrote the RAM and replaced the oldest word
See the Fix
// A 4-entry FIFO, written at full while the reader is idle.
module fifo4 (
  input  logic       clk, rst_n, wr_en, rd_en,
  input  logic [7:0] wr_data,
  output logic [7:0] rd_data,
  output logic       full, empty
);
  logic [7:0] mem [0:3];
  logic [2:0] wptr, rptr;
  assign empty   = (wptr == rptr);
  assign full    = (wptr[2] != rptr[2]) && (wptr[1:0] == rptr[1:0]);
  assign rd_data = mem[rptr[1:0]];
  always_ff @(posedge clk)
    if (wr_en && !full) mem[wptr[1:0]] <= wr_data;    // only an accepted write touches the RAM
  always_ff @(posedge clk or negedge rst_n)
    if (!rst_n) begin wptr <= 0; rptr <= 0; end
    else begin
      if (wr_en && !full)  wptr <= wptr + 1'b1;
      if (rd_en && !empty) rptr <= rptr + 1'b1;
    end
endmodule
module tb;
  logic clk = 0, rst_n = 0, wr_en = 0, rd_en = 0, full, empty;
  logic [7:0] wr_data = 0, rd_data;
  always #5 clk = ~clk;
  fifo4 dut (.*);
  task automatic put(input logic [7:0] d); @(negedge clk); wr_en = 1; wr_data = d; @(posedge clk); #1 wr_en = 0; endtask
  initial begin
    #12 rst_n = 1;
    put(8'ha0); put(8'ha1); put(8'ha2); put(8'ha3);
    put(8'hee);                                  // offered at full: must be refused and lost
    @(negedge clk);
    $display("full=%b, first word out=%h", full, rd_data);
    if (rd_data == 8'ha0) $display("PASS: the refused write left the oldest word in place");
    $finish;
  end
endmodule

Prints: full=1, first word out=a0 PASS: the refused write left the oldest word in place

Delivery

Describes the block diagram for five minutes and never mentions a test.

The question was how you know it works. The interviewer is grading evidence, not the drawing.

Half-Truth

"We ran random tests, so all corners were covered."

Random traffic rarely holds a FIFO at full while writing. Without coverage of those states, nobody knows if they were hit.

Source Mehta, ASIC/SoC Functional Design Verification (2018) ch. 7.1 Difference between code coverage and functional coverage

Learn It, Then Prove It