Assertion to check stability of a signal for 'n' clocks

Hi,

I want to check the stability of a signal for five clocks after it goes high.

Like, once the signal goes high then it should remain ‘1’ for next five clocks.

I have written the assertion in the below way.

assert_check: assert property(@(posedge clk) disable iff (rst) $rose (signal) |-> signal[*5])

Can we make it more efficient?

thanks & regards,
sanjoy

In reply to sanjay864u:


assert_check: assert property(@(posedge clk) disable iff (rst) $rose (signal) |-> signal[*5])

Can we make it more efficient?

That is the correct and only way; a procedural concurrent assertion (e.f. always @(posedge clk) ) is not more efficient. However, you mention that signal should remain ‘1’ for next five clocks, meaning for 5 more clock cycles. You would need the |=> instead of the |-> since *$rose[a) |-> a[1] is valid for the cycle in which $rose(a) occurred.


assert_check: assert property(@(posedge clk) disable iff (rst) $rose (signal) |=> signal[*5])

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us

  • SVA Handbook 4th Edition, 2016 ISBN 978-1518681448
  • A Pragmatic Approach to VMM Adoption 2006 ISBN 0-9705394-9-5
  • Using PSL/SUGAR for Formal and Dynamic Verification 2nd Edition, 2004, ISBN 0-9705394-6-0
  • Real Chip Design and Verification Using Verilog and VHDL, 2002 isbn 0-9705394-2-8
  • Component Design by Example ", 2001 ISBN 0-9705394-0-1
  • VHDL Coding Styles and Methodologies, 2nd Edition, 1999 ISBN 0-7923-8474-1
  • VHDL Answers to Frequently Asked Questions, 2nd Edition ISBN 0-7923-8115

In reply to ben@SystemVerilog.us:

Thank you Ben…

In reply to ben@SystemVerilog.us:

Hi ben , In addition to above , I think we can also apply

assert_check: assert property(@(posedge clk) disable iff (rst) $rose (signal) |=> $stable(signal[*5]))

which checks that the signal hasn’t changed since the last clock cycle and should remain stable up to 5 more clock cycles.

In reply to ben@SystemVerilog.us:

Hi Ben,

i want to check an assertion similar;
LEGAL: assert property(@(posedge clk) disable iff (rst) $rose (signal) |=>
$stable(signal)[*5]);

one addition to above; the signal which i check want to be HIGH for all remaining clk cycles & it should not go unknown(X).

assert_check: assert property(@(posedge clk) disable iff (rst) $rose (signal) |=> !($isunknown (signal)) & stable(signal)[*]) else $error();

pls advise.
Thanks

In reply to Jayaraj:

In reply to ben@SystemVerilog.us:

one addition to above; the signal which i check want to be HIGH for all remaining clk cycles & it should not go unknown(X).
assert_check: assert property(@(posedge clk) disable iff (rst) $rose (signal) |=> !($isunknown (signal)) & stable(signal)[*]) else $error();[/quote]
Change the above assertion to:


