Assertion to calculate ON and OFF period of signal based on the configuration

Hi,

I am experiencing difficult implementing in assertions where as in SV feels easy.
Can any one suggests better way of doing for the below requirement with assertions?
i am not able to paste the picture here. so i explained below.

Qn: I have a signal “A” which has ON and OFF periods. there is another signal “cnt[3:0]” which tells how many pulses can be in the signal “A”. and the signal “cnt_no” represents which pulse is currently active.

A signal can have max of 32 pulses from 0 to 31. so there will be total 32 Ton and Toff periods. So each Ton and Toff periods are
are configured by register values for ex: reg1[32:0] in which reg[11:0] represents Ton of first pulse of A and reg1[12:23] represents toff of first pulse of signal “A”.similarly there are other registers which represents different Ton and Toff of each pulse of signal “A”.

My requirement is that i need to calculate the Ton and Toff of specific pulse based on cnt_no and compare it corresponding register configured values i.e reg1[11:0] for pulse 0 of “A” and reg2[12:23] for pulse 1 of “A” and so on.

may i know how can i write generic assertion code for this case?

Thanks

In reply to muralidar:

Keep in mind that an assertion is a statement that a property is true. SVA is just a notation / language that facilitates the coding. When you say “whereas in SV feels easy”, I suggest that you use SV, probably with concurrent tasks if you want to emulate concurrency.

I failed to fully understand your requirements. If you show your SV code, I maybe able to translate it to SVA.
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


In reply to ben@SystemVerilog.us:

Hi Ben,
Below is my sample SV code for my requirement.
I need to calculate the width of the particular pulse of signal A and should compare with the particular register based on cnt no.so here cnt_no can be 1 to 32;
Please help how can i write generic assertion code for this.

module TB;
int bit[3:0] cnt;
int v_t, v_t_hi;
bit [31:0] cnt_reg_1;
bit [31:0] cnt_reg_2;
always @(posedge A) begin
v_t = $realtime;

@(negedge A) 
v_t_hi = $realtime-v_t;
cnt++;
if(cnt ==0) 

if (v_t_hi == cnt_reg_1[11:0])
 begin
 $display("Error in matching reg value");
end
if(cnt == 1)
if(v_t_hi == cnt_reg_1[12:23])
 begin
 $display("Error in matching reg value");
end
if(cnt ==2)
if (v_t_hi == cnt_reg_2[11:0]) begin
 $display("Error in matching reg value");
end
if(cnt ==3)
if(v_t_hi == cnt_reg_2[12:23]) begin
 $display("Error in matching reg value");
end
end

endmodule

Please help.

In reply to muralidar:
I used your model as a guideline. Usually, in assertions, clocks are used to sample signals. You used events on A, instead of sampling A based on a clock.
The model I wrote seems to do what you want. I used the sequence_match_item with a function call to do the last calculations. Also, realtime is real, the count is integer. I did a type cast.


/*I need to calculate the width of the particular pulse of signal A and 
should compare with the particular register based on cnt no.so here cnt_no can be 1 to 32;
Please help how can i write generic assertion code for this. */ 
import uvm_pkg::*; `include "uvm_macros.svh" 
module TB;
  bit clk, A;
  // default clocking @(posedge clk); endclocking
  initial forever #10 clk=!clk;  
  bit[3:0] cnt;
  int v_t, v_t_hi;
  bit [31:0] cnt_reg_1=32'H12345678;
  bit [31:0] cnt_reg_2=32'H9ABCDEF0;
     
    function void check_cnt(realtime vt_hi); 
    	automatic int vthi;
    	vthi=int'(vt_hi);  // Casting needed? Better practice!
    	cnt++; 
    	if(cnt ==0) 
    		a0: assert(vthi == cnt_reg_1[11:0]);
    	if(cnt == 1)
    		a1: assert(vthi == cnt_reg_1[23:12]);
    	if(cnt ==2)
    		a2: assert(vthi == cnt_reg_2[11:0]);
    	if(cnt ==3)
    		a3: assert(vthi == cnt_reg_2[23:12]);		 	 
    endfunction : check_cnt  
	
    property p_width; 
    	realtime  v_t, v_t_hi;
    	@(posedge A) (1, v_t    = $realtime)  ##0 	
    	@(negedge A) (1, v_t_hi = $realtime-v_t, check_cnt(v_t_hi));	
    endproperty 
    cover property(p_width); 
	
    initial begin 
    	repeat(200) begin 
    		@(posedge clk);   
    		if (!randomize(A)  with 
    				{ A dist {1'b1:=1, 1'b0:=3};
    				}) `uvm_error("MYERR", "This is a randomize error")
    				end 
    		$stop; 
    end  	
