← Design Verification Interviews

Interview Question · Code Writing

A Scoreboard That Calls a C Model

L2 Mid-Leveldpiscoreboardreference models

The Question

The interviewer asks

An input monitor and an output monitor both send transactions to your scoreboard. A C model gives model_read(h, addr), the data the DUT should return. Write the scoreboard methods: where do you call the model, and what do you compare?

Reveal the Model Answer

Call the model when the input monitor reports an accepted request, using that request's fields. Push the prediction into an expected queue. When the output monitor reports a response, pop the oldest prediction and compare. Never predict from the response itself: if the DUT corrupts the echoed address, the model agrees with the bug. Create the handle in the constructor or build phase, and check the queue is empty at the end.

Self-Check

Tick each key point you covered in your answer.

What Interviewers Listen For (Mid-Level)

Feeds the model from the input side, keeps an expected queue, and compares on the output side.

Cross-Questions

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

What IfProve ItCompareScale It

  1. A Scoreboard That Calls a C Model
  2. What IfA C Model with Out-of-Order ResponsesL2 Mid-LevelL3 Senior

    Asked if responses can come back out of order

    What if the DUT may return responses out of order, matched by an ID?

    Reveal the Model Answer

    A single queue would compare the wrong pairs. Store predictions in an associative array keyed by ID, each holding a queue for repeated IDs. On a response, look up its ID, pop the oldest prediction for it, and compare. At the end, every queue must be empty.

    Self-Check

    Tick each key point you covered in your answer.

    Half-Truth

    "Sort the responses back into order, then use one queue."

    The scoreboard cannot know the order until every response arrives. Matching by ID checks each response as soon as it appears.

  3. Scale ItIntegrating an Architecture Model at Subsystem LevelL3 Senior

    The architecture team owns a C++ model of the whole subsystem. How do you use it as the scoreboard's reference without forking it?

    Reveal the Model Answer

    Wrap it behind a thin, versioned DPI layer owned by verification: transaction in, predicted transactions out, one handle per instance, plus reset. Feed it from monitors, never drivers, so it predicts from what the DUT actually received. Agree on where the model is untimed, such as ordering between independent streams, and compare there by key rather than by cycle.

    Self-Check

    Tick each key point you covered in your answer.

    What Interviewers Listen For (Senior)

    A good senior answer separates the shared model from the wrapper that verification owns. It says exactly where the comparison must allow differences in order.

    Wrong Altitude

    Copies the model into the verification repository and patches it to match the RTL.

    The model then stops being independent: it quietly learns the RTL's bugs, and the architecture fixes never arrive.

  4. CompareA C Model Compared with a SystemVerilog ModelL2 Mid-Level

    Compare a C reference model behind DPI with a reference model written as a SystemVerilog class.

    Reveal the Model Answer

    A C model can be the architecture team's own code, so verification checks against an independent source. It costs a second language, a boundary and a second debug flow. A SystemVerilog model debugs in one tool and sees four-state values. Choose C when the model already exists or the algorithm is heavy; otherwise keep it in SystemVerilog.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "C models are always faster."

    For small work, the SystemVerilog version can be faster. Our probe ran the same CRC in 64 ms in SystemVerilog and 120 ms through DPI.

    Source Measured on a local Verilator 5.052 build with g++ at -O0, 2026-11-08 (6.4 million CRC byte steps)

  5. Prove ItShowing the Scoreboard Can FailL2 Mid-Level

    Prove it: how do you show that this scoreboard would catch a wrong DUT response?

    Reveal the Model Answer

    Break something on purpose and watch it fail. Corrupt one DUT output with a force, or add a bug in a scratch copy of the RTL. Then check that the scoreboard reports exactly the expected mismatch. Also count predictions and responses: equal counts show the model saw every transaction.

    Self-Check

    Tick each key point you covered in your answer.

    Misconception

    "Zero errors over thousands of tests proves it."

    A scoreboard that compares the DUT with itself also reports zero errors. Only a failure you caused shows the check is alive.

    Source Lesson D2.3 key points (show that a broken design makes the check fail)

What People Get Wrong

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

Misconception

"The response echoes the address, so predict from the response."

Then the model checks the DUT against itself. The twin's DUT reads the wrong address, echoes it, and the model agrees four times.

Run It

A lookup DUT with an off-by-one address bug that it also echoes in the response.

RUNVerilator + C/C++ over DPI · simulator service
Edit the code, then run it
Expected: checked=4 errors=0 FAIL: the model was fed the DUT's own echoed address, so it agreed with the off-by-one bug
See the Fix
`timescale 1ns/1ps
// A lookup DUT: it should return table(addr) and echo addr. The bug reads addr+1 and echoes that.
module lookup_dut(input int addr, output int rsp_addr, output int rsp_data);
  assign rsp_addr = addr + 1;
  assign rsp_data = rsp_addr * 3 + 1;
endmodule
module tb;
  import "DPI-C" function chandle model_new();
  import "DPI-C" function int model_read(input chandle h, input int addr);
  class scoreboard;
    chandle model;
    int exp_q[$];
    int errors = 0, checked = 0;
    function new(); model = model_new(); endfunction
    function void write_in(int addr);                    // from the input monitor
      exp_q.push_back(model_read(model, addr));  // the fix: predict from what the DUT accepted
    endfunction
    function void write_out(int rsp_addr, int rsp_data); // from the output monitor
      int e;
      e = exp_q.pop_front();
      if (rsp_data != e) errors++;
      checked++;
    endfunction
  endclass
  int addr, rsp_addr, rsp_data;
  lookup_dut dut(.addr(addr), .rsp_addr(rsp_addr), .rsp_data(rsp_data));
  scoreboard sb = new;
  initial begin
    for (int i = 0; i < 4; i++) begin
      addr = i * 10;
      sb.write_in(addr);
      #1 sb.write_out(rsp_addr, rsp_data);
    end
    $display("checked=%0d errors=%0d", sb.checked, sb.errors);
    if (sb.errors == 0) $display("FAIL: the model was fed the DUT's own echoed address, so it agreed with the off-by-one bug");
    else $display("PASS: the prediction from the input side caught the off-by-one address");
    $finish;
  end
endmodule

Prints: checked=4 errors=4 PASS: the prediction from the input side caught the off-by-one address

Half-Truth

"Feed the model from the driver; it knows what was sent."

The driver knows what it tried to send, not what the DUT accepted. Backpressure, drops and resets make the two differ.

Source Lesson D2.3 key points (predict from observed accepted transfers)

Wrong Altitude

"Let the C model compare and return pass or fail."

Then mismatches never reach UVM reporting, coverage or the error count. C predicts; SystemVerilog compares and reports.

Source Lesson D1.1 key points (keep the check in SystemVerilog)

Learn It, Then Prove It