Q134FreeSystemVerilog
Route a shared read bus without internal tri-states
Interview prompt
Question
Design a two-master, one-slave read-bus multiplexer. An external sel chooses the eligible master, only one request may be outstanding, and the response must return to the master that launched it. Add a master BFM read task. AW and DW are positive integers. Reset before use, initialize BFM valid=0, and serialize read calls per master. The BFM advances only when sampled ready or response-valid is exactly 1; X or Z on either observation is not acceptance or completion.
Candidate starting point
Implementation scaffold
module read_bus_mux #(
parameter int unsigned AW = 32,
parameter int unsigned DW = 32
) (
input logic clk,
input logic rst_n,
input logic sel,
input logic m0_valid,
input logic [AW-1:0] m0_addr,
output logic m0_ready,
output logic m0_rsp_valid,
output logic [DW-1:0] m0_rsp_data,
input logic m1_valid,
input logic [AW-1:0] m1_addr,
output logic m1_ready,
output logic m1_rsp_valid,
output logic [DW-1:0] m1_rsp_data,
output logic s_valid,
output logic [AW-1:0] s_addr,
input logic s_ready,
input logic s_rsp_valid,
input logic [DW-1:0] s_rsp_data
);
logic busy_q, owner_q;
logic req_fire;
always_comb begin : select_request
// TODO: Implement select_request using the supplied state and interface.
end
assign req_fire = s_valid && s_ready;
assign m0_rsp_valid = s_rsp_valid && busy_q && !owner_q;
assign m1_rsp_valid = s_rsp_valid && busy_q && owner_q;
assign m0_rsp_data = m0_rsp_valid ? s_rsp_data : '0;
assign m1_rsp_data = m1_rsp_valid ? s_rsp_data : '0;
always_ff @(posedge clk or negedge rst_n) begin : track_owner
// TODO: Implement track_owner using the supplied state and interface.
end
endmodule
interface read_master_if #(
parameter int unsigned AW = 32,
parameter int unsigned DW = 32
) (input logic clk);
logic valid, ready, rsp_valid;
logic [AW-1:0] addr;
logic [DW-1:0] rsp_data;
clocking cb @(posedge clk);
default input #1step output #0;
output valid, addr;
input ready, rsp_valid, rsp_data;
endclocking
modport TB (clocking cb);
endinterface
class read_master_bfm #(int unsigned AW = 32, DW = 32);
virtual read_master_if #(AW, DW).TB vif;
function new(virtual read_master_if #(AW, DW).TB vif); this.vif = vif; endfunction
task read(input logic [AW-1:0] addr, output logic [DW-1:0] data);
// TODO: implement this body.
endtask
endclassReviewed example
Trace one case
Input
cycle1 sel=0 and master0 request A handshakes; sel changes to 1 before slave response A at cycle4Expected output
response valid/data route only to master0; master1 response path remains known inactiveThe accepted owner is latched with the request, so a later external selection change cannot misroute the delayed response.
What to cover
Requirements
- Use valid/ready handshakes on requests and an explicit valid on responses.
- Latch the selected owner when the slave accepts a request; sel may change before the response returns.
- Drive inactive response paths to known values rather than high impedance.
- Apply backpressure while a read is outstanding and keep the BFM request stable until accepted.
- The slave response arrives no earlier than the cycle after request acceptance; a zero-latency slave would require an explicit response bypass.
- While an offered request is stalled, the environment holds sel and the selected master’s valid/address stable. After acceptance, sel may change freely; the saved owner routes the response. Responses have no backpressure pin and are consumed when valid is sampled.
