I have a class driver (coded in UVM) and a module sampler_n_dummy_gnt as follows (simplified for the purpose of this question):
class driver extends uvm_driver #(bus_trans);
...
task run_phase();
forever begin
seq_item_port.get_next_item(bus_trans_h);
drive_item(bus_trans_h);
...
end
...
endtask
task drive_item();
vif.sel = 1;
vif.req = 0;
@(posedge vif.clk);
vif.req = 1;
// #1; // this delay needed to prolong req for 1 clock
if (vif.gnt == 1)
@(posedge vif.clk);
else begin
while (vif.gnt == 0)
@(posedge vif.clk);
end
end
vif.req = 0;
endtask
endclass
module sampler_n_dummy_gnt;
logic clk, rstn;
int rdelay;
bus_interface vif(clk, rstn);
always #10ns clk = ~clk;
always @(posedge vif.req) begin
rdelay = $urandom_range(0,5);
if (rdelay != 0) begin
for (int i=0; i<rdelay; i=i+1) begin
vif.gnt = 0;
@(posedge vif.clk);
end
end
vif.gnt = 1;
end
endmodule
Basically, the driver emulates a protocol that specifies that it should assert sel
whenever there's a new transaction. One cycle after, it should assert req
. It then waits until gnt
is high and only deasserts req
one cycle after.
The sampler waits for the assertion of req
and based on the randomly generated number waits for a certain number of clock cycles before it asserts gnt
. So either there's no delay or a few delays with maximum 5 cycles.
The first transaction is OK until I run into the 2nd transaction. At posedge of clock 7, the gnt
deasserted and so req
should remain high until it sees the gnt
assert at clock 8. However, I never saw req
assert anymore from clock 7 onwards (i.e. it stayed 0). I suspected that at posedge of clock 7, it sees gnt = 1
but skipped the if-else
condition and goes straight to drive req = 0
. So I have to add the line I commented above in order to get the expected scenario. Could someone help explain why the delay is needed?
(Expected) (Actual)
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
clk _| |_| |_| |_| |_| |_| |_| |_| |_ _| |_| |_| |_| |_| |_| |_| |_| |_
_______________ ___________ _______________ ___________
sel _| |___| _| |___|
___________ _______ ___________
req _____| |_______| _____| |_______________
___________ ___ ___________ ___
gnt _____________| |___| _____________| |___|
I'm assuming clk
, vif.clk
, vif.pclk
are really all the same signal.
Your code has a number of problems with dealing with synchronous signals.
<=
Since you did not post the complete code, I can only make this a suggestion
class driver extends uvm_driver #(bus_trans);
...
task run_phase();
@(posedge vif.clk; // initial sync
forever begin
while (!seq_item_port.try_next_item(bus_trans_h)
@(posedge vif.clk;
drive_item(bus_trans_h);
...
end
...
endtask
task drive_item();
vif.sel <= 1;
vif.req <= 0;
@(posedge vif.clk);
vif.req <= 1;
@(posedge vif.clk iff vif.gnt);
vif.req <= 0;
endtask
endclass