← Design Verification Interviews
Interview Question · Code Reading
Responses That Went Missing
The Question
The interviewer asks
The driver returns a response for every read with item_done(rsp). How many responses does this sequence collect?
task body(); // in ten_reads, a uvm_sequence #(bus_item)
repeat (10) begin
req = bus_item::type_id::create("req");
start_item(req);
void'(req.randomize());
finish_item(req); // the driver answers with item_done(rsp)
end
// now collect every response
fork
forever begin get_response(rsp); got++; end
#100;
join_any
disable fork;
$display("sent 10 reads, got %0d responses", got);
endtaskYou have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
It collects 8, not 10. Each sequence keeps its responses in a queue that holds 8 by default. This sequence reads none until all ten are sent, so the ninth and tenth are dropped. In uvm-core 2020.3.1 the overflow error is off by default, so nothing is reported. Call get_response() after each finish_item, or use a response handler.
item_done(rsp) two clock cycles after it takes each item.- Both ask; low goes first
Both sequences call
start_itemas the test forks them. The sequencer grantslow, stamps its item with low's sequence ID, and the driver takes it.Follow the calls, values and waits
- data low tid=1: x=10: low → Sequencer
- data low tid=1: x=10: Sequencer → Driver
- Waiting: low — in finish_item
- Waiting: high — waiting for a grant
- A response addressed to low20 ns (illustrative)
The driver builds a new response, copies both IDs with
set_id_info(req)and callsitem_done(rsp). The sequencer reads the sequence ID and queues it forlow.Follow the calls, values and waits
- data rsp for low tid=1: y=11: Driver → Sequencer
- data rsp for low tid=1: y=11: Sequencer → low
- Released: low
- high is granted next20 ns (illustrative)
The driver asks again in the same time step.
highhas waited longest, so it is granted; its item also carries transaction ID 1.Follow the calls, values and waits
- data high tid=1: x=100: high → Sequencer
- data high tid=1: x=100: Sequencer → Driver
- Waiting: high — in finish_item
- Waiting: low — waiting for a grant
- Released: high
- tid=1 again, but for high40 ns (illustrative)
high's response is routed to high's queue. The driver then takes low's second item.
Follow the calls, values and waits
- data rsp for high tid=1: y=101: Driver → Sequencer
- data rsp for high tid=1: y=101: Sequencer → high
- data low tid=2: x=11: low → Sequencer
- data low tid=2: x=11: Sequencer → Driver
- Waiting: low — in finish_item
- Waiting: high — waiting for a grant
- Released: high
- Released: low
- low's second answer60 ns (illustrative)
low's tid=2 response reaches low, and high's second item goes out.
Follow the calls, values and waits
- data rsp for low tid=2: y=12: Driver → Sequencer
- data rsp for low tid=2: y=12: Sequencer → low
- data high tid=2: x=101: high → Sequencer
- data high tid=2: x=101: Sequencer → Driver
- Waiting: high — in finish_item
- Released: low
- Released: high
- high's second answer80 ns (illustrative)
The last response reaches high. Each sequence printed only its own two answers.
Follow the calls, values and waits
- data rsp for high tid=2: y=102: Driver → Sequencer
- data rsp for high tid=2: y=102: Sequencer → high
- Released: high
Read the diagram as text
- low: Sends 10 and 11; get_response by tid
- high: Sends 100 and 101; get_response by tid
- Sequencer: Stamps the sequence ID; routes responses
- Driver: New rsp; set_id_info(req); item_done(rsp)
- low → Sequencer: finish_item(it)
- high → Sequencer: finish_item(it)
- Driver → Sequencer: get_next_item / item_done(rsp)
- Sequencer → low: low's queue
- Sequencer → high: high's queue
The sequence ID picks the queue; the transaction ID picks the response inside it.
Self-Check
Tick each key point you covered in your answer.
What Interviewers Listen For (Mid-Level)
A good mid-level answer knows that each sequence keeps its own response queue, and predicts 8. It fixes the code by reading each response inside the loop.
What Interviewers Listen For (Senior)
A good senior answer is suspicious of the silence and checks the library default. It turns the overflow report on in the base sequence.
Cross-Questions
Where the interviewer goes next. Open a node to practise that follow-up.
WhyWhat IfBreak ItCompareScale It
- Responses That Went Missing
-
WhyWhy Responses Need Set ID InfoL1 Junior
Why must the driver call
rsp.set_id_info(req)before returning a response?2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Several sequences can share one sequencer, so a response has to say whose it is.
set_id_info()copies the sequence ID and transaction ID from the request into the response. The sequencer uses them to put the response in the right sequence's queue.Self-Check
Tick each key point you covered in your answer.
Misconception
"The sequencer remembers which request is in flight, so IDs are optional."
With several requests outstanding, or several sequences, the IDs are the only link back.
Source IEEE 1800.2-2020 §14.1.2.4 set_id_info (uvm-core seq/uvm_sequence_item.svh)
-
What IfA Response Without Its IDsL1 JuniorL2 Mid-Level
What if the driver creates the response with
newand forgetsset_id_info()?2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
The response then has no sequence ID, so the sequencer cannot route it. The uvm-core library stops the run with a fatal error: "Driver put a response with null sequence_id". So the mistake shows at once, not as a hang. Call
rsp.set_id_info(req)right after creating the response.Self-Check
Tick each key point you covered in your answer.
Misconception
"Without IDs, the response goes to the first sequence on the sequencer."
The sequencer does not guess. In uvm-core a response with no sequence ID is a fatal error.
Source uvm-core 2020.3.1 (IEEE 1800.2 library) source, seq/uvm_sequencer_param_base.svh (SQRPUT)
-
CompareResponse Handler vs Get ResponseL2 Mid-Level
Compare calling
get_response()withuse_response_handler(1)and aresponse_handler()function.2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
get_response()blocks the sequence until a response arrives, so each request waits for its answer. Withuse_response_handler(1), the sequencer calls yourresponse_handler()function for each response as it arrives. The sequence keeps sending without waiting, which suits pipelined traffic. Responses then bypass the queue, so it cannot overflow.Self-Check
Tick each key point you covered in your answer.
Misconception
"The response handler can wait for the next clock."
It is a function, called in the sequencer's context, so it cannot consume time.
Source uvm-core 2020.3.1 (IEEE 1800.2 library) source, seq/uvm_sequence_base.svh, virtual function void response_handler
-
Break ItTwo Sequences Waiting for ResponsesL2 Mid-Level
How could two sequences on one sequencer end up waiting on each other's responses?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
They cannot, as long as the driver copies the IDs: each response goes to its own sequence's queue. The problem appears when a driver builds the response from a stale request or a shared handle. Then one sequence gets two responses and the other hangs. Within one sequence,
get_response(rsp, id)waits for a specific transaction.Self-Check
Tick each key point you covered in your answer.
Misconception
"All responses go to the sequencer, and any sequence can take the next one."
Each sequence has its own response queue, and routing uses the sequence ID.
Source Verification Academy, UVM Cookbook, Sequences: response routing (PDF p198)
-
Scale ItAn Unbounded Response QueueL3 Senior
Why not set
set_response_queue_depth(-1)in the base sequence and forget about overflow?2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
It hides a sequence that never reads its responses. In a long test, those responses pile up in memory, and nobody checks them. Prefer reading responses or a response handler. If you do raise the depth, also enable the overflow report, so a real problem still shows.
Self-Check
Tick each key point you covered in your answer.
Half-Truth
"Unbounded is always safer."
It trades a visible drop for silent memory growth and unchecked data.
Source uvm-core 2020.3.1 (IEEE 1800.2 library) source, seq/uvm_sequence_base.svh, set_response_queue_depth: -1 means arbitrarily deep
What People Get Wrong
Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.
Misconception
"Responses wait in the queue until the sequence asks for them."
The queue holds 8. Extra responses are dropped. The twin collects 8 of 10 with UVM_ERROR : 0.
Run It
The interview's sequence and a driver that answers every read.
sent 10 reads, got 8 responses FAIL: the response queue holds 8; the rest were dropped without an errorSee the Fix
`timescale 1ns/1ns
`include "uvm_macros.svh"
import uvm_pkg::*;
class bus_item extends uvm_sequence_item;
`uvm_object_utils(bus_item)
rand bit [7:0] data;
function new(string name = "bus_item"); super.new(name); endfunction
endclass
class ten_reads extends uvm_sequence #(bus_item);
`uvm_object_utils(ten_reads)
int got;
function new(string name = "ten_reads"); super.new(name); endfunction
task body();
repeat (10) begin
req = bus_item::type_id::create("req");
start_item(req);
void'(req.randomize());
finish_item(req);
get_response(rsp); // the fix: collect each response as it comes
got++;
end
$display("sent 10 reads, got %0d responses", got);
if (got < 10) $display("FAIL: the response queue holds 8; the rest were dropped without an error");
else $display("PASS: every read got its response");
endtask
endclass
class bus_driver extends uvm_driver #(bus_item);
`uvm_component_utils(bus_driver)
function new(string name, uvm_component parent); super.new(name, parent); endfunction
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
#10;
rsp = bus_item::type_id::create("rsp");
rsp.set_id_info(req); // route the response back to its sequence
rsp.data = ~req.data;
seq_item_port.item_done(rsp);
end
endtask
endclass
class rsp_test extends uvm_test;
`uvm_component_utils(rsp_test)
uvm_sequencer #(bus_item) sqr;
bus_driver drv;
function new(string name, uvm_component parent); super.new(name, parent); endfunction
function void build_phase(uvm_phase phase);
sqr = uvm_sequencer #(bus_item)::type_id::create("sqr", this);
drv = bus_driver::type_id::create("drv", this);
endfunction
function void connect_phase(uvm_phase phase); drv.seq_item_port.connect(sqr.seq_item_export); endfunction
task run_phase(uvm_phase phase);
ten_reads seq = ten_reads::type_id::create("seq");
phase.raise_objection(this);
seq.start(sqr);
phase.drop_objection(this);
endtask
endclass
module tb;
initial run_test("rsp_test");
endmodule
Prints: sent 10 reads, got 10 responses PASS: every read got its response
Tool as Truth
"UVM always reports an error when the response queue overflows."
The source comment says so, but the flag that enables the report is a bit that starts at 0 in uvm-core 2020.3.1. Only set_response_queue_error_report_enabled(1) turns it on.
Source uvm-core 2020.3.1 (IEEE 1800.2 library) source, seq/uvm_sequence_base.svh: response_queue_error_report_enabled (line 174, never set) and put_base_response
Missed Corner
The driver builds rsp but skips rsp.set_id_info(req).
The sequencer routes a response by the sequence and transaction IDs copied from the request. Without them, it cannot find the sequence.
Source Verification Academy, UVM Cookbook, Sequences: routing responses with set_id_info (PDF p198, p218)