endmodule
 

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


In reply to muralidar:
Did another run and am showing sim results. I believe it would be safer to cast the realtime to unsigned when doing comparisons. Thus

vthi=int'(vt_hi);  // Casting needed? Better practice!
vthi=unsigned'(vthi); // Needed?

I did a simulation run with and without the unsigned casting and got the same results, but I believe tht it would be better practice to make the casting. From my Real Chip book:
“An object of type reg is processed by Verilog as an UNSIGNED number, however, it can be assigned a negative constant. Negative numbers are represented in 2’s complement form. A reg object loses the significance of the SIGN bit. An object of type integer is processed by Verilog as a SIGNED number and retains the significance of the sign. The difference between SIGNED and UNSIGNED number is in SIGN or ZERO extension of the left most bits when arithmetic and logical operations are performed. Section 4.4.1 of the Verilog LRM specifies the rules for expression bit lengths. For “+ - / % & | ^ ^~ ~^” arithmetic operations, and for “=== !== == != && || > >= < <=” logical operations, the number of bits used in the expression evaluations is the maximum of the length of the left operand and the right operand. Remember that an integer value is a 32-bit value, whereas a sized value is defined by the value of the size. Decimal numbers are signed. Based-numbers (e.g., 4’h21) are unsigned. An UNSIZED value (e.g., 'h5) is 32 bits. Unsized unsigned constants, where the high order bit is unknown (e.g., X or x) or tri-state (Z or z), are extended to the size of the expression containing the constant. If the size of the unsigned number is smaller than the size specified for the constant (e.g. intA32bits = 'hF;), the unsigned number is padded to the left with zeros (e.g., intA32bits = 32’h0000_000F;). If the leftmost bit in the unsigned number is an x or a z, then an x or a z is used to pad to the left respectively.”


import uvm_pkg::*; `include "uvm_macros.svh" 
module TB;
  bit clk, A;
  // default clocking @(posedge clk); endclocking
  initial forever #10 clk=!clk;  
  bit[3:0] cnt;
  int v_t, v_t_hi;
  bit [31:0] cnt_reg_1=32'H12345678;
  bit [31:0] cnt_reg_2=32'H9ABCDEF0;
     
    function void check_cnt(realtime vt_hi); 
    	automatic int vthi;
    	vthi=int'(vt_hi);  // Casting needed? Better practice!
    	vthi=unsigned'(vthi); // Needed? 
    	cnt++; $display("@t= %t, cnt=%d, vthi=%d", $time, cnt, vthi); // debug  
    	if(cnt ==0) 
    		a0: assert(vthi == cnt_reg_1[11:0]);
    	if(cnt == 1)
    		a1: assert(vthi == cnt_reg_1[23:12]);
    	if(cnt ==2)
    		a2: assert(vthi == cnt_reg_2[11:0]);
    	if(cnt ==3)
    		a3: assert(vthi == cnt_reg_2[23:12]);		 	 
    endfunction : check_cnt  
	
    property p_width; 
    	realtime  v_t, v_t_hi;
    	@(posedge A) (1, v_t    = $realtime)  ##0 	
    	@(negedge A) (1, v_t_hi = $realtime-v_t, check_cnt(v_t_hi));	
    endproperty 
    cover property(p_width); 
	
    initial begin 
    	repeat(200) begin 
    		@(posedge clk);   
    		if (!randomize(A)  with 
    				{ A dist {1'b1:=3, 1'b0:=1};
    				}) `uvm_error("MYERR", "This is a randomize error")
    				end 
    		$stop; 
    end  	
