Always block execution at time zero

限于喜欢 提交于 2019-12-13 20:23:03

问题


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


回答1:


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.




回答2:


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


来源:https://stackoverflow.com/questions/45990457/always-block-execution-at-time-zero

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!