← RTL Design Interviews

Interview Question · Code Reading

The Shift Register Written with Blocking Assignments

L0 FresherL1 Juniorblocking nonblockingsequential logic

The Question

The interviewer asks

This block is meant to be a three-stage shift register. What hardware does it really describe?

systemverilog
module shift3 (input logic clk, input logic d, output logic q);
  logic s1, s2;
  always_ff @(posedge clk) begin
    s1 = d;
    s2 = s1;
    q  = s2;
  end
endmodule
Reveal the Model Answer

It describes one flop, not three. A blocking assignment updates its variable at once, so s2 reads the new s1 and q reads the new s2. In one edge, d reaches q, so s1 and s2 are just wires. Write the three lines with <=. Then each right-hand side reads the value from before the edge, and you get three flops.

The Pipeline Written with Blocking Assignmentsd counts up from edge 2. Each line is printed after the edge has settled. With =, q equals d at every edge: one stage, not two.
01234567clkrst_nd0123456s10123456q0123456
  1. Cycle 2

    Reset is released after edge 1 and d becomes 1 before edge 2. At the edge, s1 = d runs first: s1 is 1 now. Then q = s1 reads that new 1.

  2. Cycle 3

    d is 2 and q is 2 in the same edge. The second stage never sees the old s1; nothing in the block keeps it.

  3. Cycle 5

    Every edge repeats the same thing: q follows d with one edge of delay, exactly as if s1 were a wire. That is what synthesis built: eight flops and no s1 register.

Measured in lesson R2.1 on a two-stage version. With =, q follows d at every edge, so s1 is only a wire.

The blocking and nonblocking versions side by side, fed one pulse. Yosys builds 1 flop for the blocking one.

RUNIcarus Verilog · in your browser
Edit the code, then run it
Expected: edge 1: blocking q=1 nonblocking q=x edge 2: blocking q=0 nonblocking q=x edge 3: blocking q=0 nonblocking q=1

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Fresher)

A good fresher answer steps through the three lines at one clock edge. It shows that d reaches q in that same edge.

Cross-Questions

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