endmodule 
@t=                   30, cnt= 1, vthi=         20
# ** Error: Assertion error.
#    Time: 30 ns  Scope: TB.check_cnt.a1 File: width.sv Line: 22
# @t=                  330, cnt= 2, vthi=        280
# ** Error: Assertion error.
#    Time: 330 ns  Scope: TB.check_cnt.a2 File: width.sv Line: 24
# @t=                  410, cnt= 3, vthi=         60
# ** Error: Assertion error.
#    Time: 410 ns  Scope: TB.check_cnt.a3 File: width.sv Line: 26
# @t=                  510, cnt= 4, vthi=         80
# @t=                  750, cnt= 5, vthi=        200
# @t=                  790, cnt= 6, vthi=         20
# @t=                  870, cnt= 7, vthi=         60
# @t=                  930, cnt= 8, vthi=         40
# @t=                  970, cnt= 9, vthi=         20
# @t=                 1010, cnt=10, vthi=         20
# @t=                 1130, cnt=11, vthi=        100
# @t=                 1210, cnt=12, vthi=         60
# @t=                 1290, cnt=13, vthi=         60
# @t=                 1350, cnt=14, vthi=         40
# @t=                 1490, cnt=15, vthi=        100
# @t=                 1730, cnt= 0, vthi=        220
# ** Error: Assertion error.
#    Time: 1730 ns  Scope: TB.check_cnt.a0 File: width.sv Line: 20
# @t=                 1850, cnt= 1, vthi=        100
# ** Error: Assertion error.
#    Time: 1850 ns  Scope: TB.check_cnt.a1 File: width.sv Line: 22
# @t=                 1990, cnt= 2, vthi=         60
# ** Error: Assertion error.
#    Time: 1990 ns  Scope: TB.check_cnt.a2 File: width.sv Line: 24
# @t=                 2150, cnt= 3, vthi=        140
# ** Error: Assertion error.
#    Time: 2150 ns  Scope: TB.check_cnt.a3 File: width.sv Line: 26
# @t=                 2290, cnt= 4, vthi=        120
# @t=                 2490, cnt= 5, vthi=        180
# @t=                 2550, cnt= 6, vthi=         40
# @t=                 2690, cnt= 7, vthi=        120
# @t=                 2750, cnt= 8, vthi=         20
# @t=                 2910, cnt= 9, vthi=        140

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


*In reply to ben@SystemVerilog.us:*After more thoughts, since the delays are not that large, we don’t have to worry about negative numbers. But, in the code below, I made nuber that the comparisons stay with zero extensions.


import uvm_pkg::*; `include "uvm_macros.svh" 
module TB;
  bit clk, A;
  typedef bit [31:0] bit32_t; 
  // default clocking @(posedge clk); endclocking
  initial forever #10 clk=!clk;  
  bit[3:0] cnt;
  //bit [31:0]  v_t, v_t_hi;  // instead of int v_t, v_t_hi;
  bit [31:0] cnt_reg_1=32'H12345678;
  bit [31:0] cnt_reg_2=32'H9ABCDEF0;
     
    function void check_cnt(realtime vt_hi); 
    	automatic int vthi;
    	automatic bit[31:0] vt32;
    	vthi=int'(vt_hi);  // Casting needed? Better practice!
    	vt32=vthi; // for unsigned arithmetic 
    	cnt++; $display("@t= %t, cnt=%d, vthi=%h, vt_hi=%t", $time, cnt, vthi, vt_hi); // debug  
    	if(cnt ==0) 
    		a0: assert(vt32 == cnt_reg_1[11:0]);
    	if(cnt == 1)
    		a1: assert(vt32 == cnt_reg_1[23:12]);
    	if(cnt ==2)
    		a2: assert(vt32 == cnt_reg_2[11:0]);
    	if(cnt ==3)
    		a3: assert(vt32 == cnt_reg_2[23:12]);		 	 
    endfunction : check_cnt  
	
    property p_width; 
    	realtime  v_t, v_t_hi;
    	@(posedge A) (1, v_t    = $realtime)  ##0 	
    	@(negedge A) (1, v_t_hi = $realtime-v_t, check_cnt(v_t_hi));	
    endproperty 
    cover property(p_width); 
	
    initial begin 
    	repeat(200) begin 
    		@(posedge clk);   
    		if (!randomize(A)  with 
    				{ A dist {1'b1:=3, 1'b0:=1};
    				}) `uvm_error("MYERR", "This is a randomize error")
    				end 
    		$stop; 
    end  	
