using $past in cover property statement - system-verilog

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;

Related

How to make 4 bit ring counter with 4 flip flops?

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.

Unexpected SVA assertion behavior for a periodic 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

can packed arrays be passed by reference to the task in systemverilog

Can s_clk be passed as argument to xyz task in below code?
module test(input logic m_clk, output [1:0] logic s_clk);
...
xyz (m_clk,s_clk);//assuming m_clks and s_clks are generated from top
...
task automatic xyz (ref logic clk1, ref [1:0] logic clk2);
...
endtask
endmodule
I have read your problem, first of all you have typo mistake
module test(input logic m_clk, output [1:0] logic s_clk);
task automatic xyz (ref logic clk1, ref [1:0] logic clk2);
instead of this you have to write
module test(input logic m_clk, output logic [1:0] s_clk);
task automatic xyz (ref logic clk1, ref logic [1:0] clk2);
For better understanding I have also share one demo code for packed arrays can be passed by reference to the task in systemverilog.
Here is code :
program main();
bit [31:0] a = 25;
initial
begin
#10 a = 7;
#10 a = 20;
#10 a = 3;
#10 $finish;
end
task pass_by_val(int i);
$monitor("===============================================%d",i);
forever
#a $display("pass_by_val: I is %0d",i);
endtask
task pass_by_ref(ref bit [31:0]i);
forever
begin
#a $display("pass_by_ref: I is %0d",i[0]);
$display("This is pass_by value a ====== %d \n a[0] ====== %0d ",a,a[0]);
end
endtask
initial
begin
pass_by_val(a);
end
initial
pass_by_ref(a);
endprogram
By running this example you can observe that packed arrays can be passed by reference to the task in systemverilog and its value is also reflected to it.
pass_by_val task will register the value of the variables
only once at the time when task is called. Subsequently when the variable changes its value, pass_by_val task cannot see the newer values. On the other hand, 'ref' variables in a task are registered whenever its value changes. As a result, when the variable 'a' value changes, the pass_by_ref task can register and display the value correctly.
I simulated Ashutosh Rawal's code and the output display is given below:
=============================================== 25
pass_by_val: I is 25
pass_by_ref: I is 1
This is pass_by value a ====== 7
a[0] ====== 1
pass_by_val: I is 25
pass_by_ref: I is 0
This is pass_by value a ====== 20
a[0] ====== 0
pass_by_val: I is 25
pass_by_ref: I is 1
This is pass_by value a ====== 3
a[0] ====== 1
$finish called from file "testbench.sv", line 13.
$finish at simulation time 40
V C S S i m u l a t i o n R e p o r t

system verilog assertion trigger==1 4 cycles before signal asserted

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)
)
);

Parallel To Serial HDL

I am making a parallel to serial converter using ring counter in verilog. The ring counter is working fine but the Parallel to serial converter is not working properly and I am getting x undefined result. I am providing the code kindly help me finding the problem.
TOP
module PtoSTOP;
reg clk,rst;
wire [3:0] myout;
wire out;
Ring a(clk,rst,myout);
parToser x(myout,clk,rst,out);
initial begin
clk=1;
rst=1;
#1 rst=0;
end
always
#2 clk=~clk;
endmodule
Parallel TO Serial Converter
module parToser(myout,clk,rst,out);
input clk,rst;
input [3:0] myout;
output reg out;
reg [2:0]i;
always #(posedge clk or posedge rst) begin
if(rst) begin
out <= 0;
i <= 0;
end
else begin
out <= myout[i];
i <= i+1;
end
end
endmodule
RingCounter
module Ring(clk,rst,myout);
input clk,rst;
output reg [3:0]myout;
always #(posedge clk or posedge rst) begin
if(rst)
myout<=1;
else
myout<=myout<<1;
end
endmodule
I think the main issue you are seeing is part of parToser.
You have reg [2:0]i; which you increment and use to address input [3:0] myout; but i can hold values 0 to 7, half of which is outside the address range of [3:0] myout. You should be seeing a simulation error about out of range addressing.
Also you have included a few flip-flops with a reset condition but not added the reset to the sensitivity list in 'parToser' & 'Ring':
always #(posedge clk)
Should be:
always #(posedge clk or posedge rst)
With out this trigger your out, i and myout variables will be x, as they have not been set to a known condition.
NB: parToser i = i+1; should be i <= i+1;