This Systemverilog tutorial lists interesting always block event control statements that utilize the iff qualifier.
I don't understand the first 3 simulation results for #1 and #2:
#0 clk 0 rst 0 enable x d x q x latch x
#1 clk 1 rst 0 enable x d 0 q 0 latch x
Reset is asserted with iff
Reset is asserted, no iff
#2 clk 0 rst 1 enable x d 0 q 0 latch x
Reset is asserted, no iff
Namely, why is reset triggering the $display statements #1 when there hasn't been a posedge rst?
Also, why isn't $display(Reset is asserted with iff) triggered #2 when rst becomes 1?
The $display() messages are being printed at time #2. The simulator scheduler executes the $display() messages when the lines are reached. The $monitor() message is only printed at the end of the time step. Therefore, within the same time step, $display() messages will be printed before the $monitor() message. Add $time to the $display messages to help visualize this.
The final Reset is asserted, no iff is not part of time 2, but time 3. When the clock has a rising.
#3 clk 1 rst 1 enable x d 0 q 0 latch x
The "with iff" message is not displayed because iff rst == 0 masks the posedge clk from being observed when rst !=0. The posedge clk can only be observed when iff condition is true.
Do note that iff is not synthesizable, so do not put it in a design. The feature is for verification and behavioral modeling.
Related
I have this 4 bit ring counter that I'm trying to make, and I feel like I'm so close, but I can't figure out how to make one input depend on the previous state's output. Here's what I have:
`default_nettype none
// Empty top module
module top (
// I/O ports
input logic hz100, reset,
input logic [20:0] pb,
output logic [7:0] left, right
);
// Your code goes here...
q[3:0];
assign q[3:0] = right[3:0];
hc74_set setFF(.c(pb[0]), .d(pb[1]), .q(right[0]), .sn(pb[16]));
hc74_reset resetFF1(.c(pb[0]), .d(pb[1]), .q0(right[1]), .rn(pb[16]));
hc74_reset resetFF2(.c(pb[0]), .d(pb[1]), .q1(right[2]), .rn(pb[16]));
hc74_reset resetFF3(.c(pb[0]), .d(pb[1]), .q2(right[3]), .rn(pb[16]));
endmodule
// Add more modules down here...
// This is a single D flip-flop with an active-low asynchronous set (preset).
// It has no asynchronous reset because the simulator does not allow it.
// Other than the lack of a reset, it is half of a 74HC74 chip.
module hc74_set(input logic d, c, sn,
output logic q, qn);
assign qn = ~q;
always_ff #(posedge c, negedge sn)
if (sn == 1'b0)
q <= 1'b1;
else
q <= d;
endmodule
// This is a single D flip-flop with an active-low asynchronous reset (clear).
// It has no asynchronous set because the simulator does not allow it.
// Other than the lack of a set, it is half of a 74HC74 chip.
module hc74_reset(input logic d, c, rn,
output logic q, qn);
assign qn = ~q;
always_ff #(posedge c, negedge rn)
if (rn == 1'b0)
q <= 1'b0;
else
q <= d;
endmodule
This is on an FPGA simulator, which is why there are a few things like pb (these are push buttons) and left, right outputs which are sets of 8 LEDs each.
Let's first make sure we are on the same page
Based on wikipedia description of a ring counter
This could be implemented as follows:
module top (
// I/O ports
input logic reset_n,
input logic clk,
output logic [3:0] ring
);
// Your code goes here...
always #(posedge clk or negedge reset_n) begin
if(~reset_n) begin
ring = 4'b0001;
end
else begin
ring[0] <= ring[3];
ring[1] <= ring[0];
ring[2] <= ring[1];
ring[3] <= ring[2];
end
end
endmodule
The output ring is a 4-bit one hot vector, reset_n = 0 makes ring = 0001 every clock with reset_n = 1 rolls the ring to the right, [0001, 0010, 0100, 1000, 0001, ...].
But you want to use instances of the flops you defined. Notice that in an assignment a <= b, a is the output of the flop (q port), and b is the input of the flop (d port).
module top (
// I/O ports
input logic reset_n,
input logic clk,
output logic [3:0] ring
);
// Your code goes here...
hc74_set setFF(.c(clk), .d(ring[3]), .q(ring[0]), .sn(reset_n));
hc74_reset resetFF1(.c(clk), .d(ring[0]), .q0(ring[1]), .rn(reset_n));
hc74_reset resetFF2(.c(clk), .d(ring[1]), .q1(ring[2]), .rn(reset_n));
hc74_reset resetFF3(.c(clk), .d(ring[2]), .q2(ring[3]), .rn(reset_n));
endmodule
You have to connect the ports accordingly, I just used clk for the clock and reset_n for the negated reset signal.
Quoting from a book "Systemverilog Assertions and Functional Coverage", Ashok Mehta on page 42,
# (posedge clk) a |=> !a;
In the above sequence, let us say that variable ‘a’ changes to ‘1’ the same time
that the sampling edge clock goes posedge clk (and assume ‘a’ was ‘0’ before it
went to a ‘1’). Will there be a match of the antecedent ‘a’? No! Since a’ went from ‘0’ to ‘1’ the same time that clock went posedge clk, the value of ‘a’ sampled by clock will be ‘0’ (preponed region) and not ‘1’. This will not cause the property to trigger because the antecedent is not evaluated to be true. This will confuse you
during debug. You would expect ‘1’ to be sampled and the property triggered
thereof. However, you will get just the opposite result.
This is a very important point to understand because in a simulation waveform
(or for that matter with Verilog $monitor or $strobe) you will see a ‘1’ on ‘a’ with
posedge clk and would not understand why the property did not fire or why it
failed (or passed for that matter). Always remember that at the sampling edge, the
‘previous’ value (i.e. a delta before the sampling edge in the preponed region) of
the sampled variable is used.
I tried to test this scenario by this Testbench. However I expected assertion to FAIL at simulation times #10, #50, #90
module assert_immediate();
reg a,b,clk;
initial
begin
clk = 0;
forever #10 clk = !clk;
end
initial
begin
a = 0;
b = 0;
repeat (10) #(posedge clk) a = ~a;
end
// always#(posedge clk) $display("a = %d at time %t \n", a, $time);
property p1;
#(posedge clk) a |=> !a;
endproperty
initial #100 $finish;
assert property (p1) $display("Entered assert at %t \n", $time); else $display("FAIL at %t \n", $time);
cover property (p1) $display("PASS at %t \n", $time);
endmodule
But when I ran on EDAPlayground using VCS, I got a different behavior
# KERNEL: Entered assert at 10
# KERNEL:
# KERNEL: PASS at 10
# KERNEL:
# KERNEL: Entered assert at 50
# KERNEL:
# KERNEL: Entered assert at 50
# KERNEL:
# KERNEL: PASS at 50
# KERNEL:
# KERNEL: PASS at 50
# KERNEL:
# KERNEL: Entered assert at 90
# KERNEL:
# KERNEL: Entered assert at 90
# KERNEL:
# KERNEL: PASS at 90
# KERNEL:
# KERNEL: PASS at 90
Why do you expect your assertion to fail? You instructed your testbench to change a every posedge in the initial block so your assertion will pass when triggered (you will have a sequence of a, !a, a, !a) so I expect 2 assertion passes.
What I don't understand is that assertion passes # time 10 according to your log. Your first posedge is # time 10, so the sampled value of a is 0 (because sampling is done before the posedge and your initial value of a is 0 accroding to the initial block). This value of a wouldn't trigger the assertion (doesn't meet assertion predecessor, i.e. left hand side of the assertion).
I think that there are 2 issues there.
I think that there is a misconception in the implication operator. Assertion should not fail in your case. The implication allows for the right hand side expression to be true eventually. So, if a goes up, it will eventually go down. So, at #50 it goes down after sampled high at #30, and this cause the assertion to pass, and go to the next cycle of evaluation: #70 -> #90.
For each successful match of the antecedent sequence_expr, the consequent property_expr isseparately evaluated. The end point of the match of the antecedent sequence_expr is the start pointof the evaluation of the consequent property_expr.
there is a bug in the compiler you use. There should be no assertion message at time #10. I tried it with vcs 2017.03 and it worked correctly.
also you can add this line to you code to get some debugging prints:
always #(posedge clk) $display("%0t a = %b", $time, $sampled(a));
I got these results during the simulation:
10 a = 0
30 a = 1
50 a = 0
Entered assert at 50
PASS at 50
70 a = 1
90 a = 0
Entered assert at 90
PASS at 90
I have the following simple code:
module past;
logic clk=0;
logic[3:0] adr=0;
// Clock Gen
initial forever #10 clk = ~clk;
initial #100 $finish;
always #(posedge clk) adr <= adr+1;
sequence DUMMY_SEQ;
#(posedge clk) 1'b1;
endsequence
cover property (#(posedge clk) DUMMY_SEQ) begin
$display("ADR %h past(ADR) %h at %0t", adr, $past(adr), $time);
end
endmodule
I would expect the $past(adr) return the value of adr in previous one clock cycle. But I got below simulation result which seemingly the $past(adr) return the value of adr in previous two clock cycle. Please notice it from line number 3.
ADR 1 past(ADR) 0 at 10
ADR 2 past(ADR) 0 at 10
ADR 3 past(ADR) 1 at 10
ADR 4 past(ADR) 2 at 10
ADR 5 past(ADR) 3 at 10
Can anybody explain why it is behaving like that?
Just to be clear, I am using $display just for illustration purpose. The actual problem is I couldn't get correct $past(adr) in cover statement.
Lets forget about the $display and do something else in cover statement. For example, by right, adr - $past(adr) should never exceed 1 as per above code. If I do something like this:
cover property (#(posedge clk) DUMMY_SEQ) begin
if ( (adr > $past(adr))
&& (adr - $past(adr)) > 1) $fatal;
end
then it should never get fatal, because adr increment by 1 at each clock cycle. However, it actually does get fatal error. This is confusing. Any explanation?
$past returns the value of an expression in a previous clock cycle.
Actually, there is difference between $display and $monitor that you have to understand.
$display displays once every time code is executed.
$monitor displays every time one of its parameters changes.
If you replace $display with $monitor then you will get your expected output.
The issue you are seeing is addr is updated before the $display statement and $past. This gives the impression that $past looks two clocks behind. To resolve this, use $sampled. See IEEE Std 1800-2012 16.9.3 Sampled value functions
cover property (#(posedge clk) DUMMY_SEQ) begin
$display("ADR %h past(ADR) %h at %0t", $sampled(adr), $past(adr), $time);
end
Output
ADR 0 past(ADR) 0 at 10
ADR 1 past(ADR) 0 at 30
ADR 2 past(ADR) 1 at 50
ADR 3 past(ADR) 2 at 70
ADR 4 past(ADR) 3 at 90
Another option is to put the display as a sequence_match_item which is best explained in IEEE Std 1800-2012 16.10 Local variables
cover property (#(posedge clk) (DUMMY_SEQ, $display("ADR %h past(ADR) %h at %0t", adr, $past(adr), $time));
For fatal and error reporting, it is better to use assert:
assert property (#(posedge clk) (adr >= $past(adr)) else $fatal;
I want assertion that if in current cycle signal 'a' equal to "0110"(in binary) in the next cycle signal'b'not bigger than 31(it should be between 0 and 31.it should be less than 00000000000000000000000000011111)(its width equal 32)
Can everyone help me to write assertion?!
Excuse me for my bad english.
assert property ( # (posedge clk ) (a == 32'b0110) |=> ( b > 32'd0 && b < 32'd32 ) );
assert - will set the property( assertion ) into action. The property has to be based on a clock . Choose the appropriate clock which is triggering the registers a & b in the design. Implication operator |=> indicates that the property has to be true in the next clock cycle. In this case if a equals 6, the next cycle b has to between 0 and 32 ).
In case of a failure some similar message ( based on the simulator ) will be displayed.
top.unnamed$$_0: started at ns failed at ns
Offending '((b > 0) && (b < 32))'
You can read up a basic tutorial on assertions
https://www.doulos.com/knowhow/sysverilog/tutorial/assertions/
How would I write SVA that checks that if sig goes high trigger was high 4 cycles before trigger [*4] |-> signal
is not good enough because it does not check that signal didn't go high for 3 cycles. Should I use $past how ??
This would check that on a rising edge of sig, trigger was high 4 clk cycles ago:
assert_name: assert property (
#(posedge clk) (
($rose(sig) -> $past(trigger,4))
)
);
There's nothing stopping you writing a small piece of synthesisable RTL which counts how many cycles trigger has been high.
always #(posedge clk) begin
if (trigger) begin
triggerCount := triggerCount + 1;
end else begin
triggerCount := 0;
end
end
assert_name: assert property (
#(posedge clk) (
($rose(sig) -> triggerCount == 4)
)
);