Reputation: 455
I want to execute always block at time zero. For e.g. below code won't execute at time zero.
always @* begin
//functional code
end
I moved sensitivity list at the end so that code will execute at time zero,
always begin
//funcitonal code
@*;
end
This code executes at time zero but does not execute at all after time zero, even if there is a change in inputs used inside the block. For example see the code below and its output:
module AlwaysTimeZeroTest_v();
reg reg_A;
initial begin
$display ("I'm in Initial begin block \tTime=%f, reg_A=%b\n",$stime,reg_A);
#1
reg_A=1'bZ;
#1
reg_A=1'b1;
#1
reg_A=1'b0;
#1
reg_A=1'bZ;
#5 $finish;
end
always @* begin
$display ("I'm in Non-time Zero always block\tTime=%f, reg_A=%b\n",$stime,reg_A);
end
always begin
$display ("I'm in time Zero always block \tTime=%f, reg_A=%b\n",$stime,reg_A);
@*;
end
endmodule
Output:
**I'm in Initial begin block Time=0.000000, reg_A=x
I'm in time Zero always block Time=0.000000, reg_A=x
I'm in Non-time Zero always block Time=1.000000, reg_A=z
I'm in Non-time Zero always block Time=2.000000, reg_A=1
I'm in Non-time Zero always block Time=3.000000, reg_A=0
I'm in Non-time Zero always block Time=4.000000, reg_A=z**
Simulation complete via $finish(1) at time 9 NS + 0
Can anyone explain why second always block in the code do not execute at all after time zero?
Is there a way I can implement always block so that it executes at time zero without using initial block? (something similar to always_comb in SV?)
Upvotes: 0
Views: 2195
Reputation: 42623
Many people do not realize that @
is a statement modifier, not construct by itself. It says to delay the statement that follows until there is an event. @(A or B)
means wait until there is a change in the value of A
or B
(not to be confused with a change in the result of A|B
). @*
means look at the statement that follows, and build an implicit sensitivity list of signals to wait for a change.
In your first always
, the statement that follows is a begin/end
block, so reg_A
gets added to the sensitivity list. In your second always
, the statement that follows is a null statement, so there is no sensitivity to any change.
The only way to make sure that always @*
executes at time zero is to put some reference to variable in the block that has a change at time 0. Then use a non-blocking assignment to that variable to avoid any time 0 race conditions.
Better yet, use alway_comb
which was especially designed to solve this problem.
Upvotes: 6
Reputation: 61
You tagged this system-verilog so I'll give the answer with respect to that.
If your current usage is always @*
and you don't drive the outputs from multiple always blocks, use always_comb. Per LRM, always_comb
will be executed at time 0.
module AlwaysTimeZeroTest_v();
reg reg_A;
initial begin
$display ("I'm in Initial begin block \tTime=%f, reg_A=%b\n",$stime,reg_A);
#1
reg_A=1'bZ;
#1
reg_A=1'b1;
#1
reg_A=1'b0;
#1
reg_A=1'bZ;
#5 $finish;
end
always_comb begin
$display ("I'm in Non-time Zero always block\tTime=%f, reg_A=%b\n",$stime,reg_A);
end
always_comb begin
$display ("I'm in time Zero always block \tTime=%f, reg_A=%b\n",$stime,reg_A);
// @*;
end
endmodule
Upvotes: 0