了解Verilog分层事件队列

时间:2019-10-19 20:33:25

标签: verilog system-verilog iverilog

我试图了解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),因为它适用于上面的示例?

谢谢!

enter image description here

1 个答案:

答案 0 :(得分:2)

您正确地说非阻塞作业(NBA)和连续作业(CA)就像两步过程一样,因为它们是。问题是您所说的“下一个时间步长”不是时间上的进步;它是while()循环的迭代,没有提前的时间。这通常称为 delta-step

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

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