SVA (Ben Paper reference 2018) { hard} within ,firstmatch

Hi Ben,

I went through your submitted papers 2018

The requirements for the assertion as demonstrated in the photo uploaded
in the figure below, are:

  1. Upon a rose of go, data and valid is sent on a bus
  2. Data is independent of valid when the vld signal is true / false it can be any value be it true or false
  3. The checkresult is the result which only checks if either valid or data toggles atleast once when go is high and is asserted upon the fall of go

Google Photos

code tried

property p_c;

    @ (posedge clk)  $rose(go) |-> $rose(vld) or $rose(data) within ($rose(go) ##1 $fell(go) [->1]);

endproperty 
ap_c: assert property(p_c);

please provide your input now .I request

In reply to bhajanpreetsinght:
The difficulty you are having is that you are not expressing your requirements correctly.
Let me take a shot at it; you’ll then see that the assertions will easily be derived from that.

  1. Upon a rose of go, data and valid must change at least once when go==1; it may change more than once.
  2. Data is independent of valid; thus the activity of either are unrelated.
  3. When go==0 … you have not yet defined this. For now, well ignore it.

The use of the within is a good choice, but you have to understand its equivalency:
2.4.5 Sequence containment (within) The sequence containment within specifies a sequence occurring within another sequence.
(1) - EDA Playground // code
EPWave Waveform Viewer // wave


(seq1 within seq2) is equivalent to:  ((1[*0:$] ##1 seq1 ##1 1[*0:$]) intersect seq2 ) 
// The assertion 
 ap_go_data_vld: assert property( @(posedge clk) 
   $rose(go) |-> go && $changed(vld)[->1] or go && $changed(data)[->1] within 
                                  ($rose(go) ##1 $fell(go) [->1]))
                     pass=pass+1; else fail=fail+1; // for debug


Ben Cohen
Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.

or Links_to_papers_books - Google Docs

Getting started with verification with SystemVerilog

In reply to ben@SystemVerilog.us:

The difficulty you are having is that you are not expressing your requirements correctly.
Let me take a shot at it; you’ll then see that the assertions will easily be derived from that.

Upon a rose of go, data and valid must change at least once when go==1; it may change more than once.
Data is independent of valid; thus the activity of either are unrelated.
When go==0 … you have not yet defined this. For now, well ignore it.
The use of the within is a good choice, but you have to understand its equivalency:
2.4.5 Sequence containment (within) The sequence containment within specifies a sequence occurring within another sequence.

If we donot get anything that means data and valid is not toggling for not even once when go is high ,it should fail.

when go is 0 we should not check at all

The above one is working fines when there is one toggle or data or valid .

If there is not toggle it doesn’t stop.

In reply to bhajanpreetsinght:


 ap_go_data_vld: assert property( @(posedge clk) 
   $rose(go) |-> go && $changed(vld)[->1] or go && $changed(data)[->1] within 
                                  ($rose(go) ##1 $fell(go) [->1]))
                     pass=pass+1; else fail=fail+1; // for debug

Question: Why does the property (seq1 within seq2) not fail when seq1 is not a match?
In Evaluation. My previous response is incorrect
(seq1 within seq2) is equivalent to: ((1[*0:] ##1 seq1 ##1 1[*0:]) intersect seq2 )
For example, let seq2=1[*3]; let seq=0; then


((1[*0:$] ##1 seq1 ##1 1[*0:$]) intersect seq2 )  // get reduced to 
((1[*0:$] ##1 0 ##1 1[*0:$]) intersect 1[*3] )  
// the intesect occurs on the 3rd cycle with 
((1[*3] ##1 0 ##1 1[*0:$]) intersect 1[*3] )  // true, and never false
(1[*2] ##1 0  intersect 1[*3] // final reduction., yielding a NO MARCH 

Question: How can we write an assertion that detects seq1 is a no match (a failure)?
Actually, there is an issue with he ORing, and I am currently talking to my colleague on this.
FOr educational purposes, I am providing a solution with support logic.
Again, this should NOT be needed here.
The concept is to set a variable when seq1 occurs within seq2, and then check for that variable. The following fails to work because of SVA limitation, but it demonstrates the concepts.
(4) - EDA Playground // code
EPWave Waveform Viewer //wave


property p_changed_ILLEGAL;
     bit v; 
     @(posedge clk) $rose(go) |-> ((go && $changed(vld)[->1], v=1) within  
                                    ($rose(go) ##1 $fell(go) [->1])) 
                                      and $fell(go)[->1] ##0  v==1;
   Local variable v referenced in an expression where it does not flow.

To overcome this SVA issue, you can use a function call to set a module variable (or a static function variable) when seq1 is a match (or true if an expression). You can then check if that variable was set. You need to make sure that another attempt does not clobber taht variable. In this case, since you cannot have 2 consecutive rose(go) without a fall(g) that terminates the assertion, there is no issue here.
(4) - EDA Playground // code
EPWave Waveform Viewer //wave


 bit clk, go, vld, data, dbg;
  int pass1, fail1, pass2, fail2, covered; 
  function static bit achange(bit set, value);
     bit happened; // support logic
     if (set) happened=value;
     dbg=happened; // debug
     return happened;
  endfunction

   property p_changed;
     bit v; // v is used for syntax conformity, not by the assertion
     @(posedge clk)  ($rose(go), v=achange(1, 0)) |->
     (go && $changed(vld)[->1]  ##0 (1, v=achange(1, 1)) or
      go && $changed(data)[->1] ##0 (1, v=achange(1, 1)) within
      ($rose(go) ##1 $fell(go)[->1])) and 
     $fell(go)[->1] ##0 dbg; // achange(0,0);
    endproperty

    ap_go_data_vld2: assert property(p_changed)  
      begin pass2=pass2+1;  end else 
      begin fail2=fail2+1;  end // for debug

Note: If I made that function void with no return, then
there is no need for the property local variable
(5) - EDA Playground // code
EPWave Waveform Viewer // wave


function void achange(bit set, value);
     bit happened; // support logic
     if (set) happened=value;
     dbg=happened; // debug
     //return happened;
  endfunction

   property p_changed;
     //bit v; // v is used for syntax conformity, not by the assertion
     @(posedge clk)  ($rose(go), achange(1, 0)) |->
     (go && $changed(vld)[->1]  ##0 (1, achange(1, 1)) or
      go && $changed(data)[->1] ##0 (1, achange(1, 1)) within
      ($rose(go) ##1 $fell(go)[->1])) and 
     $fell(go)[->1] ##0 dbg; //
    endproperty
    ap_go_data_vld2: assert property(p_changed)  
      begin pass2=pass2+1;  end else 
      begin fail2=fail2+1;  end // for debug

A 3rd option is to use a task with fork-join_any called upon a rose(go) as
described in my paper on Understand SVA.
Ben Cohen
Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.

or Links_to_papers_books - Google Docs

Getting started with verification with SystemVerilog

In reply to ben@SystemVerilog.us:

OK, The within works, but something is going on with the or


// Works OK 
ap_go_data_vld: assert property( @(posedge clk)
          $rose(go) |-> go && $changed(vld)[->1] // or  go && $changed(data)[->1]
           within
         ($rose(go) ##1 $fell(go) [->1])) pass1=pass1+1; else fail1=fail1+1; // for debug

(5) - EDA Playground // Code
EPWave Waveform Viewer // wave

In reply to ben@SystemVerilog.us:

Hi Ben,

Thanks for the reply

I want to ask the requirement of assertion as follows:

1:Upon a rose of all idles, we should check for that they remain high for dynamic number of clockedges which is defined by variable logic [7:0] dynamic .
2.if this condition passes we will check for variable clockgate/clock_en to be zero…
2. if it fails at any clock edge suppose dynamic clock edge value is 14 and one of the idles toggle to zero,the assertion shoul fail at the next clockedge no moving forward.

3.clockgate variable is directly related to clock_en that is if clock_en goes low it goes low immediately

code tried
sequence sq_rpt_simple_count(sq, count);
int v=count;
(1, v=count) ##0 ( v>0 ##0 sq, v=v-1) [1:$] ##0 v<=0;
endsequence // sq_rpt_simple_count
module m;
import sva_delay_repeat_range_pkg::
;
bit clk, a, b, c, d, e, w;
int duration;

sequence q_abcde; @(posedge clk) a && b && c && d && e; endsequence
assert property(@(posedge clk)
q_abcde ##0 sq_rpt_simple_count(q_abcde,duration) |-> q_abcde ##1 clk_en==0;
endmodule

This code is working fine ,but it doesn’t catch the error which it should suppose all idles are not high during the whole duration of dynamic variable ,but it catches after the certain number of clock edge and requirement is to comes out immediately if either of a,b,c,d,e is not high representing idle or clock_en suddenly goes low in the period when all a,b,c,d,e are high.

Request you to add a control to catch to catch a scenario if either of a,b,c,d,e which are idle goes low after going to high.it should stop immediately and also in the mean time check for clock_enable to be zeroif either of condition happens it should show error.

so variable a,b,c,d,e are all idles

clock_en and clockgated signals are related to each other directly as clock_en goes low it goes low .

In reply to ben@SystemVerilog.us:
GOT THE or ISSUE resolved!
Requirements: Upon a go, vld or data can change at any cycling until fell of go (but not at the cycle of the fall of go. When I use (go && $changed(vld)[->1]) or (go && $changed(data)[->1]) on the RHS of the within, the assertion does not failThe issue is precedence. 1800 Table 16-1—Operator precedence and associativity
shows that the within has higher precedence than the or. Thus, my assertion was interpreted

as ap_go_data_vld: assert property( @(posedge clk)
          $rose(go) |-> (go && $changed(vld)[->1]) or 
                        (go && $changed(data)[->1]  within
         ($rose(go) ##1 $fell(go) [->1])) ) pass1=pass1+1; else fail1=fail1+1; // for debug
   The RHS of the or fails when no data change in the within window. 
   The LHS of the or evaluates at every cycle and does not complete or fail unless I have a strong(sequence) that makes it a property. 

// (5) - EDA Playground // code
// EPWave Waveform Viewer // wave


module top;
timeunit 1ns;
timeprecision 100ps;
bit clk, go, vld, data, dbg;
int pass1, fail1, pass2, fail2, covered; 
initial forever #1 clk=!clk;
ap_go_data_vld: assert property( @(posedge clk)
    $rose(go) |-> ((go && $changed(vld)[->1]) or 
                   (go && $changed(data)[->1])) within
       ($rose(go) ##1 $fell(go) [->1])) pass1=pass1+1; else fail1=fail1+1; // for debug
  
ap_go_data_vld2a: assert property( @(posedge clk)
 $rose(go) |-> 
  (go && $changed(vld)[->1])  within ($rose(go) ##1 $fell(go) [->1]) or
  (go && $changed(data)[->1]) within ($rose(go) ##1 $fell(go) [->1]))
     pass1=pass1+128; else fail1=fail1+128;