siu*_*siu 3 verilog system-verilog
在下面显示的测试台代码中,我观察到时钟信号clk没有按预期切换。时钟在时间 5 从低电平变为高电平,但此后不再切换。
module tb();
reg clk;
initial begin
clk = 'b0;
#100 $finish;
end
always@* #5 clk = ~clk;
endmodule
Run Code Online (Sandbox Code Playgroud)
但是,如果我@*从always@*语句中删除,时钟将按预期每 5 纳秒切换一次。always@*我的问题是为什么在第一次更改后没有触发流程块?
注意:我已经在 NCSIM 和 VCS 中测试了代码,我不认为这是模拟器问题。
接受的答案是错误的 -always最初是由块中分配给 0 触发的initial,所以你有一个完全有效的问题,这就是为什么块always在第一次运行后没有触发自身(并且它显然确实运行了,因为clk设置为 1)。
运行下面的代码 - 如果您将阻塞分配更改为非阻塞分配,或者使用分配内延迟而不是延迟控制 ( clk = #5 ~clk),您将看到它按预期工作。所以,这是一个调度问题。您可能直观地期望您的流程只会触发一次,因为最终的阻塞分配和流程评估实际上发生在同一个增量中,因此阻塞分配可能会丢失。但是,我在 LRM 中看不到具体的理由。延迟控制变成未来的非活动事件,调度程序最终执行它,创建一个更新事件,该事件会更新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
Run Code Online (Sandbox Code Playgroud)