Modeling Variable Delay ( ##[readLatency] )

Using a variable as #Delay is Illegal i.e


 property  read_latency_check ;
  int  Ldelay ;           
   $fell( rd_ )  |->  ##[readLatency] ( read_data == expected_data ) ;
endproperty 

One Possible Solution I observe in the book I am referring is :: EDA_LINK1 .

However I have a few questions regarding the O/P and the Solution .

[Q1] I expect the assertion to Pass at TIME : 65 , however I observe different O/P across Simulators .

[Q2] The possible solution isn’t similar to ##[readLatency] in the sense that the Consequent is evaluated after 6 clock ticks whereas variable ’ readLatency ’ is 5 .

   Shouldn't  I  write  ::  **##1  ( Ldelay == 1 )  instead  of  ##1  ( Ldelay == 0 )**

[Q3] Why do I observe “Ldelay is -1” ? Shouldn’t the first_match decrement the variable ’ Ldelay ’ till it’s 0 ?

[Q4] Apart from the above solution as a counter , is there any alternate possible solution ?

In reply to hisingh:
See my package at
https://verificationacademy.com/forums/systemverilog/sva-package-dynamic-and-range-delays-and-repeats

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
** SVA Handbook 4th Edition, 2016 ISBN 978-1518681448

  1. SVA Package: Dynamic and range delays and repeats SVA: Package for dynamic and range delays and repeats | Verification Academy
  2. Free books: Component Design by Example FREE BOOK: Component Design by Example … A Step-by-Step Process Using VHDL with UART as Vehicle | Verification Academy
    Real Chip Design and Verification Using Verilog and VHDL($3) https://rb.gy/cwy7nb
  3. Papers:

Udemy courses by Srinivasan Venkataramanan (http://cvcblr.com/home.html)
https://www.udemy.com/course/sva-basic/
https://www.udemy.com/course/sv-pre-uvm/

In reply to ben@SystemVerilog.us:

Ben ,

I tried the solution using sequence ’ dynamic_delay ’ from your package .

It works as intended :: EDA_LINK2

However I am trying to understand the following part ::


( (1, v=count) ##0 ( v>0, v=v-1 , $display("TIME : %2t v is %0d " , $time , v ) ) [*0:$] ##1 v<=0 ) ;

The initialization occurs when sequence is invoked ( TIME : 5 in my case ) .

Then the 1st increment occurs at same time at TIME : 5 .

As *##0 ( v>0, v=v-1 ) [0:$] is infinite sequence which has 0 delay between the 2 consecutive decrement , how is it that the decrement occurs at each clock edge ?

In reply to hisingh:


1)  a ##0 b[*3] ##1 c
2)  a ##0 b ##1 b ##1 b ##c
// 1 & 2 are similar 

( (1, v=count) ##0 ( v>0, v=v-1 , $display("TIME : %2t v is %0d " , $time , v ) ) [*0:$] ##1 v<=0 ) ; 
//so here 1 cycle delay between the 2 consecutive decrement

( v>0, v=v-1 ) [*0:$]
//This isn't infinite sequence as v have finite value 
//This will stop when v>0 condition isn't true  


https://www.linkedin.com/in/patel-rahulkumar/

In reply to Rahulkumar:

Thanks .

In reply to ben@SystemVerilog.us:

Ben ,

A final question regarding the Original Code ( Trying to document in my notes )
Based on your code I change the property to ::


 property  read_latency_check ;
   int  Ldelay ;   
        
   ( $fell( rd_ ) , Ldelay = readLatency )  ##0   //  Changed  to  ##0  from  ##1 
   
   first_match(  ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) ) [*0:$]  
     
                 ##1  ( Ldelay == 0 )  )                                                               
   
   ##0 ( 1 , $display("TIME : %2t  Antecedent  is  True ", $time ) ) |->  ( read_data == expected_data ) ; 
          
 endproperty 

If I were to expand the expression within the first_match ::


 ( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*0] ##1  ( Ldelay == 0 )  )  or

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*1] ##1  ( Ldelay == 0 )  )  or

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*2] ##1  ( Ldelay == 0 )  )  or

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*3] ##1  ( Ldelay == 0 )  )  or

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*4] ##1  ( Ldelay == 0 )  )  or

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*5] ##1  ( Ldelay == 0 )  )  or

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*6] ##1  ( Ldelay == 0 )  )  or

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*7]  ##1  ( Ldelay == 0 )  )  or  ..............
 

Which of these would the antecedent be True for ’ readLatency = 5 ’ ?

I  am  confused  between  the  following  two ::

(a)  ( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*5] ##1  ( Ldelay == 0 )  )

(b)  ( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*6] ##1  ( Ldelay == 0 )  )        
 

Via (a) Ldelay gets decremented to 0 such that after 1 clock ( Ldelay == 0 ) is True .

Via (b) Ldelay gets decremented to -1 but after 1 clock ( Ldelay == 0 ) isn’t True .

In reply to hisingh:


