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

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