Assertion to check signal is toggling or not

Hi,

Assertion to check signal c is stable if b is true otherwise c is the running clock. Frequency of c and assertion clock “clk” is same so cannot use “$changed” to check c is toggling or not as sampled value of c remains same at each posedge of clk. Is there any construct/logic to check c is toggling as something like “always” is used to check stability without dependency on assertion clk?

property p;
@(posedge Clk)

$rose(a) |-> if (b)
always(c)
else
$changed(c);
endproperty

Thanks in advance.

In reply to rohithgm:
I don’t fully understand your requirements. However, I have a suggestion that can get you started on the right path. That suggestion makes use of concepts explained in my paper
SVA Alternative for Complex Assertions The paper was published at Verification Horizons - March 2018 Issue | Verification Academy

Your solution would look something like

 
$rose(a) |-> (1, my_task(b, c)); 

task automatic my_task(bit b, c); 
  // here you can use # delays, wait statements, @ (posedge clk), 
  // fork other tasks, or whatever you need to verify your requirements
endtask

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


  1. Verification Horizons - March 2018 Issue | Verification Academy
  2. SVA: Package for dynamic and range delays and repeats | Verification Academy
  3. SVA in a UVM Class-based Environment
    SVA in a UVM Class-based Environment | Verification Horizons | Verification Academy

FREE BOOK: Component Design by Example
… A Step-by-Step Process Using VHDL with UART as Vehicle

In reply to ben@SystemVerilog.us:

Basically, How can I check toggling of signal “c” when frequency of signal “c” is same as “clk”?

“$changed” will get same sampled value of c at each posedge of clk even though “c” is toggling.
$changed assertion will fail if “c” is toggling with same frequency of clk or remains stable, hence does not matter.
So, cannot use $changed.

One approach for solution would be as follows

property p;
logic v,o;
@(posedge clk)
(a > 2, v = c) |-> if (b)
(@(negedge clk) (1, o = c) |-> (v == o)) // not sure why always(c) is not working
else
(@(negedge clk) (1, o = c) |-> ( v != o));
endproperty

But above solution assumes both “c” and “clk” have same frequency but not valid if signal “c” is having different frequency than clk. Is there any logic/construct that checks just toggling of signal without dependency on assertion clock.

In reply to rohithgm:
Looks to me that you are trying to check a gated clock (c) that is synchronous to a master clock (clk). Below is a code with a testbench. Two key approachesL


// Uses the concept of multiclocking where @ (posedge clk)  (a, t=$realtime) you save the current time. Then, with the |> if  @ (posedge c) exactly occurs with the @ (posedge clk)  then the consequent starts right away, thus in synchronism.  Else, it waits till the next @ (posedge c).
 property p_c; 
        realtime t; 
        @ (posedge clk)  (a, t=$realtime) |-> @ (posedge c) ($realtime==t); 
    endproperty 
    ap_c: assert property(p_c);
 

The Other approach uses a task that fires two threads (forks) and each measure the current time, and when joined, check the time diff. The while(a) keep on firing those threads.


   ap_ac: assert property(@ (posedge clk)  $rose(a) |-> (1, t_check()) ); // ** LINE 22
    task automatic t_check(); 
        automatic realtime ta1, tc; 
        $display("%t start of task ", $realtime);
        while (a) begin : while1                
            fork
                begin : chk1
                    @ (clk); 
                    ta1=$realtime; 
                    -> e1;
                end : chk1
                
                begin : chk2
                    @(c); 
                    tc=$realtime; 
                    -> e2;
                end : chk2  
            join
            a_intask: assert(ta1==tc) else $display ("%t clk and c not in sync", $realtime); 
            $display("%t ta1= %t tc=%t", $realtime, ta1, tc);
            if(ta1!=tc) -> ec;
        end : while1
    endtask 
// ****** simulation results
                  310 start of task 
#                  410 ta1=                  410 tc=                 410
# ** Error: Assertion error.
#    Time: 54 ns Started: 51 ns  Scope: top.ap_c File: C:/ben_play/./a_syncs.sv Line: 22 Expr: $realtime()==t
#    Local vars : t = 51
#                  540 clk and c not in sync
#                  540 ta1=                  510 tc=                 540
#                  640 clk and c not in sync
#                  640 ta1=                  610 tc=                 640
#                  710 ta1=                  710 tc=                 710
#                  810 ta1=                  810 tc=                 810
#                 1110 start of task 
# ** Error: Assertion error.
#    Time: 114 ns Started: 111 ns  Scope: top.ap_c File: C:/ben_play/./a_syncs.sv Line: 22 Expr: $realtime()==t
#    Local vars : t = 111
#                 1210 clk and c not in sync
#                 1210 ta1=                 1210 tc=                1140
#                 1310 clk and c not in sync
#                 1310 ta1=                 1310 tc=                1240