// Ldelay==5 
// Ldelay==5
  ( ( 1 , Ldelay-- )[*0] ##1  ( Ldelay == 0 )  )  or // Ldelay==4 
  // is equivalent to 
  (  ##0  ( Ldelay == 0 )  )  or // Ldelay==5 
//  expression[*0] ##1 expr1 is same as  ##0 expr1
  ( ( 1 , Ldelay-- )[*1] ##1  ( Ldelay == 0 )  )  or  // Ldelay==4  
  ( ( 1 , Ldelay-- )[*2] ##1  ( Ldelay == 0 )  )  or  // Ldelay==3   
  ( ( 1 , Ldelay-- )[*3] ##1  ( Ldelay == 0 )  )  or  // Ldelay==2   
  ( ( 1 , Ldelay-- )[*4] ##1  ( Ldelay == 0 )  )  or  // Ldelay==1   
  ( ( 1 , Ldelay-- )[*5] ##1  ( Ldelay == 0 )  )  or  // Ldelay==0
// Which of these would the antecedent be True for ' readLatency = 5 ' ?
// This one  ( ( 1 , Ldelay-- )[*5] ....

This one:
(a) Ldelay gets decremented to 0 such that after 1 clock ( Ldelay == 0 ) is True .
Your property has issues:


// What if readLatency is 0? then Ldelay == 0 will never be reached? 
property  read_latency_check ;
    int  Ldelay ;     
    ( $fell( rd_ ) , Ldelay = readLatency )  ##0   //  Changed  to  ##0  from  ##1   
    first_match(  ( 1 , Ldelay-- ) [*0:$]    ##1  ( Ldelay == 0 )  )   
         |->  ( read_data == expected_data ) ; 
  endproperty 

// Use my sequence
sequence dynamic_delay(count);
    int v;
  (count<=0) or ((1, v=count) ##0 (v>0, v=v-1) [*0:$] ##1 v<=0);
endsequence // dynamic_delay 


In reply to ben@SystemVerilog.us:

Ben , I am trying to understand the execution of $display for value of readLatency as 5 and 0 ::


  $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay )
  

(1) Since (a) is True

( ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) )[*5] ##1  ( Ldelay == 0 )  )

,
*why is it that I Observe “Ldelay is -1” . I understand the expression ( 1 ) is always True
but due to [5] shouldn’t Ldelay be decremented 5 times till 0 ?

(2) In my property if Ldelay is 0 , the following antecedent expression is True ::


//  ( $fell( rd_ ) , Ldelay = readLatency )  ##0( ( 1 , Ldelay-- )[*0] ##1  ( Ldelay == 0 ) )
//    Is  equivalent  to  :: 
   ( $fell( rd_ ) , Ldelay = readLatency )  ##0  ( Ldelay == 0 ) ; 
     

So the assertion Passes at TIME : 5 i.e 0 clock tick after $fell( rd_ ) is True i.e Same Clock tick

( The same O/P I observe when using your sequence :: EDA_LINK2 )

Due to *[0] I expected that $display(" … Ldelay is …") won’t execute .

However I still observe “Ldelay is -1” in O/P :: EDA_LINK3 .

Any suggestions why is it so ?

In reply to hisingh:
As I said before:
*expression[0] ##1 expr1 is same as ##0 expr1
Thus, with the code below with readLatency = 0


(1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) ) [*0] 
// The display shows Ldealy to -1 
// HOWEVER, the local variable Ldealy is NOT modified because of the [*0] 
// Thus in the same cycle Ldelay is still 0 
         ##1  ( Ldelay == 0 ), $display("TIME : %2t  after the Ldelay==0, Ldelay=  is  %0d ", $time , Ldelay)   )

int readLatency = 0;
  property  read_latency_check ;
    int  Ldelay ;    
    ( $fell(req ) , Ldelay = readLatency )  ##0   //  Changed  to  ##0  from  ##1   
    first_match(  ( 1 , Ldelay-- , $display("TIME : %2t  Ldelay  is  %0d ", $time , Ldelay ) ) [*0:$]    
                  ##1  ( Ldelay == 0 ), $display("TIME : %2t  after the Ldelay==0, Ldelay=  is  %0d ", $time , Ldelay)   )    
    ##0 ( 1 , $display("TIME : %2t  Antecedent  is  True ", $time ) ) |->  ( 1 ) ;   
  endproperty 
  ap_read_latency_check: assert property(@(posedge clk) read_latency_check);  
/* SIm results (in reverse order )
# TIME : 500  Antecedent  is  True 
# TIME : 500  after the Ldelay==0, Ldelay=  is  0 
# TIME : 500  Ldelay  is  -1  */ 

My apologies on my mistake
What if readLatency is 0? then Ldelay == 0 will never be reached?
I was wrong. above is the right explanation.

In reply to ben@SystemVerilog.us:

Thanks Ben .
As you pointed Ldelay is actually never decremented to -1 , although we do observe the fake report