Usage of $past in System Verilog Assertions - system-verilog

I want to check if the current value of variable is '1' then the previous value of the variable should be '0'. I am using $past in System Verilog Assertions. Here I am checking if cal_frame_mode=1, then it's previous value of cal_frame_mode=0. My code is below. However, I am seeing assertion failure. When I check in the waveform it's behaving correctly. Assertion flags 2 clock after the the first check. How to stop this assertion after checking just one clock cycle?.
property p_NOP_2_RX_CAL;
#(posedge clk)
(cal_frame_mode==3'b001) |-> ##2 $past(cal_frame_mode)==3'b000;
endproperty
assert_nop2cal : assert property(p_NOP_2_RX_CAL);

##2 means wait two clocks. The default of $past looks at the value of the expression one clock back from the current clock (by default this is the clock defined in the property). Therefore:
(cal_frame_mode==3'b001) |-> ##2 $past(cal_frame_mode)==3'b000;
Is equivalent to:
(cal_frame_mode==3'b001) |-> ##1 cal_frame_mode==3'b000;
What you want is: (cal_frame_mode==3'b001) |-> $past(cal_frame_mode)==3'b000; but I'm guessing the reason you had the ##2 is to filter out cal_frame_mode equaling one for two clocks. If so, then the better solution is to add $change or !$stable to the antecedent, this what the check is only performed when the cal_frame_mode changed and the current value is one.
$changed(cal_frame_mode) && (cal_frame_mode==3'b001) |-> $past(cal_frame_mode)==3'b000;
Assertions are documented in IEEE Std 1800-2012 § 16 Assertions
§ 16.9.3 Sampled value functions describes $sample, $rose, $fell, $stable, $changed, and $past in detail
§ 16.12.6 Implication describes |-> and |=>

Related

What is the best way to check an event occurred in the past in SVA?

I want to check in my design that when signal b get asserted, then signal a should have gotten asserted 3 to 5 cycles before.
I'm looking for the different ways to check that.
Currently I'm using the following logic
sequence s_test();
##1 $rose(a) ##[3:5] 1;
endsequence
property p_test();
##1 $rose(b) |-> s_test.triggered();
Is there a way to check that property without using the sequence triggered mechanism ? I guess I could also use something like $past(a, 3) || ... || $past(a, 5), but that's cumbersome.
Also what's the difference between the sequence triggered and matched mechanism ?
We can have two approaches here: cause then effect or effect because of cause.
Cause then effect approach:
You can use a forward-time-based assertion stating that when s_test is triggered, then b should go high in 1-5 clock period of time window:
s_test.triggered |-> ##[1:5] $rose(b);
Effect then cause approach:
Alternatively, if s_test is a signal, then you can use a glue logic which monitors past 5 values of s_test. Thereafter, the assertion checks that the earlier values of s_test must have atleast 1'b1 when b rises from 0 to 1.
bit[1:5] earlier;
always #(posedge clk) begin
earlier <= {s_test, earlier[1:5]}; // shift for 5 clocks
end
p1_past20: assert property(#(posedge clk)
$rose(b) |-> $countones(earlier) >= 1);
A similar discussion is available here and a reference is over here.
You can use $past something like below.
property test_past;
#(posedge clk)
$rose(b) |-> ##[3:5] $past(a);
endproperty
triggered & matched methods differ for single clock & multi clock sequences.
Both methods show end point of a sequence, but triggered method evaluates to true if the operand sequence has reached it's end point at that particular time and false otherwise.
Whereas matched method detects endpoint of sequence, referenced in multiclocked sequence. So it provides synchronization between 2 sequences and evaluates to true after match, untill arrival of 1st clock tick of destination sequence.
triggered status of a sequence is set in observed region and is persisted through the remainder of the timestep. Whereas matched status of a sequence is set in observed region and is persisted untill the observed region of the arrival of first clock tick of destination sequence after match.

System Verilog: I am confused about the $stable statement

I understand that the $stable(expression) statement returns 'True', if the expression being evaluated has the same value as in the previous clock cycle. However, I don't understand why the following is being said in most learning materials:
assert property(#(posedge clk) enable == 0 |=> $stable(data));
states that data shouldn’t change whilst enable is 0.
As I have proved it, because |=> is being used, this will not work for the following example:
enable 1110000111
data__ ABCAAAABB
assert ______X___
(where A, B and C are some values of the data bus, and X is the point where the assertion would fail)
As you can see, the data has the value A while enable = 0, so it remains stable. But the assertion would not work as desired, because the data changes from A to B at the same time that enable changes from 0 to 1.
So my question is, how would you really implement or code the expression the data shouldn't change while enable is 0.?
Thanks in advance.
Maybe you are thinking of
assert property(#(posedge clk) (enable == 0)[*2] |-> $stable(data));
This means for two consecutive cycles when enable==0, data should not change.
I think "the desired behavior" of the original assertion is not very clear. The state of enable is one clock cycle and $stable is a condition evaluated over 2 clock cycles. There is a similar argument if overlapping implication |->was used. So the question becomes what happens if (enable==0) is true for only one clock cycle? How do you want stability of data defined?

How can I use SystemVerilog sequence properties in asserts?

I want to say "if there are an unlimited number of inputs, eventually I get an output", how can I do this?
In other parts of the script I want to assume a limited supply of inputs so I can't just write "assume there are an unlimited number of inputs" and have that hold globally.
So far I've written properties:
property always_another_valid_input;
#(posedge clock) ##[1:$] valid_input;
endproperty
property foo;
#(posedge clock) always_another_valid_input |-> ##[0:$] bar == 1;
endproperty
assert property (foo);
but when I run this I get an error: property instance always_another_valid_input is not allowed in sequence expression.
If I replace either side of the |-> with a non-sequence property then I still get an error. It only works when both sides are non-sequence properties.
Is there a good way to work around this?
Refer to IEEE Std 1800-2012 § 16.12 Declaring properties, and more specifically § 16.12.6 Implication, you will see the |-> syntax ussage is described as:
property_expr ::=
...
sequence_expr |-> property_expr
sequence_expr |=> property_expr
The left hand side must be a sequence or sequence expression. It cannot be a property even if that property only contains a sequence expression.
If you declare always_another_valid_input as a sequence instead of a property, your code will compile
sequence always_another_valid_input;
#(posedge clock) ##[1:$] valid_input;
endsequence

Reset awareness when using 'sequence.triggered' in assertion

I have a few assertions that use the triggered property of sequences. This is useful for checking properties of the form "when X happens, Y must have happened sometime in the past".
Let's take a simple example:
Given three signals, a, b and c, c is only allowed to go high if a was high 3 cycles ago and b was high 2 cycles ago. This is a trace that satisfies this property:
To be able to check this, we'd need a helper (clocked) sequence that should match at the point where a c is legal:
sequence two_cycles_after_a_and_b;
#(posedge clk)
a ##1 b ##2 1;
endsequence
We could then use this sequence in an assertion:
c_two_cycles_after_a_then_b : assert property (
c |-> two_cycles_after_a_and_b.triggered )
$info("Passed");
This assertion works fine in most cases, but it's going to go haywire when dealing with resets.
Let's say that we also have a reset signal that becomes active exactly in the clock cycle between b and c:
The naive approach in this case would be to implement reset awareness outside of the assertion, inside a default disable iff clause:
default disable iff !rst_n;
The expectation would be that, since reset was active before c, the a ##1 b that happened before doesn't count and that the assertion fails. This isn't what happens, though, as the evaluation of the sequence is independent of reset.
To achieve this behavior, the sequence must be made reset aware:
sequence two_cycles_after_a_and_b__reset_aware;
#(posedge clk)
rst_n throughout two_cycles_after_a_and_b;
endsequence
and the assertion needs to use the reset aware version:
c_two_cycles_after_a_then_b__reset_aware : assert property (
c |-> two_cycles_after_a_and_b__reset_aware.triggered )
$info("Passed");
The second assertion will indeed fail, because the two_cycles... sequence won't match due to the occurrence of reset.
This obviously works, but it requires a lot more effort and it requires reset to become an integral part of the sequences/properties instead of being controlled on a per-scope basis. Is there any other way to achieve reset awareness in this case that is closer to using a disable iff?
Best solution I can come up with is to add a little auxiliary code to sample rst_n and keep it low long enough for it to be sampled by the clock.
always #(posedge clk, negedge rst_n) begin
if(!rst_n) smpl_rst_n <= 1'b0;
else smpl_rst_n <= 1'b1;
end
Then use a generic sequence for the reset aware that uses smpl_rst_n and a a reference to a target sequence.
sequence reset_aware(sequence seq);
#(posedge clk)
smpl_rst_n throughout seq;
endsequence
Final assertion would work as follows:
a_two_cycles_after_a_then_b__reset_aware : assert property (
c |-> reset_aware(two_cycles_after_a_and_b).triggered )
$info("Passed");
Proof of concept: https://www.edaplayground.com/x/6Luf

SystemVerilog: implies operator vs. |->

Recently the question came up what the difference is between the usual implication operator (|->) and the implies operator in SystemVerilog. Unfortunately I couldn't find a clear answer yet. However, I collected the following information:
From SystemVerilog LRM 1800-2012:
§ 16.12.7 Implies and iff properties:
property_expr1 implies property_expr2
A property of this form evaluates to true if, and only if, either property_expr1 evaluates to false or property_expr2 evaluates to true.
§ F.3.4.3.2 Derived Boolean operators:
p1 implies p2 ≡ (not p1 or p2)
§ F.3.4.3.4 Derived conditional operators:
(if(b) P) ≡ (b |-> P)
However, the LRM does not really point out what the actual difference is. I assume that they differ in the evaluation in case of a false antecedent (success vs. vacuous success), but I could not find any source or evidence for this assumption. Moreover, I know that the implies operator is very common in combination with formal verification tools like OneSpin.
Could anyone help me out?
P.S.: It seems there is an answer to this question in the following book: SystemVerilog Assertions Handbook, 3rd Edition. But $155 is a bit too much for me just for getting the answer to this question :)
I think there is even a more significant difference. Assume that we have the following example:
property p1;
# (posedge clk)
a ##1 b |-> c;
endproperty
property p2;
# (posedge clk)
a ##1 b implies c;
endproperty
assert property (p1);
assert property (p2);
Both implication operators simply have different proving behavior. Property p1 will be triggered through a match of a ##1 b and will look for a matching c during the same clock tick as b. However, property p2 is triggered by a ##1 b and will check for a match of c during the clock cycle of a. This means the properties would pass for the following scenarios:
Property p1 passes and p2 fails:
Property p2 passes and p1 fails:
A hint for this behavior can be found in the SystemVerilog LRM. The defined substitutions are:
(if(b) P) = (b |-> P)
p1 implies p2 = (not p1 or p2)
So all in all, if one uses the implies operator it becomes easier to define multi-cycle operations since antecedent and consequence have the same starting point for the evaluation.
I tried it out and apparently the |-> is not allowed for properties (only for sequences and boolean expressions). Here's what I tried:
property a_and_b;
#(posedge clk)
a && b;
endproperty
property a_and_c;
#(posedge clk)
a && c;
endproperty
First form using |-> doesn't compile:
// this doesn't compile
assert property(a_and_b |-> a_and_c);
Second form using implies does compile:
// this does compile
assert property(a_and_b implies a_and_c);
Semantic-wise, it's as it is for the |-> operator. When a_and_b fails, the assertion vacuously passes. If a_and_b succeeds but b_and_c doesn't, then a fail is issued.