testbench

 
import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
    timeunit 1ns;     timeprecision 100ps;    
    bit clk0, clk, a, c;  
    bit va, vb, vc; 
    realtime period =20ns; 
    event ec, e1, e2; 
    default clocking @(posedge clk); 
    endclocking
    
    initial forever #(period/2) clk0=!clk0;  
    always @(clk0) begin
        #1 clk <= clk0; 
        if(vb) #3 c <= clk0;
        else c <= clk0; 
    end
    
    property p_c; 
        realtime t; 
        @ (posedge clk)  (a, t=$realtime) |-> @ (posedge c) ($realtime==t); 
    endproperty 
    ap_c: assert property(p_c);  
    
    //  How can I check toggling of signal "c" when 
    //  frequency of signal "c" is same as "clk"?
    ap_ac: assert property(@ (posedge clk)  $rose(a) |-> (1, t_check()) ); 
    
    task automatic t_check(); 
        automatic realtime ta1, tc; 
        $display("%t start of task ", $realtime);
        while (a) begin : while1                
            fork
                begin : chk1
                    @ (clk); 
                    ta1=$realtime; 
                    -> e1;
                end : chk1
                
                begin : chk2
                    @(c); 
                    tc=$realtime; 
                    -> e2;
                end : chk2  
            join
            a_intask: assert(ta1==tc) else $display ("%t clk and c not in sync", $realtime); 
            $display("%t ta1= %t tc=%t", $realtime, ta1, tc);
            if(ta1!=tc) -> ec;
        end : while1
    endtask
    
    // here you can use # delays, wait statements, @ (posedge clk), 
    // fork other tasks, or whatever you need to verify your requirements
    
    initial begin         
        repeat(200) begin 
            @(posedge clk0);   
            if (!randomize(va, vb, vc)  with 
            { va dist {1'b1:=10, 1'b0:=1};
            vb dist {1'b1:=1, 1'b0:=2}; 
            vc dist {1'b1:=1, 1'b0:=1};      
        }) `uvm_error("MYERR", "This is a randomize error")
        #3;
        a <= va;        
        end 
        $stop; 
     end 
endmodule       
 

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


  1. Verification Horizons - March 2018 Issue | Verification Academy
  2. SVA: Package for dynamic and range delays and repeats | Verification Academy
  3. SVA in a UVM Class-based Environment
    SVA in a UVM Class-based Environment | Verification Horizons | Verification Academy
    FREE BOOK: Component Design by Example
    … A Step-by-Step Process Using VHDL with UART as Vehicle

    http://systemverilog.us/cmpts_free.pdf

Ben,
I have a scenario wherein I need to check whether the clock sys_clk toggles within 80 clock cycles of en going low. I have a reference clock named refclk to time the assertion. The assertion should fail if the clock sys_clk does not toggle within the specified time.

I tried your solution but it does not fail when sys_clk is not toggling. Because the fork waits for posedge of the clock and never fails.

In reply to nimitz_class:
Show your code

In reply to ben@SystemVerilog.us:

Try this code.


import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
    timeunit 1ns;     timeprecision 100ps;    
    bit clk0, clk, a, c, refclk, sysclk, window;  
    bit va, vb, vc; 
    realtime period =20ns; 
    event ec, e1, e2; 
    realtime ta1, tc, done, active; 
    int count;
    default clocking @(posedge clk); 
    endclocking

    initial begin 
        repeat(90) @(posedge refclk); 
        forever @(posedge refclk) sysclk=!sysclk; 
    end
    initial begin 
        window=1'b1; 
        repeat(120) @(posedge refclk); 
        window=1'b0;
    end
    
    initial forever #(period/2) clk0=!clk0;  
    initial forever #(period/2) refclk=!refclk;  
    always @(clk0) begin
        #1 clk <= clk0; 
        if(vb) #3 c <= clk0;
        else c <= clk0; 
    end
    
    property p_c; 
        realtime t; 
        @ (posedge clk)  (a, t=$realtime) |-> @ (posedge c) ($realtime==t); 
    endproperty 
    ap_c: assert property(p_c);  
    
    //  
    ap_ac: assert property(@ (posedge clk)  $rose(a) |-> (1, t_check()) ); 

    /*I need to check whether the clock sys_clk toggles within 80 clock cycles of en going low. 
    I have a reference clock named refclk to time the assertion. 
    The assertion should fail if the clock sys_clk does not toggle within the specified time.
I tried your solution but it does not fail when sys_clk is not toggling. 
Because the fork waits for posedge of the clock and never fails.*/
    initial t_check(); 
    
    task automatic t_check(); 
        automatic realtime ta1, tc, done, active; 
        int count;
        $display("%t start of task ", $realtime);
        while (window) begin : while1                
            fork
                begin : chk1
                    //@ (refclk);  
                    count = count+1'b1; 
                    if(count>= 80) done=1'b1;
                    -> e1;
                end : chk1
                
                begin : chk2
                    @(posedge sysclk); 
                   active=1'b1; 
                    -> e2;
                end : chk2  
            join_none
            a_intask: assert(!done || active) else $display ("%t sysclk is not active ", $realtime); 
            $display("%t ta1= %t tc=%t", $realtime, ta1, tc);
            if(active) -> ec;
            active=1'b0; 
            @ (refclk); 
        end : while1
    endtask
    
    // here you can use # delays, wait statements, @ (posedge clk), 
    // fork other tasks, or whatever you need to verify your requirements
    
    /*initial begin         
        repeat(200) begin 
            @(posedge clk0);   
            if (!randomize(va, vb, vc)  with 
            { va dist {1'b1:=10, 1'b0:=1};
            vb dist {1'b1:=1, 1'b0:=2}; 
            vc dist {1'b1:=1, 1'b0:=1};      
        }) `uvm_error("MYERR", "This is a randomize error")
        #3;
        a <= va; 
        end 
        $stop; 
    end */ 
endmodule   

In reply to ben@SystemVerilog.us:
Will this not work if I just want to check clk gating during assertion of en?


 assert((sys_clk|~en) == 0)
 else 
 $error("error:")

In reply to rlot:

In reply to ben@SystemVerilog.us:
Will this not work if I just want to check clk gating during assertion of en?


assert((sys_clk|~en) == 0)
else 
$error("error:")

sys_clk is a clock that toggles between 1 and 0. Thus, if en==1 the assertion fails when sys_clk goes to 0.

Hi ,
What are the different ways to check clock is toggling or not when reset is enabled (other than assertions)?