【问题标题】:Always block execution at time zero总是在零时间阻塞执行
【发布时间】:2017-08-31 21:38:44
【问题描述】:

我想在零时间执行总是阻塞。 例如下面的代码不会在零时间执行。

always @* begin
//functional code
end

我在最后移动了敏感度列表,以便代码在零时间执行,

always begin
//funcitonal code
@*;
end

此代码在时间为零时执行,但在时间零之后根本不执行,即使块内使用的输入发生变化也是如此。例如看下面的代码及其输出:

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

输出:

**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**

通过 $finish(1) 在时间 9 NS + 0 完成模拟

谁能解释为什么代码中的秒总是阻塞在时间为零之后根本不执行?

有没有一种方法可以实现总是阻塞,以便它在零时间执行而不使用初始块? (类似于 SV 中的 always_comb?)

【问题讨论】:

    标签: verilog system-verilog


    【解决方案1】:

    很多人没有意识到@ 是一个语句修饰符,而不是自己构造的。它说延迟随后的声明,直到有事件发生。 @(A or B) 表示等到AB 的值发生变化(不要与A|B 的结果变化混淆)。 @* 表示查看下面的语句,并构建一个隐含的信号敏感度列表以等待更改。

    在您的第一个always 中,后面的语句是begin/end 块,因此reg_A 被添加到敏感度列表中。在您的第二个 always 中,后面的语句是 null 语句,因此对任何更改都不敏感。

    确保always @* 在时间 0 执行的唯一方法是在时间 0 发生变化的块中放置一些对变量的引用。然后对该变量使用非阻塞赋值以避免任何时间 0比赛条件。

    更好的是,使用专为解决此问题而设计的alway_comb

    【讨论】:

    • 感谢戴夫的解释。 Verilog中有always_comb的替代品吗?
    • 这取决于导致块在时间 0 不执行的情况。一个建议可能是确保敏感列表中的所有内容都声明为线。
    【解决方案2】:

    你标记了这个系统-verilog,所以我会给出答案。 如果您当前的使用是always @*,并且您不驱动多个always 块的输出,请使用always_comb。根据 LRM,always_comb 将在时间 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
    

    【讨论】:

      猜你喜欢
      • 2017-07-23
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多