Hi,
I was trying to summarize on different ways on how leading clock is inferred in SVA
Using default clocking block
default clocking cb1 @(posedge clk); endclocking
sequence sr1;
a ##2 b ;
endsequence
property pr1;
c |=> sr1;
endproperty
ap1:assert property(pr1);
Specifying clock in sequence
sequence sr1;
@(posedge clk) a ##2 b ;
endsequence
property pr1;
c |=> sr1;
endproperty
ap2:assert property(pr1);
Specifying clock in property
sequence sr1; // Infers the clock from pr1
a ##2 b ;
endsequence
property pr1;
@(posedge clk) c |=> sr1;
endproperty
ap3:assert property(pr1);
Clock Inferred from always block
sequence sr1; // Infers the clock from pr1
req ##2 gnt ;
endsequence
property pr1; // Infers the clock from always block
cStart |=> sr1;
endproperty
always@(posedge clk)
ap4:assert property(pr1);
Clock inferred from forever block
sequence sr1;
req ##2 gnt ;
endsequence
property pr1;
cStart |=> sr1;
endproperty
initial begin
forever @(posedge clk) begin
ap5:assert property(pr1);
end
end
I notice that (2) and (5) are illegal whereas (1),(3) and (4) are legal.
[Q1] I am curious to know what makes (2) and (5) illegal ?
(a) For (2) , why doesn’t property pr1 inherit the clock from sequence sr1 ?
(b) For (5) , similar to inheriting the clock from always block , why isn’t the clock inherited from forever block ?
[Q2] Are there any other legal ways to specify/infer the leading clock ?
[Q3] Do the same rules apply for cover property as well ?
In reply to Have_A_Doubt:
I think this has been specified in 16.16 Clock resolution in IEEE std 1800 2017 as follows:
There are a number of ways to specify a clock for a property. They are as follows:
— Sequence instance with a clock, for example:
sequence s2; @(posedge clk) a ##2 b; endsequence
property p2; not s2; endproperty
assert property (p2);
— Property, for example:
property p3; @(posedge clk) not (a ##2 b); endproperty
assert property (p3);
— Contextually inferred clock from a procedural block, for example:
always @(posedge clk) assert property (not (a ##2 b));
— A clocking block, for example:
clocking master_clk @(posedge clk);
property p3; not (a ##2 b); endproperty
endclocking
assert property (master_clk.p3);
— Default clock, for example:
default clocking master_clk ; // master clock as defined above
property p4; (a ##2 b); endproperty
assert property (p4);
As For Q1:
(a) For 2, there is a variable c has been used and there is no clock defined for this variable, so if you remove it from pr1, it should be legal.
(b) For 5, forever isn’t a procedural block.
For Q2 and Q3: As mentioned, there is nothing mentioned about whether the directive you’re using (assert, cover, …) will affect the clock resolution or not. So it’s fair to say that the rules still apply.
1800’2017: 16.16 Clock resolution addresses this topic.
1) Using default clocking block: LEGAL
default clocking cb1 @(posedge clk); endclocking
sequence sr1; a ##2 b ; endsequence
property pr1; c |=> sr1; endproperty
ap1:assert property(pr1); // LEGAL
**2) Specifying clock in sequence: LEGALITY DEPENDS ON USE/b]
See embedded comments
sequence sr1; @(posedge clk) a ##2 b; endsequence
property pr1; c |=> sr1; endproperty
ap2:assert property(pr1); // ILLEGAL
// Illegal because c has no leading clocking event (LCE)
// the clocking event in sr1 does not flow backwards
//-----------
property pr2; sr1 |-> c; endproperty
// Directive 'ap2' has un-clocked expressions or constructs. Please fix
ap2b:assert property(pr2); // ILLEGAL
// The clocking event in sr1 does not flow out of the sequence
//--------------
sequence s2; @(posedge clk) a ##2 b; endsequence
property p2; not s2; endproperty
assert property (p2); // LEGAL because the s2 has a LCE
[b]Specifying clock in property: DEPENDS**
sequence sr1; a ##2 b ; endsequence
property pr1; @(posedge clk) c |=> sr1; endproperty
ap3:assert property(pr1); LEGAL
// Clocking event in property is the LCE and
// it flows into sr1. It cannot flow out of the sequence
// but can flow into sequences following the sr1
property pr1b; @(posedge clk) c |=> sr1 ##1 d; endproperty
// -----
sequence sq; a ##2 b ; endsequence
property p1x; @(posedge clk) c |=> sq; endproperty
property p2x; @(posedge clk2) c |=> a ##1 sq; endproperty
ap3:assert property(pr1); // LEGAL
ap4: assert property(p1 implies p2x);// illegal
// Directive 'ap3' has un-clocked expressions or constructs
sequence sr1b; req ##2 gnt ; endsequence
property pr1b; cstart |=> sr1; endproperty
initial begin
forever @(posedge clk) begin
// The sva directive is not sensitive to a clock. .
// Procedural assertion ( i.e., assert, assume or cover property) is not
// allowed in looping statement.Only immediate assertions are allowed in this
ap5:assert property(pr1b);
The same rules do apply for cover property as well ?
Ben Cohen Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.
I couldn’t find anything in the 2017 LRM that justifies your comment in number [5]
// Procedural assertion ( i.e., assert, assume or cover property) is not
// allowed in looping statement.
Could you point me to the section where that is explained? As I’ve tried the following code and it seems like it’s legal. in the below code always_asrt (defined in always block) is equivalent to forever_asrt (defined in a loop).
I couldn’t find anything in the 2017 LRM that justifies your comment in number [5] // Procedural assertion ( i.e., assert, assume or cover property) is not
// allowed in looping statement.
1800’21017: 16.16
— Contextually inferred clock from a procedural block, for example:
always @(posedge clk) assert property (not (a ##2 b));
1800:2017 Clause 9 describes the SystemVerilog **procedural blocks**:
initial, always, always_comb, always_ff, always_latch, and final.
9.2 Structured procedures All structured procedures in SystemVerilog are specified within one of the following constructs:
— initial procedure, denoted with the keyword initial (see 9.2.1 )
— always procedure, denoted with the keywords: • always (see 9.2.2.1 )
• always_comb (see 9.2.2.2 )
• always_latch (see 9.2.2.3 )
• always_ff (see 9.2.2.4 )
— final procedure, denoted with the keyword final (see 9.2.3)
— Task
— Function
The syntax for these structured procedures is shown in Syntax 9-1 )
I’ve tried the following code and it seems like it’s legal. in the below code always_asrt (defined in always block) is equivalent to forever_asrt (defined in a loop).
You touched on tool issues, and we don’t discuss tools in this forum.
If you have a problem, contact your vendor.
In any case, 1800 is specific as to what is a procedural block.
//----------------------//
initial begin
forever @(posedge clk)begin
forever_asrt: assert property(forever_pp); // line 28
end
end
sim: Error-[PAOCNAILS] Procedural assertion in a loop
testbench.sv, 28
test, "assert property(forever_pp);"
Procedural assertion ( i.e., assert, assume or cover property) is not
allowed in looping statement.Only immediate assertions are allowed in this
context.
In reply to ben@SystemVerilog.us:
Note that the following is also ILLEGAL even if you have a Leading Clocking Event (LCE)
initial begin
forever @(posedge clk)begin
forever_asrt: assert property( @(posedge clk) forever_pp);
end
end
"assert property(@(posedge clk) forever_pp);"
Procedural assertion ( i.e., assert, assume or cover property) is not
allowed in looping statement. Only immediate assertions are allowed in this
context.
1800’2017: 9.2 Structured procedures All structured procedures in SystemVerilog are specified within one of the following constructs:
— initial procedure, denoted with the keyword initial (see 9.2.1 )
— always procedure, denoted with the keywords: • always (see 9.2.2.1 )
• always_comb (see 9.2.2.2 )
• always_latch (see 9.2.2.3 )
• always_ff (see 9.2.2.4 )
— final procedure, denoted with the keyword final (see 9.2.3)
— Task
— Function
I think you might misunderstood my question, I am not saying forever is a procedural block. I know it’s not. 2017 LRM section 16.16 is about clock inference, and it doesn’t say anything about the illegality of forever_asrt statement in the following code
module test;
bit clk;
bit a,b;
default clocking @(posedge clk); endclocking
always #1 clk = ~clk;
//----------------------//
property forever_pp;
a |-> b;
endproperty
//----------------------//
initial begin
forever @(posedge clk)begin
forever_asrt: assert property(forever_pp);
end
end
//----------------------//
initial begin
#2 a=1; b=0;
#20 $finish;
end
So my question is which section in the LRM says using
So my question is which section in the LRM says using assert property is illegal in a looping statement?
You are correct, 1800 does not specifically say that it is illegal for looping statements.
The following reasons, based on SV rules, are possibly why one vendor is enforcing this restriction:
Unrolling errors:
Concurrent asserts are essentially static objects; if they are placed in a loop, the loop would have to be either unrolled or the assertion placed in an equivalent generate loop. For example: Edit code - EDA Playground
always @(posedge clk) begin
for (int i=0; i<=3; i++) begin
assert property(a|-> b);
// ILLEGAL: Range must be bounded by constant expressions.
ap_arbiter: assert property(@(posedge clk)
(req[i]==1'b1) ##0 req[i:0] !=0 |=>
grnt[i]==1'b1 ##0 $onehot(grnt) );
end
end
One could say, yah, but the following should be legal if I change req[i:0] to req[i]
always @(posedge clk) begin
while(c==1) begin // ifinite loop
assert property(a|-> b);
end
end
// System virtual memory limit exceeded -
We have the same issue with the forever
Getting back to the question: Should looping allowed in an always, always_ff?
Maybe there is a philosophical or inference reason for a tool to put such a code constraint because it can cause trouble or implementation issues.
1800 16.16 and 16.16.1 exhaustively go thru al the rules for inferred leading clocking event (LCE). It is tiresome to read and fully comprehend. Byt in simple terms, and as a guideline, if the property does not have a clocking event then the inferred LCE is only in an always in the style of always @(clocing_event)
Just stick to this rule if you do not want to include the clocking event in the assertion.
You’re making life too complicated if you violate simple design rules; and that is true for SV in general. Funky stuff can lead to funky behavior.
Ben
property pr1; a ##2 b; endproperty
always@(posedge clk) begin
if ( bstate ) begin
@(negedge regcheck);
assert property( pr1 ); // ERROR! No leading clocking event (LCE)
end
end