WhyWhat IfProve ItBreak ItCompare

  1. The Shift Register Written with Blocking Assignments
  2. WhyWhy Nonblocking Assignments Model FlopsL1 Junior

    Why do nonblocking assignments model flip-flops correctly?

    Reveal the Model Answer

    Real flops on one clock all sample their inputs at the same edge, before any of them changes. A nonblocking assignment copies that. Its right-hand side is read when the statement runs, and the update happens later, in the NBA region. So every flop sees the values from before the edge, whatever order the code runs in.

    What Each Version BuildsThe nonblocking version has two flops in series: d into s1, s1 into q. The blocking version has one flop: d into q, with s1 a name for the wire between d and the flop.
    What each version buildsThe nonblocking version has two flops in series: d into s1, s1 into q. The blocking version has one flop: d into q, with s1 a name for the wire between d and the flop. manager d[7:0] input bridge s1 8 flops (only with <=) bridge q 8 flops completer q[7:0] output edge kedge k+1
    1. Nonblocking, edge k

      d = 3 is captured into s1. q still holds the value s1 had before the edge.

      Follow the calls, values and waits
      1. data 3: d[7:0] → s1
    2. Nonblocking, edge k+1

      The 3 moves from s1 to q. Two edges after it arrived, 3 is at the output.

      Follow the calls, values and waits
      1. data 3: s1 → q
      2. data 3: q → q[7:0]
    3. Blocking, any edge

      s1 is assigned and read in the same statement list, so it is a wire; d reaches q in one edge. The middle box is not built.

      Follow the calls, values and waits
      1. data 3: d[7:0] → s1
      2. data 3: s1 → q
      3. data 3: q → q[7:0]
    Read the diagram as text
    • d[7:0]: input
    • s1: 8 flops (only with <=)
    • q: 8 flops
    • q[7:0]: output
    • d[7:0] → s1: edge k
    • s1 → q: edge k+1
    • q → q[7:0]

    Measured: 16 flops with nonblocking assignments, 8 with blocking ones, on this flow.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "<= adds a small delay, so the read happens first."

    There is no delay. Time does not move; the update is scheduled for a later region of the same time step.

    Source IEEE 1800-2017 §10.4.2

  3. What IfSwapping Two RegistersL0 FresherL1 Junior

    What if you swap two registers at a clock edge, once with = and once with <=? What does this print?

    systemverilog
    module tb;
      logic clk = 0;
      logic [3:0] a = 4'd1, b = 4'd2;   // blocking pair
      logic [3:0] c = 4'd1, d = 4'd2;   // nonblocking pair
      always @(posedge clk) begin
        a = b;
        b = a;
      end
      always @(posedge clk) begin
        c <= d;
        d <= c;
      end
      initial begin
        #5 clk = 1; #1;
        $display("blocking:    a=%0d b=%0d", a, b);
        $display("nonblocking: c=%0d d=%0d", c, d);
      end
    endmodule
    
    Reveal the Model Answer

    With =, a becomes 2 first, then b copies the new a, so both are 2. With <=, both right-hand sides read the old values, so c and d swap to 2 and 1. No temporary variable is needed. This is the shortest proof of the old-value rule.

    RUNIcarus Verilog · in your browser
    Edit the code, then run it
    Expected: blocking: a=2 b=2 nonblocking: c=2 d=1

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "You need a temporary variable to swap two registers."

    With <= both reads happen before either update, so the swap works in one edge. The run shows it.

    Source Measured: the run on this question, Icarus Verilog 12

  4. CompareReversed Blocking Order vs NonblockingL1 JuniorL2 Mid-Level

    Writing q = s2; s2 = s1; s1 = d; also gives three flops. Compare it with the nonblocking version. Why not use it?

    Reveal the Model Answer

    Both give three flops in this block. The reversed version only works because of the line order, so a later edit can break it silently. The blocking writes also update at once, so another block reading s1 at the same edge has a race. With <= the order does not matter and readers elsewhere see the old value.

    Self-Check

    Tick each key point you covered in your answer.

    Half-Truth

    "Synthesis gave three flops, so the style does not matter."

    The netlist is right today. The race with other blocks shows only in simulation, and it depends on which block the simulator runs first.

    Source Cummings, Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill! (SNUG 2000)

  5. Break ItOne Register Written from Two BlocksL2 Mid-Level

    How do you break this further: what happens if two always_ff blocks both write q?

    Reveal the Model Answer

    A flop has one D input, so two writers describe hardware that cannot exist. In simulation, the last write in a time step wins, which depends on block order. always_ff makes this a compile error, because a variable it writes may not be written anywhere else. Plain always @(posedge clk) gives no such check.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "The two blocks never write in the same cycle, so it is fine."

    Synthesis cannot see that promise. It still needs one driver per flop, and tools reject or mis-merge the two drivers.

    Source IEEE 1800-2017 §9.2.2.4

  6. Prove ItSolve R2.1.1: The Pipeline That Ran AheadSimulator-graded

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

    Open Problem R2.1.1

What People Get Wrong

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

Misconception

"Inside always_ff, every variable becomes a flop."

always_ff names the intent. Synthesis still builds what the assignments say. The twin synthesizes one flop, and q rises after the first edge.

Run It

The snippet with a bench that sends one pulse, and the fix with <=.

RUNIcarus Verilog · in your browser
Edit the code, then run it
Expected: q first rose after edge 1 FAIL: always_ff did not make three flops; blocking writes built one flop
See the Fix
module shift3 (input logic clk, input logic d, output logic q);
  logic s1, s2;
  always_ff @(posedge clk) begin
    s1 <= d;
    s2 <= s1;
    q  <= s2;
  end
endmodule
module tb;
  logic clk = 0, d = 0, q;
  shift3 dut (.clk(clk), .d(d), .q(q));
  always #5 clk = ~clk;
  int first = -1;
  initial begin
    d = 1; @(posedge clk); #1 d = 0;
    for (int e = 1; e <= 4; e++) begin
      if (q === 1'b1 && first < 0) first = e;
      @(posedge clk); #1;
    end
    $display("q first rose after edge %0d", first);
    if (first == 1) $display("FAIL: always_ff did not make three flops; blocking writes built one flop");
    if (first == 3) $display("PASS: q rose after the third edge");
    $finish;
  end
endmodule

Prints: q first rose after edge 3 PASS: q rose after the third edge

Half-Truth

"Just reverse the three lines and blocking is fine."

Reversed, this one block happens to work. The order is now part of the design, and any other block that reads s1 at the same edge races with it.

Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 8.1.4.2 Improper use of blocking assignments in sequential flip-flop behavior

Buzzword Without Mechanism

"Nonblocking assignments run in parallel, like hardware."

They run one by one, in order. Only the updates wait for the NBA region, so every right-hand side reads the values from before the edge.

Source IEEE 1800-2017 §10.4.2

Learn It, Then Prove It