Verilog:always@* block 未触发

标签 verilog system-verilog

在下面显示的测试台代码中,我观察到时钟信号clk未按预期切换。 时钟在时间 5 从低电平变为高电平,但此后不再切换。

module tb();
  reg clk;
  initial begin
     clk = 'b0;
     #100 $finish;
  end
  always@* #5 clk = ~clk;
endmodule

但是,如果我从 always@* 语句中删除 @*,时钟就会按预期每 5ns 切换一次。我的问题是为什么进程 block always@* 在第一次更改后没有被触发?

注意:我已经在 NCSIM 和 VCS 中测试了代码,我不认为这是模拟器问题。

最佳答案

接受的答案是错误的 - always 最初是由 initial block 中的 0 赋值触发的,所以你有一个完全有效的问题,这就是为什么always block 在第一次运行后不会自行触发(它显然确实运行了,因为 clk 设置为 1)。

运行下面的代码 - 如果您将阻塞分配更改为非阻塞分配,或者使用内部分配延迟而不是延迟控制(clk = #5 ~clk)。所以,这是一个调度问题。您可能直观地期望您的流程只会触发一次,因为最终的阻塞分配和流程评估实际上发生在同一个增量中,因此阻塞分配可能会丢失。但是,我在 LRM 中看不到具体的理由。延迟控制变成 future 的非事件事件,调度程序最终执行它,创建一个更新事件,该事件更新clk(您会看到这种情况发生一次)。然后,这应该为该进程创建一个评估事件,因为它对clk敏感,但它没有这样做。调度部分(非常)困惑,并没有真正涵盖这一点。如果你问导师,他们可能会告诉你他们对正在发生的事情的看法。 VHDL 通过使所有信号分配非阻塞来避免这个问题。

   module tb();
      reg clk1, clk2, clk3;
      initial begin
         $monitor($time,, "clk1 = %b; clk2 = %b, clk3 = %b", clk1, clk2, clk3);
         clk1 = 1'b0;
         clk2 = 1'b0;
         clk3 = 1'b0;
         #100 $finish;
      end

      always @* 
         #5 clk1 = ~clk1;

      always @*
         #5 clk2 <= ~clk2;

      always @(clk3) 
         clk3 <= #5 ~clk3;
   endmodule

关于Verilog:always@* block 未触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46962002/

相关文章:

verilog - seg Controller 故障计数器如何解决

Verilog 模块顺序

verilog - 防止 Systemverilog 文本替换宏中的参数替换

system-verilog - 静态任务函数声明中的引用参数是非法的是什么意思?

editor - Gvim 折叠系统 verilog 关键字对

concatenation - 使用串联符号扩展

Verilog 中 Always block 内的递归

floating-point - 系统 Verilog 中的浮点除法

c++ - 使用 DPI 从 C++ 函数中的 SV 读取值时出错

macos - 有没有适用于 Mac 的 Verilog IDE