Assertion failure using strong property

Hi Forum,

Consider the following concurrent assertions

`define FAIL(x) `"T:%0t x Fails`"

a1:assert property( @(posedge clk) seq_expr1 |=> seq_expr2 ) 
                                   else $display(`FAIL(a1),$time);

//  Assume  seq_expr3  is  boolean_expr[->1]
a2:assert property( @(posedge clk) seq_expr1 |=> strong( seq_expr3 ) ) 
                                   else $display(`FAIL(a2),$time);

Note that both concurrent assertions have the same antecedent.

Assume posedge of clock occurs at T0,T1,T2,โ€ฆTn and antecedent matches at T4

For a1 if the seq_expr2 doesnโ€™t match ( assuming that there are sufficient clock ticks )

then we observe $display(โ€œa1 Failsโ€œ)

i.e the user-defined message in fail action block associated with a1

If the consequent boolean_expr[->1] doesnโ€™t match till end of simulation then a2 fails

Does the user-defined message in fail action block $display(โ€œa2 Failsโ€œ) execute in this case

or is a default $error ( possibly tool dependent ) thrown ?

I referred LRM section 16.12.2 Sequence property for this but I donโ€™t see an explicit explanation for this case

Thanks

Iโ€™m making sure I understand the question properly. Here, weโ€™ve got something thatโ€™s expected to fail with a goto repetition. Boiling it down to something stupid, I think we could probably have:

a3: assert property (@(posedge clk) 1 |=> strong (0 [->1])) else $display("Boo");

Since 0 is never true, I think Iโ€™m convinced that the property isnโ€™t true, but Iโ€™m not an expert on liveness properties in simulation.

Thinking about it, we can boil things down even further to

a4: assert property (@(posedge clk) strong (0 [->1])) else $display("Boo");

(the implication doesnโ€™t really do anything).

Looking at the text of 16.12.2, I think the point is that the property wonโ€™t evaluate to true because there is no match for it before the end of the simulation.

But

If I understand the question, this isnโ€™t really a question about properties, but is rather a question about what happens when one fails at the end of a simulation?

Is the behaviour you see the same across EDA tools? With which one do you see it?

Across 3 EDA tools ( 2025 version ) I do observe the fail action block executing.

On 1 tool I see no output ( which possibly could be a tool limitation )

Hmm, that sounds like it might belong in a bug report :slight_smile: I canโ€™t see any obvious wiggle room for the tool vendor allowing the tool to do something unusual here.

Ben has shared his perspective on this topic :: linkedin.com/posts/ben-cohen

Thus, if $finish is executed in the Active region, it's a KILL switch as far as
simulation is concerned and all other regions are not executed.
However, the ๐˜€๐—ถ๐—บ๐˜‚๐—น๐—ฎ๐˜๐—ถ๐—ผ๐—ป ๐—ถ๐˜€ ๐˜€๐˜๐—ถ๐—น๐—น ๐—ฟ๐—ฒ๐˜€๐—ฝ๐—ผ๐—ป๐˜€๐—ถ๐—ฏ๐—น๐—ฒ ๐˜๐—ผ ๐—ฝ๐—ฟ๐—ผ๐˜ƒ๐—ถ๐—ฑ๐—ฒ ๐—ถ๐—ป๐—ณ๐—ผ๐—ฟ๐—บ๐—ฎ๐˜๐—ถ๐—ผ๐—ป ๐—ฎ๐—ฏ๐—ผ๐˜‚๐˜ ๐—ฎ๐—ป๐˜† ๐—ณ๐—ฎ๐—ถ๐—น๐˜‚๐—ฟ๐—ฒ ๐—ผ๐—ณ ๐—ฎ
๐˜€๐˜๐—ฟ๐—ผ๐—ป๐—ด ๐—ฝ๐—ฟ๐—ผ๐—ฝ๐—ฒ๐—ฟ๐˜๐˜† ๐˜๐—ต๐—ฎ๐˜ ๐—ฑ๐—ผ๐—ฒ๐˜€ ๐—ป๐—ผ๐˜ ๐—ฐ๐—ผ๐—บ๐—ฝ๐—น๐—ฒ๐˜๐—ฒ The action block need not be executed 
(tool option, IMHO).

As per LRM Pass / Fail action block executes in reactive region

LRM 9.2.3 Final procedures mentions

A final procedure executes when simulation ends due to an explicit or implicit call to $finish.
All final procedures shall execute in an arbitrary order.
No remaining scheduled events shall execute after all final procedures have executed.

This above quote tells me that once $finish() executes in active region,

the remaining regions in the same time step donโ€™t execute.

Execution of Fail action block ( as observed across 3 EDA tools ) means that reactive region does execute ( or maybe incomplete strong properties have an exception to the rule of remaining regions not executing once $finish executes )

Having referred LRM Sections 16.12.2 Sequence property and

16.12.15 Weak and strong operators,

I believe that the LRM doesnโ€™t explicitly mention whether the fail action block executes ( in reactive region of the same time step that $finish() is called ) when strong(boolean_expression[->1]) doesnโ€™t match till end of simulation

i.e if the strong( sequence ) โ€œ๐—ฐ๐—ฎ๐—ป๐—ป๐—ผ๐˜ ๐—ฏ๐—ฒ ๐—ถ๐—ฑ๐—ฒ๐—ป๐˜๐—ถ๐—ณ๐—ถ๐—ฒ๐—ฑ ๐—ฎ๐˜ ๐—ฎ ๐—ณ๐—ถ๐—ป๐—ถ๐˜๐—ฒ ๐˜๐—ถ๐—บ๐—ฒโ€

Also thank you @rswarbrick for your a3 / a4 examples .

It never occurred to me to try 0[โ€“>1] as sequence_expression :slightly_smiling_face:

Was surprised at first that itโ€™s not treated as No Match.

On writing itโ€™s equivalent expression itโ€™s clear that itโ€™s perfectly legal !!

The LRM is not clear in this context. It only defines the semantics of strong properties in terms of static formal tools, not dynamic simulation. And the description of $finish was written for Verilog before SystemVerilog add event regions.

I get different behaviors with this testcase with all simulators.

`define FINISH
module top;
  bit clk, a,b,d;
  initial repeat(20) #5 clk =!clk;
 
  assert property (@(posedge clk) $rose(a) |-> strong( b[->1]))
    $info("you passed"); else $error("you failed");
    
    initial begin 
      @(posedge clk) a<=1;
      @(posedge clk) a<=0;
      @(posedge clk) b<=1;
      @(posedge clk) b<=0;
      @(posedge clk) a<=1;
      @(posedge clk) 
      `ifdef FINISH
      $finish
      `endif
      ;
    end
    final $display("it's final");
endmodule

My expectation is that you should always be notified of a failure. However, whether the action block executes and in which region it occurs is debatable.

2 Likes

Hi Dave,

I was referring to your response in an older thread

I believe the strong operator isnโ€™t in effect for the attempt at T: 55.

Hence I wouldnโ€™t expect a failure at end of simulation at T: 55 ( on 3 eda tools I observe output as T:35 you passed )

Once $finish() executes in active region the observed region wouldnโ€™t execute i.e antecedent wouldnโ€™t match and as a result consequent would start evaluation ( hence strong operator wouldnโ€™t be active )

If I remove the `define FINISH at the top I observe the fail action block executing at T: 100 units ( across 3 EDA tools )

# run -all
# ** Info: T:35 you passed
#    Time: 35 ns Started: 15 ns  Scope: tb File: testbench.sv Line: 10
# exit
# ** Error: T:100 you failed