Sequence which admits : No match v/s Hard Zero

I was referring to section 1.2 of “Understanding SV Degeneracy”

degen_seq:assert property( @(posedge clk) a ##0 b[*0] ) ; // Illegal as it is degenerate sequence

Since a degenerate sequence is equivalent to hard zero ( 0 ) , I tried the equivalent expression

hard_zero:assert property( @(posedge clk) (0) ) ; //  Why is the code legal ?

I observe that fail action block ( by default $error executes ) and instead of compilation error I observe run-time error.

Is there a difference between a sequence which admits ‘no_match’ v/s a sequence with a hard zero ?
Since both sequence won’t ever match shouldn’t there be a compilation error in both cases ?
According to 1800 is concurrent assertion ‘hard_zero’ legal ?

It depends on the context where the expression gets evaluated. Repetition expressions in an assertion need to be constant because they get evaluated at compilation. The compiler can check if the resulting code is semantically correct.

In the hard_zero assertion, the (0) does not get evaluated until run-time. At tool might do some optimizations to catch this at compile time, but no message is required.

Hi Dave,
A follow-up question

In the hard_zero assertion, the (0) does not get evaluated until run-time.A tool might do some optimizations to catch this at compile time, but no message is required.

What confuses me is that a tool is smart enough to detect at compilation time itself that ‘degen_seq’ is a degenerate sequence and throws a compilation error whereas for ‘hard_zero’ it is unable to interpret it as degenerate sequence.

It depends on the context where the expression gets evaluated.

From a strict LRM perspective, shouldn’t ‘hard_zero’ be considered a degenerate sequence ( since it won’t ever match ) ?
Ideally is it incorrect if a LRM compliant tool were to throw compilation error ?

For the hard_zero example - am sure a tool can throw an error, but the value/use of such SVA is quite rare and hence the R&D engineer maynot feel motivated to add that - very little ROI - IMHO. It gets bit more fancier once you have a signal instead of hard-coded-zero there (or `define/param - those can be statically computed prior to sim).

There are cases where I am glad that the tool doesn’t throw a compilation error for hard zero.

Intention :: Once signal ip_en ( clocked on sys_clk ) is asserted , ’ ip_clk ’ should not toggle .

( Ben suggests to use classic SV task for such scenarios )

 ip_clk_disable:assert property( @(posedge sys_clk) ip_en ##1 1 |=> @(ip_clk) 0 ) else `uvm_error( ... )

Since a tool may choose to exercise certain sections of the LRM while ignoring certain sections, I meant to ask from LRM perspective should SVA ‘hard_zero’ be treated as degenerate sequence
If yes, this would also mean that ‘ip_clk_disable’ is illegal as well and wouldn’t compile.

If that is not kosher, you can do this:

type or paste code here
ip_clk_disable:assert property( @(posedge sys_clk) ip_en ##1 1 |=> @(ip_clk) not(1) ) else `uvm_error( ... )

// also
ip_clk_disable:assert property( @(posedge sys_clk) ip_en ##1 1 |=>
seq #-# @(ip_clk) not(1)) else `uvm_error( ... )
Ben Cohen

Hi Ben,
Yes, there are possible alternatives to using hard 0 in SVA ( incase a tool throws compilation error )

// To trigger pass action block as well
ip_clk_disable2:assert property( @(posedge sys_clk) ip_en ##1 1 |=> @(ip_clk) 1 ##0 !(ip_en)   )
 `uvm_info(. .. ) else `uvm_error( ... )

One last question before I conclude the thread :
Based on 1800 ,16.12.22 Nondegeneracy

A sequence that admits no match or that admits only empty matches is called degenerate.

From a strict LRM perspective : Should SVA ‘hard_zero’ be treated as degenerate sequence ?
( as Dave and Srini have pointed that tools evaluate 0 at run-time with possible optimizations to catch it at compile time and we as users can’t expect tools to change their implementation )

I would say that “0” in a sequence represents ** A sequence that admits no match is called degenerate.**
I have an issue with

( @(posedge sys_clk) ip_en ##1 1 |=> @(ip_clk) not(1) ) 

because following the antecedent you are waiting for an occurrence of the (ip_clk), and that is when it fails.
But that @(ip_clk) will eventually occur in a time slot when that is OK. However, that assertion will fail.
You can do something like the following where the assertion would fail if ip_clk==1 one cycle afterthe antecedent.
The timing on that seqeunce needs to be adjustd to the needs.

sequence s; (@(posedge clk1) a ##1 b ##1 ip_clk); endsequence
ap_1: assert property(@(posedge clk1) reject_on(s.triggered) a ##1 b |=> 1); 

Thank you Dave,Srini and Ben.
To summarize
(1) 1800, 16.12.22 terms concurrent assertion ‘hard_zero’ as degenerate sequence .
(2) Tools seem to evaluate the (0) at run-time due to which the fail action block executes on each clocking event. Hence instead of compilation error ( since it’s degenerate ) we observe run-time error