SVA to check a N-stage synchronizer output

Hi all! I want to write an assertion for an N-stage synchronizer output (this synchronizer accounts for metastability modeling, so its delay is non-deterministic and it ranges in between N and M cycles).

This assertion needs to check that: a signal B can only change (from 0 to 1, or from 1 to 0) if and only if a signal A has changed (from 0 to 1, or from 1 to 0) in between [N:M] cycles in the past.

Thanks in advance!

property check_signal_b_change;

@(posedge clk)

($fell(signal_b) || $rose(signal_b)) |->

( ##[N:N+1] $changed(signal_a) );

endproperty

Hi @liviareis,

Assuming the clock edges occur at T0 ( 1st clock edge ) , T1 , T2 , T3 , … Tx,

N & M are constants with values 3 & 5 respectively.

If signal A changes at T2 then signal B should change at T5 or T6 or T7 ,

is this the expectation ?

Hi arshi582! No, according to your example, the assertion should check that: If signal B changes at T6 then signal A should have changed at T3 or T2 or T1.

        T0    T1    T2    T3    T4    T5    T6    T7    
CLK    __/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__
         ┊     ┊     ┊     ┊     ┊     ┊     ┊     ┊     
B      ____________________________________/‾‾‾‾‾‾‾‾‾‾‾‾‾
         ┊     ┊     ┊     ┊     ┊     ┊     ┊     ┊     
A      ________________/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
         ┊     ┊     ┊     ┊     ┊     ┊     ┊     ┊     
               <===========>                 *
              -5    -4    -3    -2    -1     0

property check_signal_b_change;

@(posedge clk)

($fell(signal_b) || $rose(signal_b)) |->

( ##[N:M] $changed(signal_a) );

endproperty

This is checking that, if B changes, then A should change from N to M cycles later.

What I want to check is: if B changes, then A should have changed in between [N:M] cycles in the past.

Currently this is what I have:

sequence A_rose;
  @(posedge clk) $rose(A) ##[N:M] 1'b1;
endsequence

sequence A_fell;
  @(posedge clk) $fell(A) ##[N:M] 1'b1;
endsequence

property B_CHANGED_DUE_TO_A;
  @(posedge clk) disable iff (~rst_n)
  $changed(B) |-> (B && A_rose.triggered) or (~B && A_fell.triggered);
endproperty

assert property (B_CHANGED_DUE_TO_A);

If signal A changes at T6 then signal B should have changed at T3 or T2 or T1.

sequence b2a_change( N , M );
 $changed(b) ##[N:M] $changed(a);
endsequence

property b_2_a( N , M );
  @(posedge clk) disable iff (!rst_n)
    $changed(a) |→ b2a_change(N,M).triggered;
endproperty

b2a:assert property( b_2_a(3,5) ) else `uvm_error(..)

Hi Have_A_Doubt, thanks for you reply but I didn’t see a big difference between your solution and the one I already have.

BTW, the issue I have with this solution is that during simulation, when B changes too close to the rising edge of the clock, the design and the sequence samples different values; the design samples 1 and the sequence samples 0.

 

    D[0]   _______   Q[0]   _______  Q[1]
A ------->|D     Q|------->|D     Q|-------> B
          |       |        |       |
          |  FF0  |        |  FF1  |
          |       |        |       |
CLK ----->|>CK    |     -->|>CK    |
           ‾‾‾‾‾‾‾          ‾‾‾‾‾‾‾

           T0    T1    T2    T3    T4    T5    T6    T7    
    CLK  __/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__/‾‾\__
           ┊     ┊     ┊     ┊     ┊     ┊     ┊     ┊     
A, D[0]  ______________/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
           ┊     ┊     ┊     ┊     ┊     ┊     ┊     ┊       
   Q[0]  _______________/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
           ┊     ┊     ┊     ┊     ┊     ┊     ┊     ┊     
B, Q[1]   _____________________/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

At T2, D[0] is 1 and Q[0] goes to 1. I’d expect that $rose(A) is true at T2, but it isn’t - it is only true at T3.

Anyone has an alternative solution or a solution for the issue I am having?

Thanks!