Based on my understanding of scheduling mechanism, we evaluate assertion properties in Observed phase and deal with sampled signals which get from Preponed phase, it’s why simple DFF in-out property wrote in this way:
property DFF;
@ posedge clk
out = $past(in); // using sampled input value to drive output in non-blocking phase, so we are using $past
endproperty
So to detect glitch, we should use (@ in) instead of (@ posedge clk), right?
I try to search this problem online and find this solution, and seem the answer is not very clear to me.
In the following code, we detected glitch’s duration and make sure its’ long enough, right?
property glitch_p;
time first_change;
time duration = 3;
@(req)
(1, first_change = $time) |=> (($time-first_change) >= duration); // make sure time difference between 2 changed >= duration
endproperty
in code, |=> means next cycle implication which is based on clocking event definition, right?
so here, we define clocking cycle as “req input change”, then we will get the duration of glitch to judge.
I am not sure if my understanding is correct?
Thanks.
in code, |=> means next cycle implication which is based on clocking event definition, right?
That statement is true; SVA is based on clocking events.
I don’t believe that you are using the “time” correctly. Below is an example from my SVA Handbook 4th Edition that demonstrates proper time usage.
10.34 Measuring clock periods
User's requirement: Check that the duty cycle of a clock is within acceptable limits.
The concept is simple: based on clock edges, measure the widths in which the clock is high and low, and compare the difference against an acceptable tolerance. The use of realtime type provides more accuracy. When using a concurrent assertion, local variables are used to hold the measured values. A multiclocking approach is used to trigger on each edge of the clock. module timem; // /ch10/10.34/timem.sv
timeunit 100ps; timeprecision 100ps;
initial $timeformat(-9, 5, " ns", 10); // for display of time
bit clk, a, b;
property period_chk;
realtime current_time, deltat; // deltat used for debug, as a temp
('1,current_time = $time ) ##1
(1, deltat=current_time) ##0 deltat == 10ns;
endproperty
ap_time: assert property(@(posedge clk) period_chk);
property period_chk2;
realtime current_time, deltat;
('1,current_time = $time ) ##1
(1, deltat=current_time) ##0 (deltat >= 9.99ns && deltat<= 10.01ns); //
endproperty
ap_time2: assert property(@(posedge clk) period_chk2);
Thanks, Ben.
$time return as the integer.
Using $realtime to have more accuracy.
It depends on env’s timescale setting
updated version, thanks for the feedback.
It states that at every edge of “a” you start a new thread, and in that thread, from then on, and and forever, every edge of “a” must be >= duration. That creates multiple, unneeded threads. I strongly suggest that you read my paper https://verificationacademy.com/forums/systemverilog/paper-understanding-sva-engine-simple-alternate-solutions
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.
2. On realtime, SystemVerilog is laxed and allows to specify a time in integer. From my roots in VHDL, and I prefer to specify a realtime variable with a real number
3. Add timeunits
Below is my corrected code. I believe that this is more of what you are looking for. DO NOT use the [*1:$], it serves no purpose, except overload your simulator.
import uvm_pkg::*; `include "uvm_macros.svh"
module top;
timeunit 1ns; timeprecision 100ps;
bit clk, a, b, signal;
default clocking @(posedge clk); endclocking
initial forever #10 clk=!clk;
realtime duration=45.0ns;
property glitch_p;
realtime first_change;
// realtime duration = 10;
@(signal) // pos and neg edge
// detecting every 2 changes duration
(1, first_change = $realtime) |=> (($realtime - first_change) >= duration); // [*1:$];
endproperty
ap_glitch_p: assert property(glitch_p);
always_ff @(posedge clk) begin
end
initial begin
repeat(200) begin
@(posedge clk);
if (!randomize(signal) with
{ signal dist {1'b1:=1, 1'b0:=3};
b dist {1'b1:=1, 1'b0:=2};
}) `uvm_error("MYERR", "This is a randomize error")
end
$stop;
end
endmodule
[*1:] was my fault, we don't need this.
We should use unbounded ([1:]) consequent more carefully. Every success antecedent creates a new thread, so make consequent sequence able to finish properly. Unbounded is not safe here, it will cause stack overflow issue.
adding timeunit and using realtime/real literals to provide better accuracy.