Stable for n*8 cycles property - system-verilog-assertions

I am learning SVA and trying to get my head around this check: data can only change every 8 cycles.
I know I can do that check by adding a counter that counts clock cycles and checking against it that way:
bit[2:0] count;
always #(posedge clk)
begin
count++;
end
change_n8cycles: assert property (#(posedge clk) $changed(data) |-> count == 0);
However, I'm interested in a way to do that with only SVA. So far, I was thinking of something like that (which doesn't compile)
property change_n8cycles(valid, ready, data);
#(posedge clk)
$changed(data) |=> $stable(data)[*7] ##1 ($stable(data)[*8])[0:$] ##0 $changed(data);
endproperty : change_n8cycles
I feel there is an elegant way using an approach similar; or using recursive properties. However, I couldn't find it.

I would propose to use local variable in order to verify that
property change_n8cycles(valid, ready, data);
int lv_cnt;
#(posedge clk)
($changed(data), lv_cnt=0) ##1 ($stable(data), lv_cnt=lv_cnt+1)[*1:$] ##1 $changed(data) |-> lv_cnt == 8;
endproperty
Or use some modeling layer
always #(posedge clk) begin
if($changed(data))
count=0;
else
count++;
end
property change_n8cycles(data);
#(posedge clk)
$changed(data) |-> $past(count) == 8;
endproperty

Related

How to make a signal stable for quite some time in the assertion

Suppose I have an assertion as follows. Now here I want signal A to remain stable for some time after rising up. That is, A should be high until the first occurrence of D == 4 after that it can go low at any time it wants.
Also I dont want to use ##[0:$] in this assertion.
Any help/advice would be very much appreciated. Thank you.
property p_check(A,B,C,D,E);
#(posedge clk) disable iff(!resetn)
$rose(A) ##1 B ##0 (C == 3) ##0 (D != 2) |=> (D == 4)[->1] ##[0:2] (!E throughout A);
endproperty : p_check
You should write this as a separate property.
#(posedge clk) disable iff(!resetn)
$rose(A) |=> $stable(A) until (D==4);

Data Mux SVA compare

I've trouble designing assertions(SVA) for this scenario.
When a mux sel is asserted, the data_in is expected to be stable for 2 clocks ; clock prior to mux sel being asserted, and the current clock when mux sel is asserted.
Now the data_in is a wide vector/bus signal, whereby some bits of the bus are Z and X during functional mode (this is expected), while this bits may carry value during non-functional mode.
This then implies, the approach to design the SVA would be to compare bit by bit of data bus when mux sel is asserted.
This is my approach, but SVA fails and am not sure why.
generate
for( genvar i=1 ; i<BUS_WIDTH ; i++ ) begin
always # (posedge clk) begin
if(!$isunknown(data_in[i]) && reset) begin
data_in_temp_prev[i] <= data_in[i];
if (mux_sel==1 && reset==1 && i>0) begin
SVA_TEST: assert property (data_in[i] == data_in_temp_prev[i-1]) else `uvm_error("TRIAL_SVA",$sformatf("datain expected to be stable for 2 clks prior to mux sel"));
end //if
end //if isunknown
else begin
din0_temp_prev[i] <= 0;
end
end //always
end // for genvar
endgenerate
Any suggestions on how to approach designing this SVA ?
Thanks.
If I understood correctly your problem, you don't need all this structure for this kind of problem, look at my example below and tell me if helps or not.
property mux_compare;
disable iff(!reset)
#(posedge mux_sel)
!$isunknown(data_in)
|->
#(posedge clk)
$stable(data_in) [*2];
endproperty: mux_compare
My approach to SVA checkers is to use a standard structure to properties to avoid all kinds of problems. the structure is to always use clocked properties with "disable iff" and always use an implication operator, where the left hand side is the trigger and the right hand side is what we want to verify.
Here's an example from the LRM:
property abc(a, b, c);
disable iff (c) #(posedge clk) a |=> b;
endproperty
similarly to the answer above, I would do this:
property mux_compare;
disable iff(!reset) #(posedge clk)
mux_sel===1 |->
!$isunknown(data_in[i]) || $stable(data_in) && data_in[i] == $past(data_in[i],2);
endproperty: mux_compare

How to write property for formal verification?

property prop1;
#(posedge clk)
$fell(sig1) ##1 sequence1 |-> sequence2;
endproperty
I want to disable the property iff sig1=1'b1 after first clock cycle.
Transition from high to low on sig1 is my triggering condition. If I do disable iff(sig1) triggering condition will not be met.
Also using throughout is not possible on both enabling and satisfying sequences in formal verifiers.
How can i do it?
Thanks!
How about writing some satellite code to derive a delayed version of sig:
always #(posedge clk) sig1d <= sig1;
property prop1;
#(posedge clk) disable iff(sig1d)
$fell(sig1) ##1 sequence1 |-> sequence2;
endproperty
http://www.edaplayground.com/x/2tbX
You can re-write your assertion to only trigger if you don't see sig1 high after the first cycle:
property prop1;
#(posedge clk) disable iff(sig1d)
$fell(sig1) ##1 !sig1 ##0 sequence1 |-> sequence2;
endproperty

How to write a property in System verilog assertions?

I want to write a property in SVA to formally verify a behavior.
Here is what I want to:
property prop1(sig1,sig2,sig3,sig4);
#(posedge clk)
$fell(sig1) ##[1:$] first_match($fell(sig2)) ##0 sig3 |-> sig4 == sig3;
endproperty
How can I rewrite the above property so that after sig1 falls, it stays LOW during remaining Evaluation cycles?
Note: I do not want to put sig1 as disable iff (sig1)
property prop1(sig1,sig2,sig3,sig4);
#(posedge clk)
(!sig1) throughout (##[1:$] first_match($fell(sig2)) ##0 sig3)
|-> sig4 == sig3;
endproperty
See section 16.9.9 Conditions over sequences in the 1800-2012 LRM

system verilog assertions: Using a reg value in a repition operator

I am trying to do something like this:
assert property (#(posedge clk) disable iff (!rst) a[*c] -> $rose(b))
Here c is not a 'constant' but a value coming from some bits of a register. eg: reg[4:0] which is written only once. The check is to see if b is asserted only when a is high for "c" number of cycles.
However, SVAs do not accept a variable like this : [*reg[4:0]]. Any ideas??
Introduce a local variable ctr. At every posedge a new assertion with a new instance of ctr will be created. Set ctr equal to the value in reg1. Check that a is true throughout the down count. Decrement the counter as long as it is larger than zero. The (ctr>0, ctr--)[*0:$] statement will count down until ctr == 0 is true.
You might want to change (ctr>0, ctr--)[*0:$] to (ctr>0, ctr--)[*1:$], depending on what results you expect if reg == 0.
property pr_aRegTimes;
integer ctr;
disable iff (!rst)
#(posedge clk)
(1, ctr = reg1) ##0 a throughout ((ctr>0, ctr--)[*0:$] ##1 (ctr == 0)) |-> $rose(b);
endproperty
as_aRegTimes: assert property (pr_aRegTimes)
else $error("aRegTimes failed");
Working example:
http://www.edaplayground.com/x/Xh9
Sources:
https://www.doulos.com/knowhow/sysverilog/tutorial/assertions/
http://www.win.tue.nl/~jschmalt/teaching/2IMF20/SvaFvTutorialHVC2013.pdf
property pr_aRegTimes;
integer ctr;
disable iff (!rst)
#(posedge clk)
($rose(a), ctr = reg1) ##0 (a&&ctr>0,ctr--)[*] |-> $rose(b);
endproperty