// [*$] is illegal, use the always(property) 
// 1800 
// property_expr ::= .... 
//     always property_expr
//  | always [ cycle_delay_const_range_expression ] property_expr
//  | s_always [ constant_range] property_expr
//   Do you need the $error?  Ok if you want it. 
assert_check: assert property(@(posedge clk) disable iff(rst) 
   $rose (signal) |=> always( 
               !$isunknown(signal) && $stable(signal)); //  else $error();

// To avoid multiple threads, you could do the following: 
initial begin 
  wait(rst==1'b0); // use whatever variation you need) 
  assert_check: assert property(@(posedge clk) disable iff(rst) 
   $rose (signal)[->1] |=> always( 
               !$isunknown(signal) && $stable(signal)); //  else $error();
end
 

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


In reply to ben@SystemVerilog.us:

Thanks Ben,

// To avoid multiple threads, you could do the following:
initial begin
wait(rst==1’b0); // use whatever variation you need)
assert_check: assert property(@(posedge clk) disable iff(rst)
$rose (signal)[->1] |=> always(
!$isunknown(signal) && $stable(signal)); // else $error();
end

I tried your suggestion like below; as i want to check this for few sets of signals; when i compile hit with syntax error: "token is ‘always’. (using synopsys)

property xx_chk (logic a, logic b);
@(posedge clk) disable iff(rst)
$rose(a)[->1] |=> always (!$isunknown(q) && $stable(q));
endproperty
xx_check: assert property (xx_chk(dut.signal1, dut.signal2)) else $error();

tried
$rose(a)[->1] |=> ##30 (!$isunknown(q) && $stable(q)); // this works, but it checks once and not till simulation end.
me requirement is to check HIGH for all remaining clk cycles.

In reply to Jayaraj:
Comments:

  1. SVA legal but not supported:
    property_expr ::= …
    always property_expr // Is legal syntax
    Tools may not support this feature because it is not often used
  2. Alternative solution
    See my alternative approach in the paper below. I address your model further down.
    PAPER: Understanding the SVA Engine + Simple alternate solutions | Verification Academy
    Abstract: Understanding the engine behind SVA provides not only a better appreciation and limitations of SVA, but in some situations provide features that cannot be simply implemented with the current definition of SVA. This paper first explains, by example, how a relatively simple assertion example can be written without SVA with the use of SystemVerilog tasks; this provides the basis for understanding the concepts of multithreading and exit of threads upon a condition, such as an error in the assertion. The paper then provides examples that uses computational variables within threads; those variables can cause, in some cases, errors in SVA. The strictly emulation model with tasks solves this issue.
    A new version of that paper entitled "SVA Alternative for Complex Assertions" will be on the February 2018 Issue of the Verification Horizons.

Below is code that simulates OK. I used an always block to fire the task, and also an assertion where in the consequent I fire the task in the sequence_match_item.
Read my paper, as it explains the concepts. The code is self-explanatory, I believe.


import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
	timeunit 1ns;     timeprecision 100ps;  
	logic clk=0, a, rst=-0;  
	default clocking @(posedge clk); endclocking
	initial forever #10 clk=!clk;  
 
	/*initial begin 
		wait(rst==1'b0); // use whatever variation you need) 
		assert_check: assert property(@(posedge clk) disable iff(rst) 
					$rose (a)[->1] |=> always( 
						!$isunknown(a) && $stable(a)); //  else $error();
	end*/
	
	
	task automatic t_stays();
	  forever begin : fevr
		  @(posedge clk); 
		  if(rst) return; 
		  if($isunknown(a) || $changed(a)) begin : err
		    `uvm_error("my_module", "a changed or is unkonwn")
		     return; 
		  end : err 
	   end : fevr	 
	endtask 
	
	always   @(posedge clk)  begin // possible new thread at every rose(a) 
	// use initial to fire task once (see below) 
	  if($rose(a)) t_stays(); 
	end 
	
	initial begin  // FIring task once, an option
	  wait(rst==1'b0); // use whatever variation you need) 
	  assert_check: assert property(@(posedge clk) disable iff(rst) 
	    $rose(a)][->1] |=>  (1, t_stays())); // the [->1] needed because 
                             // it can occur anyime after rst==0, an it is in the initial. 
	end

	initial begin
	  repeat(10)  @(posedge clk) ; 
	   a <= 1'b0; 
		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 ben@SystemVerilog.us:

Thanks Ben. I shall try and come back if any issues seen.

In reply to ben@SystemVerilog.us:

Hi ben,

I want to check a signal “a” which should not remain high for more than 5 clock cycles otherwise throw an error. What should be the assertion for that.

Thanks in advance.

In reply to prashantk:
You need supporting logic.
Write a counter that increments if a==1, and resets to 0 if a==0.
assert property(@(posedge clk) counter <6);

Ben

In reply to ben@SystemVerilog.us:

Hi Ben,

I’m implementing clock DCC checker using SVA. I want to only check the duty cycle in the first 2 clock cycles after id goes to 4’h2. When I use the repetition operator, compiler is throwing an error saying ‘repetition operator not allowed in multi-clocking sequence

property positive_duty_cycle_chk(clk, real tolerance, real half_duty_cycle, id);    
     real v_t1, v_t2, v_hi, v_lo, v_diff, v_total;
     real ratio;
     @(id) id== 4'h2 |=> (@(posedge clk) (1, v_t1=$time) ##0 @(negedge clk) (1, v_t2=$time, v_hi=v_t2-v_t1) ##0 @(posedge clk) (1, v_lo=$time-v_t2) ##0 
        (1, v_total = (v_lo+v_hi)) ##0 (1, ratio = (v_lo* (1/v_total))) ##0 ratio >= half_duty_cycle - tolerance && ratio <= half_duty_cycle + tolerance) [*2];
endproperty

Can you please tell me how to fix this?

In reply to nimitz_class:
You’re saying compiler is throwing an error saying ‘repetition operator not allowed in multi-clocking sequence’
I don’t see that with 2 simulators.
Edit code - EDA Playground // some modified code here
It looks like you may have a tool issue.
From a language point of view, ‘repetition operator is allowed in multi-clocking sequence’.
You’ll need to contact your vendor.
Ben

In reply to ben@SystemVerilog.us:

**Warning-[LCA_FEATURES_ENABLED] Usage warning
LCA features enabled by ‘-lca’ argument on the command line. For more
information regarding list of LCA features please refer to Chapter “LCA
features” in the VCS Release Notes

Parsing design file ‘design.sv’
Parsing design file ‘testbench.sv’
Top Level Modules:
duty_cycle
TimeScale is 1 ns / 1 ns

Error-[SVA-SCSE] Single-clocked sequence expected
testbench.sv, 17
duty_cycle, "ap_positive_duty_cycle_ch: assert property(positive_duty_cycle_chk(clk, 0.10000000000000001, 0.10000000000000001, 1)); "
Single-clocked sequence expected in operand of ‘repetition’ operator,
multi-clocked sequence found.

1 warning
1 error
CPU time: .134 seconds to compile
Exit code expected: 0, received: 1**

I just ran your code on EDA playground and got this error.

In reply to nimitz_class:

From an 1800’2017 I do not see this restriction; maybe I missed it, but I could not find it.
From 1800 syntax

( sequence_expr {, sequence_match_item } ) [ sequence_abbrev ] 
boolean_abbrev ::=
   consecutive_repetition
 | non_consecutive_repetition
 | goto_repetition

sequence_expr ::=
 cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }
| sequence_expr cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }

@(id) id== 4'h2 |=> (@(posedge clk) (1, v_t1=$time) ##0 @(negedge clk) (1, v_t2=$time, v_hi=v_t2-v_t1) ##0 @(posedge clk) (1, v_lo=$time-v_t2) ##0 
        (1, v_total = (v_lo+v_hi)) ##0 (1, ratio = (v_lo* (1/v_total))) ##0 ratio >= half_duty_cycle - tolerance && ratio <= half_duty_cycle + tolerance) [*2];
// is equivalent to 
@(id) id== 4'h2 |=> (@(posedge clk) (1, v_t1=$time) ##0 @(negedge clk) (1, v_t2=$time, v_hi=v_t2-v_t1) ##0 @(posedge clk) (1, v_lo=$time-v_t2) ##0 
        (1, v_total = (v_lo+v_hi)) ##0 (1, ratio = (v_lo* (1/v_total))) ##0 ratio >= half_duty_cycle - tolerance && ratio <= half_duty_cycle + tolerance) // [*2];
##1 
 (@(posedge clk) (1, v_t1=$time) ##0 @(negedge clk) (1, v_t2=$time, v_hi=v_t2-v_t1) ##0 @(posedge clk) (1, v_lo=$time-v_t2) ##0 
        (1, v_total = (v_lo+v_hi)) ##0 (1, ratio = (v_lo* (1/v_total))) ##0 ratio >= half_duty_cycle - tolerance && ratio <= half_duty_cycle + tolerance);
// or more simply, just looking at the clocks 
(@(posedge clk) (1) ##0 @(negedge clk) 1 ##0 @(posedge clk) expr ##0 expr2)[*2]
// same as 
@(posedge clk) (1) ##0 @(negedge clk) 1 ##0 @(posedge clk) expr ##0 expr2 ##1
@(posedge clk) (1) ##0 @(negedge clk) 1 ##0 @(posedge clk) expr ##0 expr2

To me, it does not look like an 1800 issue. It could be a tool restriction, and we don’t address tools in this forum. Am consulting with one of the other 1800 SVA member.
More to come.

Did a search on LCA feature
NOTE: Adding the “-lca” switch to a VCS/VCS-MX command line enables a suite of “limited customer availability” features.The exact set of features differs from release to release, but is documented in the “LCA Features” portion of “vcs -doc”.

You seem to be using a special switch feature.

In reply to ben@SystemVerilog.us:

Without the switch I cannot compile, tool suggested me to add -lca and then re-reun. Anyway, I’m not sure how to fix this issue with the tool. So, I will go with your suggestion of computing duty cycle again after one cycle.

Thanks Ben!