SystemVerilog disable cover property after hit - system-verilog

I have a few cover property's that I expect to fire pretty frequently, and I'm seeing they are starting to impact my simulation performance because they are firing so frequently. I don't want to remove them because I want to make sure I am still hitting these properties, but I don't care how many times I hit them. Is there a way to disable the cover property after it's hit once so it won't hinder simulation performance?
B2BReq : cover property (
#(posedge CLK iff !RESET)
Intf.ReqValid ##1 Intf.ReqValid
);
I'm thinking of something like this:
bit cov_disable;
B2BReq : cover property (
#(posedge CLK iff !RESET) disable iff(cov_disable)
Intf.ReqValid ##1 Intf.ReqValid |=> cov_disable = 1
);
But this is incorrect syntax. Is there a way to achieve something like this?

Some tools automatically disable a cover directive when it hits a certain limit. I know that in Questa, the default is disabling after 1 hit.
Also, you may get better performance modeling what you want with a simple implication
B2BReq : cover property (
#(posedge CLK iff !RESET)
Intf.ReqValid |-> ##1 Intf.ReqValid;
);
BTW, the syntax you were looking for was
bit cov_disable;
B2BReq : cover property (
#(posedge CLK iff !RESET) disable iff(cov_disable)
Intf.ReqValid ##1 Intf.ReqValid |=> (1,cov_disable = 1);
);

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

Usage of $past in System Verilog Assertions

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 |=>