Let’s say I want to write monitor for a simple valid/ready data streaming interface: “@ clock edge, the transaction is valid if both valid and ready are high.”
I have a clocking block defined as follows (we don’t drive anything this only monitors the interface.
I can think of two ways to define the monitor task, and I’m wondering if there is any reason to prefer one or the other. Can anybody tell me if there is a difference between the following sequences?
I strongly suggest when you have a process using clocking block events, use only clocking events in that process, and no other event controls.
Although the LRM guarantees that clocking block input variables get updated before triggering the clocking block event, it says nothing about which region the input samples get updated. This is best illustrated if you have @(cb) as the next event control after thewait (cb.valid …).
module top;
bit clk=1, v;
clocking cb @(posedge clk);
input v;
endclocking
always #5 clk= !clk;
initial begin
wait(cb.v) $display("wait(cb.v)",, $time);
@cb $display("@(cb)",, $time);
@(cb iff !cb.v) $display("@(cb iff !cb.v)",, $time);
@(cb) $display("@(cb)",, $time);
$finish;
end
initial begin
#12 v = 1;
#26 v = 0;
end
endmodule
On some simulators you will see that the wait followed by @cb occurs in the same cycle, whereas @(cb) followed by @(cb) always comes comes in adjacent cycles.
As, we know “wait” is level sensitive will be block until cb.v = 1 ( and will continue check ).
Clocking block input will be stable( prepone region ) before clocking event.
So, as v is updated at #12. but as you mentioned which region sampled value will update for #20 clocking event is not define by 1800.
but , wait is level sensitive it will become true as soon as cb.v updated ( display come at #20 ).
So, in which condition below display will come at #30 instead of #20.
# @(cb) 30
as per me this behavior, due to “clocking event @(cb)” evaluate before “wait” for #20 time.
hence,@cb $display(“@(cb)”, $time); shift to next time clocking event.
is it correct understanding ?
This race is very similar to the following example
module top;
bit a,b;
initial begin
wait(a)
@(b)
$display("done1");
end
initial begin
#20
a = 1;
b = 1;
$display("done2");
end
endmodule
Because the two assignments to a and b execute in the same region, the SystemVerilog LRM section 4.7 Nondeterminsim allows the wait statement to proceed as soon as the first assignment to a occurs, or it could proceed after the display of “done2”. If it chooses the latter, the change to b has already happened and @(b) never resumes.
If I put a #0 between the two assignments, or use a non-blocking assignment to b, then @(b) is guaranteed to execute before the change to b, so “done1” will be displayed.