1
votes

Quoting from a book "Systemverilog Assertions and Functional Coverage", Ashok Mehta on page 42,

@ (posedge clk) a |=> !a; In the above sequence, let us say that variable ‘a’ changes to ‘1’ the same time that the sampling edge clock goes posedge clk (and assume ‘a’ was ‘0’ before it went to a ‘1’). Will there be a match of the antecedent ‘a’? No! Since a’ went from ‘0’ to ‘1’ the same time that clock went posedge clk, the value of ‘a’ sampled by clock will be ‘0’ (preponed region) and not ‘1’. This will not cause the property to trigger because the antecedent is not evaluated to be true. This will confuse you during debug. You would expect ‘1’ to be sampled and the property triggered thereof. However, you will get just the opposite result. This is a very important point to understand because in a simulation waveform (or for that matter with Verilog $monitor or $strobe) you will see a ‘1’ on ‘a’ with posedge clk and would not understand why the property did not fire or why it failed (or passed for that matter). Always remember that at the sampling edge, the ‘previous’ value (i.e. a delta before the sampling edge in the preponed region) of the sampled variable is used.

I tried to test this scenario by this Testbench. However I expected assertion to FAIL at simulation times #10, #50, #90

module assert_immediate();

      reg  a,b,clk;

      initial
      begin
        clk = 0;
        forever #10 clk = !clk;
      end

      initial
      begin
        a = 0;
        b = 0;
        repeat (10) @(posedge clk) a = ~a;
      end

     // always@(posedge clk) $display("a = %d at time %t \n", a, $time);

      property p1;
         @(posedge clk) a |=> !a;
      endproperty

      initial #100 $finish;

      assert property (p1) $display("Entered assert at %t \n", $time); else $display("FAIL at %t \n", $time);
      cover property (p1) $display("PASS at %t \n", $time);

endmodule

But when I ran on EDAPlayground using VCS, I got a different behavior

# KERNEL: Entered assert at                   10 
# KERNEL: 
# KERNEL: PASS at                             10 
# KERNEL: 
# KERNEL: Entered assert at                   50 
# KERNEL: 
# KERNEL: Entered assert at                   50 
# KERNEL: 
# KERNEL: PASS at                             50 
# KERNEL: 
# KERNEL: PASS at                             50 
# KERNEL: 
# KERNEL: Entered assert at                   90 
# KERNEL: 
# KERNEL: Entered assert at                   90 
# KERNEL: 
# KERNEL: PASS at                             90 
# KERNEL: 
# KERNEL: PASS at                             90
2
What is your expected behavior?Karan Shah
@KaranShah Expected behavior is Entered assert at 10 and PASS at 10 should not be printed.Shankhadeep Mukerji
Yes. Agreed. It seems like a tool bug, as the concurrent assertion samples value from the preponed region and hence @10, the sampled value of a should be 0.Karan Shah

2 Answers

0
votes

I think that there are 2 issues there.

  1. I think that there is a misconception in the implication operator. Assertion should not fail in your case. The implication allows for the right hand side expression to be true eventually. So, if a goes up, it will eventually go down. So, at #50 it goes down after sampled high at #30, and this cause the assertion to pass, and go to the next cycle of evaluation: #70 -> #90.

For each successful match of the antecedent sequence_expr, the consequent property_expr isseparately evaluated. The end point of the match of the antecedent sequence_expr is the start pointof the evaluation of the consequent property_expr.

  1. there is a bug in the compiler you use. There should be no assertion message at time #10. I tried it with vcs 2017.03 and it worked correctly.

also you can add this line to you code to get some debugging prints:

always @(posedge clk) $display("%0t a = %b", $time, $sampled(a));

I got these results during the simulation:

10 a = 0
30 a = 1
50 a = 0
Entered assert at 50
PASS at           50
70 a = 1
90 a = 0
Entered assert at 90
PASS at           90
1
votes

Why do you expect your assertion to fail? You instructed your testbench to change a every posedge in the initial block so your assertion will pass when triggered (you will have a sequence of a, !a, a, !a) so I expect 2 assertion passes.

What I don't understand is that assertion passes @ time 10 according to your log. Your first posedge is @ time 10, so the sampled value of a is 0 (because sampling is done before the posedge and your initial value of a is 0 accroding to the initial block). This value of a wouldn't trigger the assertion (doesn't meet assertion predecessor, i.e. left hand side of the assertion).