Check clock is stable for 1us before signal is asserted

Hi,

I am trying to write an assertion that should make sure that the clock is stable (frequency is constant) for 1us before a signal is asserted.

I have another faster reference clock which can be used to write the assertion. Is there any way to write the assertion when the expected clock period is not known?

Thanks
Ankit

In reply to Ankit Bhange:
Your requirements are a bit ambiguous. Below is one possibility where upon a “go” signal, there must be T number of ns before sigal “a” goes to 1’b1.
The model needs tuning to address the condition when “a” occurs.
It is modeled after my other model in
https://verificationacademy.com/forums/systemverilog/data-stable-throughout-clock-cycle/no-glitch


import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
    bit clk, a, go;  
    event e, e0, e1; 
	initial forever #5 clk=!clk; 
    /* I am trying to write an assertion that should make sure that the clock is stable 
    (frequency is constant) for 1us before a signal is asserted.
    I have another faster reference clock that can be used to write the assertion. 
    Is there any way to write the assertion when the expected clock period is not known? */

    let T=100ns; // or 1us 
    task automatic t_count();
        int count;
        fork
            fork1: begin 
                -> e0; 
                forever begin 
                    @(posedge clk) count += 1'b1;  
                end  
                //disable fork2;               
            end
            fork2: begin                
                #T; 
                disable fork1; 
                -> e1;            
            end
            fork3: begin 
                 @(posedge a); // "a" signal is asserted.
                 disable fork1; 
                 disable fork2;
            end
        join_any
        $display("%t count= %d ", $realtime, count);  
        a_t_count: assert (count >9 &&  count < 11)  else -> e; 
    endtask
	
    always @(go)  t_count(); 

	initial begin 
        #35 go <= 1'b1; 
        #20 a <= 1'b1;
    end 
endmodule  

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact http://cvcblr.com/home.html
** 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:

In reply to ben@SystemVerilog.us:

Alternatively, when a signal A goes high, the assertion should check that a clock signal CLK has been running at least for 1us

OR

When clock starts running, signal A should be low for at least 1us.

Thanks
Ankit

In reply to Ankit Bhange:
A small variation to my model, plus an SVA assertion. Adjust the time when a==1.


import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
	bit clk, a;  
    event e, e0, e1; 
	initial begin 
        #39; 
        forever #5 clk=!clk; 
    end
    /* When clock starts running, signal A should be low for at least 1us.*/

    let T=1000ns; // at 10ns/cycle then 100 clocks 
    task automatic t_count();
        int count;
        fork
            fork1: begin 
                -> e0; 
                forever begin 
                    @(posedge clk) count += 1'b1;  
                end  
                //disable fork2;               
            end
            /* fork2: begin                
                #T; 
                disable fork1; 
                -> e1;           
            end */ 
            fork3: begin 
                 @(posedge a); // "a" signal is asserted.
                 disable fork1; 
                 // disable fork2;
            end
        join_any
        $display("%t count= %d ", $realtime, count);  
        a_t_count: assert (count >= 100)  else -> e; // error 
    endtask
	
    initial begin 
     a_aIS0: assert(a==1'b0);  // "a" starts at 0
     t_count(); 
    end

    property p_100before_a; 
        int v_count=0;
        @(posedge clk) first_match((a==1'b0, v_count+=1'b1) [*1:$] ##1 $rose(a)) 
                       ##0 v_count >=100;
    endproperty 

    initial ap_100before_a: assert property(@ (posedge clk) p_100before_a );  

    initial begin        
        #1399 a <= 1'b1;
    end 
endmodule  

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact http://cvcblr.com/home.html
** 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:

In reply to ben@SystemVerilog.us:

Thank you, Ben.

Please comment on the solution below:

    logic CLK;    //expected frequency is 100Mhz
    logic stable_CLK;
    realtime period;
    realtime current_time;

    task freq_monitor();
            @(posedge CLK) current_time = $realtime;
            @(posedge CLK) period = $realtime - current_time;
    endtask

    //reset period after waiting for 10 times CLK period after the last negedge of CLK 
    task reset_period;
        fork begin
                fork
                    begin
                        @(negedge CLK);
                        @(posedge CLK);
                    end
                    begin
                        #100ns; //10*period for 100MHz
                        period = 0;
                    end
                join_any
                disable fork;
            end
        join
    endtask

    initial forever freq_monitor();
    initial forever reset_period();

    //10000 because the ref_clk is 2GHz
    assign stable_CLK = period <= 10000*1.01 && period >= 10000*0.99 ? 1 : 0;

    property sig1_high_for_1us_before_sig2 (logic sig1, sig2);
        disable iff (!rstb)
        $rose(|sig1) && !sig2 |-> !sig2[*2000];
    endproperty //sig1_stable_for_1us_before_sig2

    //ref_clk is 2GHz
    CLK_stable_for_1us_before_A: assert property (@(posedge ref_clk) sig1_high_for_1us_before_sig2 (stable_CLK , A));

Thanks,
Ankit

In reply to Ankit Bhange:

It looks too complicated. Have you tried the proposed solutions and your other solution?
Ben