I am attempting to write a SystemVerilog assertion to evaluate a circumstance where a given signal (sig) maintains static value any time the design is either in or out of asynchronous reset. Meaning that I would only like the value of sig to potentially change when the value for reset (rst) has asynchronously changed. Can this be done in a truly asynchronous manner?
I attempted to use $stable to accomplish this however it is still not capturing the desired functionality.
I am not clear about your requirements:
@(rst)
$changed(rst) |-> $stable(sig); would only like the value of sig to potentially change when the value for reset (rst) has asynchronously changed
Isn’t @(rst) a change in rst?
Do you mean that @(rst) then sometime later sig can change?
What length of time?
Can you write the behavior you are checking in a task?
Ben
To clarify the change of sig would be caused only by the change in the rst signal. Thus, in a perfect world they would happen simultaneously. sig should only be able to change when rst does, but should be stable at all other times. It also important to note that it is not mandatory for sig to change when rst does. Only that if sig does change it must do so with rst.
In reply to E_R_R:
You could try something like the following:
/* The change of sig would be caused only by the change in the rst signal.
Thus, in a perfect world they would happen simultaneously.
sig should only be able to change when rst does, but should be stable at all other times. */
// if(change in rst) then a change is sig is possible
// if(change in sig) && (no change in rst) then illegal
module m;
bit sig, rst;
bit sig_stretch, rst_stretch; // support
always @(rst) begin
#1 rst_stretch =1;
#1 rst_stretch =0; // need to tune this number. maybe #2 or #3
end
always @(sig) begin
#1 sig_stretch =1;
#1 sig_stretch =0;
end
am_sig: assert #0 (!(sig_stretch && !rst_stretch)); // no sig change when no rst
endmodule
Let me know if this is working for you or how you modified this.
Ben Cohen Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.
It is not perfect - as the $changed(rst) is using tmp_sig as “clock” (to detect a change), so it sort of misses to flag the first change in tmp_sig without an accompanying change in rst, but guess you get the idea.
In reply to Srini @ CVCblr.com:
@(tmp_sig) 1’b1 |-> $changed (rst));
requires that when tmp_sig changes then $sampled(rst) is different than its previous sampled value when tem_sig occurred the last time.
There is no flexibility in the time zone when sig can change just after rst,
Good attempt Srini. Your and my solution need to be evaluated for requirements.
Ben
initial begin
sig = '0;
rst = '1;
#10;
sig = '1;
rst = '0;
#20;
sig = '0;
#5;
rst = '1;
sig = '1;
#10;
rst = '0;
end
always @(rst) begin
#1 rst_stretch = 1;
#1 rst_stretch = 0;
end
always @(sig) begin
#1 sig_stretch = 1;
#1 sig_stretch = 0;
end
am_sig: assert #0 (!(sig_stretch && !rst_stretch));
Are you aware of a way to get the same functionality to work in a formal application rather than in simulation? In the solution you shared it is still dependent on the timescale of the testbench.
I doubt if popular FV tools would support asynchronous SVA such as these. However, this seems to be a RDC-related check (more or less a structural check) and there are special tools that may fit the bill here.
this property appears to work in detecting the situation that I desire; however, it seems to flag the assertion on the edge of sig following the actual error.
I think that I may have gotten close with the solution above. However, it seems to flag the assertion on the edge of sig following the actual error. Are you aware of a way to insist that an error using the $changed operator will assess on edge of failure?
In reply to E_R_R:
With the following, I see from the waveforms that
at 10ns, with @(sig) clocking event, the sampled value of sig is 0.
Also at 10ns the sampled value of rst is 1 sampled with @(sig).
Since sig had a default value of 0, @(sig) $changed(sig) is 0.
Thus, the property is vacuous at 10ns.
At 30ns, you have @(sig) and the sampled value of sig is 1, and
the sampled value of rst is 0. Therefore,
$changed(sig) at t30 is 1 (was 0 in the previous @(sig). Also,
$changed(rst) at t30 is 1 (was 1 in the previous @(sig).
The property is true at t30.
Using the same arguments above, you can see why the assertion fails at t35.
Just as a comments, it is a strange requirement for the following:
// if(change in rst) then a change is sig is possible
// if(change in sig) && (no change in rst) then illegal
How do you implement that in RTL? Show code.
Ben
Thank you for getting back to me about this. I appreciate your feedback. Unfortunately, I am unable to access the RTL code at this time. However, I am writing the sva properties to meet the requirements outlined in an IP document for a port.
Port signal specification:
signal should be treated as a STATIC input. If the value changes during operation, data corruption will occur.
It is also mentioned that signal is independent of the clocks and thus asynchronous.
From this specification I gathered that the signal is only able to legally change state on an edge of the system reset.
In reply to E_R_R:
I read the requirements differently. “signal should be treated as a STATIC input.” says that this is an input that is hardwired, possibly after the board is built with a jumper to provide options. If you want to include rst you can use the following code that can be used in formal:
/* signal should be treated as a STATIC input. If the value changes during operation, data corruption will occur.
It is also mentioned that signal is independent of the clocks and thus asynchronous.
From this specification I gathered that the signal is only able to legally change state
on an edge of the system reset. */
bit sig_support;
always_comb begin
if(rst) sig_support=sig;
am_sig: assert #0 (!rst && sig==sig_support || rst);
end