endmodule

 @t=                   30, cnt= 1, vthi=00000014, vt_hi=                  20
# ** Error: Assertion error.
#    Time: 30 ns  Scope: TB.check_cnt.a1 File: width2.sv Line: 24
# @t=                  330, cnt= 2, vthi=00000118, vt_hi=                 280
# ** Error: Assertion error.
#    Time: 330 ns  Scope: TB.check_cnt.a2 File: width2.sv Line: 26
# @t=                  410, cnt= 3, vthi=0000003c, vt_hi=                  60
# ** Error: Assertion error.
#    Time: 410 ns  Scope: TB.check_cnt.a3 File: width2.sv Line: 28
# @t=                  510, cnt= 4, vthi=00000050, vt_hi=                  80
# @t=                  750, cnt= 5, vthi=000000c8, vt_hi=                 200
# @t=                  790, cnt= 6, vthi=00000014, vt_hi=                  20
# @t=                  870, cnt= 7, vthi=0000003c, vt_hi=                  60
# @t=                  930, cnt= 8, vthi=00000028, vt_hi=                  40
# @t=                  970, cnt= 9, vthi=00000014, vt_hi=                  20
# @t=                 1010, cnt=10, vthi=00000014, vt_hi=                  20
# @t=                 1130, cnt=11, vthi=00000064, vt_hi=                 100 

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


Thanks Ben,
using of function worked. I have done few changes in my code and assertions are triggered at correct point as per my requirement.

In reply to muralidar:

I have one more problem here.

Actually my assertion is working but it fails in this case because the actual time and expected time is not matching due to precision differences.

In the above code i have to compare “v_t_hi” value which we got from property with the values of (cnt_reg_1*1.312ms).
here value 1.312 is constant for all the checks.

when i use above equation tool is taking (cnt_reg_1*1312) i am seeing the small difference

v_t_hi = 418248000ns (cnt_reg_1*1312) = 419328000ns

So my assertion is failing for all the comparison due to small difference between two.
I can not compare this in ms because operations happens in us.
Please suggest is there any other solution for making it roundoff?

In reply to muralidar:
Why don’t you use the clock and sample signal A.
Untested code example, you need to tune it to your requirements. Te concept is to use integer counts based on $rose and $fell, and do increments until signal transitions. Signal A is sample with clk. Tune the function as required. Am just giving you directions. This avoids the issues with realtime. BTW, I hinted on this in my first reply by using the sampling of A with the clock, and counting the number of clocks.

 
// USE something like this 
property p_width; 
    	int  v_t=0;        
    	@(posedge clk) ($rose(A), vt=0) ##1 (A, vt++)[*1:$] ##1 	
    	($fell(A), check_cnt(v_t));	
    endproperty 
    cover property(p_width); 

function void check_cnt(int vt32); 
cnt++; $display("@t= %t, cnt=%d, vthi=%h, vt_hi=%t", $time, cnt, vthi, vt_hi); // debug  
    	if(cnt ==0) 
    		a0: assert(vt32 == cnt_reg_1[11:0]);
    	if(cnt == 1)
    		a1: assert(vt32 == cnt_reg_1[23:12]);
    	if(cnt ==2)
    		a2: assert(vt32 == cnt_reg_2[11:0]);
    	if(cnt ==3)
    		a3: assert(vt32 == cnt_reg_2[23:12]);		 	 
    endfunction : check_cnt  
 

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr