FWIW, this concept was a derivation of of my modeling SVA with fork-join_none.
I strongly encourage you to read my paper
Understanding the SVA Engine, Verification Horizons - July 2020 | Verification Academy
It will give more insights into how SVA works, and that will help you write better SVA code.
BTW, that paper is just a model of SVA, it is NOT how vendors implement it, but still, it is of value particualrly if you want to write a concurrent assertion in a class (where SVA is illegal). If you have dynamic repeats and delays, see my package (link below).
In reply to ben@SystemVerilog.us:
This model does not use any clocks. It is based on the use of forks.
In this application, this concept is a derivation of of my modeling SVA with fork-join_none.
I strongly encourage you to read my paper - Understanding the SVA Engine,
On transitions in signals a,b,c after that, I made an assumption of 15 transitions
/* I have a requirement to check if a couple of signals does not transition
after de-assertion of reset for a fixed time.
Here is the scenario
1. reset de-asserted at time 100ns
2. check signals a,b,c are stable(held either high or low) for next 1000ns
3. see transitions in signals a,b,c after that
As the clock is not involved, how do we check if the signal is stable for a fixed time?
In my case the clock is not toggling when reset is low,
as both are asynchronous I cannot expect the clock to be toggling*/
module top;
`include "uvm_macros.svh"
import uvm_pkg::*;
bit clk, reset, a, b, c;
let period=10ns;
event e0, e1;
initial forever #5 clk=!clk;
initial begin
$dumpfile("dump.vcd"); $dumpvars;
#0 reset = 0;
force clk = 0;
#100 reset = 1;
#20 release clk;
#5000 $finish;
end
initial begin
repeat(9000) begin
@(posedge clk);
if (!randomize(a, b, c) with
{ a dist {1'b1:=1, 1'b0:=1};
b dist {1'b1:=1, 1'b0:=2};
}) `uvm_error("MYERR", "This is a randomize error");
end
end
// 2. check signals a,b,c are stable(held either high or low) for next 1000ns
// abc grouped. If individual is needed,
// create 3 copies of the task and do individual @(x) for the a, b, c,
// also indicidual arguments.
// Used inout instead of ref because
// Actual argument passed as reference cannot be used within
// fork-join_any or fork_join_none (see link below).
task automatic t_abc1000 (inout bit abc_error, done);
fork
begin : the1000
#1000;
end : the1000
begin : the_stable
@(a or b or c);
-> e0;
abc_error=1;
a_abc_triggered: assert(0) else $display("%t a or b or c unstable within 1000ns", $realtime);
end : the_stable
join_none
done=1;
endtask: t_abc1000
// 3. see transitions in signals a,b,c after that for the next 1000ns
task automatic t_abc_after (inout bit abc_error, done);
realtime t;
int count;
#1000;
t=$realtime;
->e1;
fork
begin : the1000
#1001;
abc_error=1;
a_abc_no_triggered: assert(0) else $display("%t a or b or c no trigger after 1000ns", $realtime);
end : the1000
begin : the_stable
while ($realtime < t+1000) begin : the_while
@(a or b or c);
count=count+1'b1;
if(count>=15) begin
done=1;
disable t_abc_after;
end
end : the_while
end : the_stable
join_none
done=1;
endtask: t_abc_after
// 2. check signals a,b,c are stable(held either high or low) for next 1000ns
always @(posedge reset) begin : b0
bit abc_error0, abc_error1, done1000, done_after;
fork
t_abc1000 (abc_error0, done1000);
t_abc_after (abc_error1, done_after);
join_none
wait(done1000);
if(abc_error0) $display("%t Error in first 1000ns", $realtime );
wait(done_after);
if(abc_error1) $display("%t Error after 1000ns", $realtime );
end : b0
endmodule