了解 Verilog 分层事件队列

Understanding the Verilog Stratified Event Queue

我正在尝试了解 Verilog 调度算法的工作原理。下面的示例输出 0, xxxx 而不是 1010。我不清楚为什么。如果我在 $display 之前延迟,它会输出 1010.

module test;
  reg [3:0] t_var;
  initial begin
    t_var <= 4'b1010;
    $display("%0t, %b", $realtime, t_var);
  end
endmodule

相同的输出,0, xxxx,对于以下示例:

module test;
  reg [3:0] t_var;
  wire [3:0] y;
  assign y = ~t_var;
  initial begin
    t_var = 4'b1010;
    $display("%0t, %b, %b", $realtime, t_var, y);
  end
endmodule

根据示例,非阻塞赋值连续赋值似乎都是两步过程,其中 RHS 在当前时间步和 LHS 计划在下一个时间步(如果未指定延迟)或稍后的时间步(如果指定了延迟)发生。

有人可以确认并向我解释以下算法的分步流程(来自 Clifford Cummings),因为它适用于上述示例吗?

谢谢!

你说非阻塞赋值 (NBA) 和连续赋值 (CA) 就像两步过程一样,这是正确的,因为它们是。问题是你所说的 "the next time-step" 不是时间的提前;它是 while() 循环的迭代,没有提前时间。这通常称为 delta-step

使用 NBA 时,LHS 被安排为 NBA 更新事件,但在那之后,$display 是下一个要执行的活动事件。它在 NBA 更新事件有机会执行之前打印 y 的值。一旦你引入延迟,NBA 就有机会在推进到下一个事件时间之前执行。

使用 CA 时,您正在创建一个单独的进程,该进程在 RHS 更改时激活,它在同一活动区域中对 LHS 进行分配。 initial 和 CA 是两个独立的进程,活动区域中语句之间的顺序是不确定的。因此,无论您看到 y 的旧未初始化值还是 y 的更新值,都是竞争条件。您将看到模拟器之间的差异,具体取决于它们如何优化此代码。