How to pass information from inside sequence/property to the outside world - system-verilog

I have a property that is waiting for two different sequence to happen, as follows (the sequence and property are already simplified here):
sequence seq1;
logic [3:0] a;
#(posedge clk) (some_signal1 == 1, a = other_signal1);
endsequence
sequence seq2;
logic [3:0] b;
#(posedge clk) (some_signal2 == 1, b = other_signal2);
endsequence
property abc;
seq1 ##[1:$] seq2;
endproperty
some_signal1,some_signal2, other_signal1, other_signal2 are all RTL signals.
My question:
When the property abc is passed or covered, I want to know the corresponding other_signal1 and other_signal2 sampled in the sequences. How can I access those signals values?
I am thinking to hierarchically access the sequence local variables, such as seq1.a or seq2.b. But these are not allowed, as they are locals.
Declaring those variables as formal argument also does not help, because formal argument can not be assigned in the LHS.
My intention is that I am going to use those signals for other purpose, i.e.:
cover property (abc) begin
// grab seq1.a and seq2.b, and do some other tasks
end

You can do one of 3 things on the right of the comma inside the ( , ):
an assignment (to a local variable)
increment or decrement
call a tasks, task method, void function, void function method or system task.
(see IEEE1800-2012, 16.11 Calling subroutines on match of a sequence)
A task call is the key to this. You can assign to variables outside the task scope within a task called from within the sequence:
sequence seq1;
#(posedge clk) (some_signal1 == 1, assign_a(other_signal1));
endsequence
sequence seq2;
#(posedge clk) (some_signal2 == 1, assign_b(other_signal2));
endsequence
property abc;
seq1 ##[1:$] seq2;
endproperty
cover property (abc)
$display("a= %d, b= %d", a , b);
task assign_a(input int i);
a = i;
endtask
task assign_b(input int i);
b = i;
endtask
http://www.edaplayground.com/x/akw

Related

variable delay in assertions in System Verilog

I am a newbie learning System Verilog assertions and found a code online from verificationguide.com for variable delays in assertions. But I am unable to understand a few things.
Can someone elaborate on these following given descriptions?
// Copy variable value to the local variable.
(1,delay=v_delay)
How does this data gets copied?
// Decrements the value of the local variable and checks for the value of ‘delay’ equals ‘0’.
(1,delay=delay-1) [*0:$] ##0 delay <= 0
What does *0 mean? I know $ is for infinite checking till the end of the simulation. And why is ##0 needed as it just means 0 delay, if I am not wrong?
// waits for value of ‘delay’ equals to ‘0’
first_match((1,delay=delay-1) [*0:$] ##0 delay <=0)
How does the first_match function works and whats the syntax of it?
Please find the code below:
//-------------------------------------------------------------------------
// www.verificationguide.com
//-------------------------------------------------------------------------
module asertion_variable_delay;
bit clk,a,b;
int cfg_delay;
always #5 clk = ~clk; //clock generation
//generating 'a'
initial begin
cfg_delay = 4;
a=1; b = 0;
#15 a=0; b = 1;
#10 a=1;
#10 a=0; b = 1;
#10 a=1; b = 0;
#10;
$finish;
end
//delay sequence
sequence delay_seq(v_delay);
int delay;
(1,delay=v_delay) ##0 first_match((1,delay=delay-1) [*0:$] ##0 delay <=0);
endsequence
//calling assert property
a_1: assert property(#(posedge clk) a |-> delay_seq(cfg_delay) |-> b);
//wave dump
//initial begin
// $dumpfile("dump.vcd"); $dumpvars;
//end
endmodule
1) The sequence delay_seq has a variable cfg_delay which is passed from the property. That is actually assigned to v_delay, which is in turn assigned to the local variable delay.
2) *0 is called an empty match. For example a[*0:$] |-> b means
a [*0] or a [*1] or a [*2] .. a [$]
3) For example ($rose(b) ## [3:4] b) has two possible matches and ($rose(b) ## [3:$] b) can have infinite number of matches. To avoid unexpected behaviors because of multiple matches or cause an assertion to never succeed because all threads of antecedent must be tested for property to succeed. The first_match operator matches only the first of possibly multiple matches for an evaluation attempt and causes all the subsequent matches to be discarded.

system verilog expect behavior

I tried using expect with the following property
module tb;
logic a;
logic clk=0;
default clocking #(posedge clk); endclocking
always
#5ns clk = ~clk;
initial begin
$dumpfile("dump.vcd"); $dumpvars;
$display("START");
a = 0;
#100ns;
a = 1;
#100ns;
$finish;
end
initial begin
#10ns;
expect(#(posedge clk) 1 ##1 $changed(a) |-> 1) $display("SUCCESS"); else
$display("FAIL");
end
endmodule
Is the expect going to block until a change from 0 to 1 at 100ns ?
No, it will block until the second (posedge clk), regardless of the value of a, and will always pass.
The expect statement does not start evaluating the property until the first clk edge. The antecedent takes two cycle to either match or not match. Since the consequent is always true, the property passes on match. If there is no match, the property also passes, vacuously.

SV assertion based on event trigger

Assume SV interface contains a concurrent assertion property.
Is it possible to enable this assertion only when an event is triggered? I tried writing property inside a task in interface file, but I ended up with error: near "property": syntax error, unexpected property.
Interface intf;
task e1();
-> e1;
endtask
wait(e1.triggered); // something like this, where property waits for trigger
property prop1;
#(posedge clk) a ##1 b;
endproperty
endinterface
Thank you.
I think you need to consider that properties are best written synchronously and are evaluated on every clock cycle. You property says that one cycle after every clock cycle where a occurs b occurs. I guess what you're after is something like:
if e1 occurs, then a should be true (on the next rising edge of
clk?) and then b should be true on the rising edge of clk after
that
So, one way of doing that would be to create an always block that generates a pulse one clock wide should e1 occur, eg:
always begin
#(e1);
#(posedge clk) e = 1'b1;
#(posedge clk) e = 1'b0;
end
property prop1;
#(posedge clk) e |-> a ##1 b;
endproperty
or some variation of that. I feel like I should be worried about races, however.

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

$past with an input signal

I want to verify that if an event occurrs, then at “num_ticks” in the past, some signal should have been asserted.
As an example, the property I wrote is:
property test_past;
#(posedge clk)
$rose(gnt) |-> $past(req, num_ticks);
endproperty
The problem here is with num_ticks. If num_ticks is an input signal to the module in which the property is written, then the assertion fails. If I declare num_ticks as an int, and assign it to a constant, it passes.
Does $past only work for constant values? This is not mentioned in the LRM.
I am using Questasim 10.3
You might use multiple assertions for this purpose.
Suppose num_ticks is 4 bits wide, then you can do like this.
genvar x;
generate
for (x=0; x<16; x++)
begin
property test_past;
#(posedge clk)
(num_ticks == x) && $rose(gnt) |-> $past(req, x);
endproperty
end
endgenerate