reject_on is an asynchronous about property. Perhaps you meant to use sync_reject_on. But without knowing what your requirements are, I’m not sure why you need the reject in any case.
The reject_on (expression_or_dist) property_expr rejects the property as false if the abort condition is true. Otherwise, with the abort condition as false, the property expression evaluates to completionlog]
If I use **reject_on( ! $stable( Sig1, @( posedge clk) ) )**
it is equivalent to property_expression without using ' reject_on ' i.e
$stable( Sig1 ) s_until_with $rose( Sig2 ) ;
Hence a glitch between 2 posedge of clk would go unnoticed .
**NOTE :: Using @( clk ) a glitch between posedge N negedge OR negedge N posedge still goes unnoticed .**
[3] Since ’ reject_on ’ samples the Signals asynchronously .
My guess is this could leads to performance issues for longer simulations .
In reply to ben@SystemVerilog.us:… Hence a glitch between 2 posedge of clk would go unnoticed.
With supporting logic, you can create a signal that goes to 1’b1 if in between clocks sig1 changes value. Here, I use a task initiated by @(posedge clk) that forks 2 processes:
#2 @(sig1) s1_glitch=1’b1;
The #2 is used to avoid a normal sig1 toggling to be considered as a glitch in sig1.
I am assuming that sig1 can toggle in less than 2 ns.
I there is an @(sig1)before an @(posedge clk) then it is considered a glitch
@(posedge clk) s1_glitch=1’b0; That resets the glitch signal
Code
module m;
bit clk, sig1, sig2, enable, s1_glitch, a, b;
property suntil_with(Sig1, Sig2);
reject_on (s1_glitch) $stable(Sig1) |-> $stable(Sig1) s_until_with $rose(Sig2);
endproperty
task automatic glitch();
fork
#2 @(sig1) s1_glitch=1'b1; // sig1 can taggle in less than 2 ns
@(posedge clk) s1_glitch=1'b0;
join_any
endtask
always_ff @(posedge clk) glitch();
ap : assert property (@(posedge clk) suntil_with(a, b));
endmodule
[3] Since ’ reject_on ’ samples the Signals asynchronously .
My guess is this could leads to performance issues for longer simulations . Is usage of ’ reject_on ’ discouraged ?
bit clk , a , b , enable , s1_glitch ;
sequence trigger1 ; // Declared as ' sequence ' to use .triggered Method !!
@( posedge clk ) $rose( enable );
endsequence
always @( trigger1.triggered ) // Start ONLY when antecedent is True
....
/* [Ben] Too much unnecessary code! Why declaring a sequence of one term to use .triggered
when you can use that term directly? Thus, instead of */
always @( trigger1.triggered )
// use
// $rose ( expression [, [clocking_event] ] )
always @($rose(a, @(posedge clk) ))
// ---------------------------------
// [Ben] your glitch task has too many embedded forks?
// This looks better to me
task automatic glitch();
fork
begin
fork
@( a ) s1_glitch = 1'b1;
@( clk ) s1_glitch = 1'b0 ;
join_any
disable fork
endtask
// -------------------------
// [Ben] To many forks and glitch() calls.
// Somehow, it does not look right to me.
always @( trigger1.triggered ) // Start ONLY when antecedent is True
begin
fork
begin
fork
begin
glitch();
forever @( clk ) glitch(); // [Ben] why not a simple
//[Ben] always @( clk ) glitch();
end
begin
@( trigger2.triggered ) ; // Restart when Consequent has a Match
end
join_any
disable fork ;
end
join
end
ap : assert property ( ab(a, b) );