Gate-level timing checks in SVA - system-verilog

I need to check the value of a signal after a certain amount of time a clock edge occurs. For example, I want to check that if signal b asserts to high 1ps after posedge clock occurs.
Does SVA provide a syntax for this?

system-verilog-assertions were not intended for use as gate-level timing checks. Verilog already provides a number of built-in and optimized timing checks like $setuphold and $skew. See section 31. Timing checks in the IEEE 1800-2017 SystemVerilog LRM.
Timing checks are usually expressed as limits—either assertion happens at least 1ps after the clock edge, or at most 1ps after the clock edge. Also, must b be asserted after every clock edge? Regardless of the answers to these questions, it's possible to use SVA to model timing check, but you will have to manually create equations based on the actual requirements. For example
property p;
realtime timestamp;
#(posedge c) ($rose(a), timestamp = $realtime) |=>
#(posedge b) $realtime - timestamp < 1ps;
endproperty

Related

how to write a coverpoint to check a signal is on after a particular signal is on?

Here, I am trying to write a cover point to check after signal a is on, Is there any signal b(on).
check: coverpoint {a,b}{
bins hit = {2'b11}
}
I believe that the above cover point checks when both signals are on. I am not sure how we exactly write the scenario I mentioned. Any help would be appreciated. And also please help me with the best resources if you know to learn system Verilog.
cover directive are much better with temporal sequences than a covergroup but that requires a sampling clock:
check: cover property (#(posedge clk) a |-> ##[*] b; );

systemverilog comparing two ways to wait signal; 1) #( clock iff condition), 2) while( ! condition) #(clock);

I am looking for some intuitive understanding of systemverilog method of waiting for certain signal on the interface for 1) capturing transaction in a monitor, or 2) driving a transaction in response to some signal from DUT. Let's assume that DUT is asserting ready signal and driver has to drive two data beats (values of 1 and 2) back to back while asserting valid signal so that DUT would know when to capture data.
There are two methods of waiting for the ready single from the DUT that I know of; 1) one is iff conditioned clock event, and the other is 2) consuming clock while some signal is not true (e.g., ready is low). The testbench code can be found EDA playground (line 37 of my_driver.sv).
The first method is using #(posedge dut_vif.clock iff(dut_vif.ready == 1));
and the second method is using while( ! dut_vif.ready) #(posedge dut_vif.clock); and there is single clock difference between two methods as shown in the waveform. My best understanding is --
#(posedge dut_vif.clock iff(dut_vif.ready == 1));
This method is waiting for the clock rise event 'on the condition' of ready == 1. Therefore, data and valid are driven high on 25ns.
while( ! dut_vif.ready) #(posedge dut_vif.clock);
On the other hand, this statement means that simulation should consume clock while ready is low. However this interpretation and the actual behavior of systemverilog is very different. At 15ns, ready signal goes high and the valid and data are driven at the same cycle. My understanding is that at 15ns, the ready should be still captured as low by the testbench, and simulation should consume one clock. Therefore, the second method should behave just like the first method.
Can I get some interpretation on how to make sense of this difference?
I am attaching waveform here.
The issue is because of hidden delta delay inside the call to get_next_item() Even though the time is still at 15, counter and thus ready now have their new values after returning from the call. Using iff gives you a clearer sampling of values w.r.t the clock edge. It also avoids problems when !ready is x because that evaluates to false.
#(event iff (expression));
is equivalent to
do #event; while (!expression);
not
while (!expression); #event;
as Dave mentioned at here, maybe he forget it. That's why you missed one clock cycle.

assertion for holding the reset for a long time

I see that assertions are always related to n number of cycles of a clock. Is there any way I can check the duration wrt timescale? Meaning
let's say I want to check if a reset is hold for 100ns or less, how do we write a assert statement for this?
Yes, conceptually you can write an assertion like this, using local variables in SVA.
It may look like this :
property reset_chk;
time current_time;
#(rst) (~rst, current_time = $time) |=> ($time - current_time == 100);
endproperty
But this type of assertions, should be avoided, as they are written not wrt clock.
Alternatively, one can always make a reference clock, fast enough to accommodate any such signal timings.
For local variables in assertion, you can read Local Variables in SVA
First I would consider whether SVA was the best way to check this at all.
If you think so, how about creating a dummy clock in the testbench with a suitable period and (via the power of hierarchical naming) use that. A suitable period might be
100ns if you were looking for a minimum pulse width
much faster if you were looking for a maximum pulse width (eg a 10ns period would allow you to check the pulse width was less than 110ns, ie 11 cycles).
Assertions are best done synchronously. That doesn't mean you cannot check asynchronous things, but you still need to sample the signals in question synchronously. So, this way you are sampling your asynchronous signal synchronously, using your dummy clock.
This is asynchronous check. The best way is to check it in traditional way or pure systemverilog instead of using SVA concurrent assertion.
If you want, you can still add immediate assertion for coverage purpose.
Quick sample code:
//
task assert_reset_hold_100ns();
fork : fk1
begin : blk1
#(reset);
$fatal;
end
begin : blk2
#100ns;
ASSERT_RESET_HOLD_100NS: assert(1);
end
join_any
disable fork;
endtask
// checker
initial forever begin
wait(reset === 0);
assert_reset_hold_100ns();
wait(reset === 1);
end
//

System Verilog always_latch vs. always_ff

I am confused about the usage of statements always_ff and always_latch.
The former would be used as:
always_ff # (posedge clk)
begin
a <= b;
end
while the latter:
always_latch
begin
a <= b;
end
The first is activated just by the positive edge of the clock and, coupled with nonblocking assignment, produces a FF.
The always_latch is obviously thought to represent a latch, but then why use a nonblocking assignment?
Wouldn't it be better using an always_comb with blocking assignments?
By using always_latch or always_ff a designers intent to infer a latch or a sequential logic respectively, but if the logic is not correct software tools can warn the designer that the intended hardware logic is not inferred properly.
eg:
always_ff # (posedge clk or negedge rst)
begin
if (!rst)
a <= '0;
end
For the above code the designer intended to get only a sequential logic and not a latch but a latch would be generated in actual (Any static tool will generate a warning message as "Latch will be inferred for the logic")
Similarly for the below code the designers intent is to infer a hardware latch so tool will(understand your logic better) and won't report it.
always_latch
begin
if (rst)
a <= b;
end
Latch is a sequential logic which works on levels of clocks instead of clock edges.
In general best practice is to use Non-blocking assignments for sequential logic and blocking assignments for combinatorial logic which is explained in detail under Section 5.0
Verilog coding guidelines of Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill!
Guideline #2: When modeling latches, use nonblocking assignments.
From IEEE Std 1800-2012, section "9.2.2.3 Latched logic always_latch procedure":
The always_latch construct is identical to the always_comb construct
except that software tools should perform additional checks and warn
if the behavior in an always_latch construct does not represent
latched logic, whereas in an always_comb construct, tools should check
and warn if the behavior does not represent combinational logic.
The code example in the Std shows the always_latch using a non-blocking assignment.

Clock skew assertion

Is it possible to have absolute delays specified in Sequences for assertions as shown below:
sequence Sab
a # 2ns b;
endsequence
This doesn't compile for sure. But I just wanted to know how to go about such situations when we want to write assertions for delays not in terms of clock cycles?
Eg: I want to write an assertion to check the skew relationship between 2 clocks? How do I specify an assertion to fire when the skew exceeds say 5 ps?
You use timing checks like $skew. See Section 31 of the IEEE Std 1800-2012 LRM