为什么像这样的非阻塞赋值会导致进程重新进入?

huangapple go评论48阅读模式
英文:

Why would a non-blocking assignment like this cause the process to re-enter?

问题

always @(clk) begin #10 clk <= ~clk;end       //工作正常
always @(clk) begin #10 clk = ~clk;end        //不工作

工作正常表示执行重新进入always块,行为类似振荡器。
不工作表示只执行一次。

我已阅读Verilog标准中的调度语义部分,按我理解,一个时间步内,进程中的所有语句同时放置在层次化事件队列中,直到遇到进程中的时序控制语句时暂停进程。然后对这些语句进行排序和排序。如果语句在begin end块中,需要按照它们出现的顺序进行排序。

按我理解,阻塞赋值和非阻塞赋值都可以生成一个跳动的时钟,因为在进程中检测到时序控制语句之前会先发生。

一个时间步内的事件评估是逐句进行的吗?还是我对此有误解?

为什么非阻塞赋值的更新事件可以在同一个时间步内触发敏感事件?
你能告诉我事件的评估和更新是如何进入层次化事件队列的吗?

英文:
always @(clk) begin #10 clk &lt;= ~clk;end       //works
always @(clk) begin #10 clk = ~clk;end        //doesn&#39;t work

Works means execution re-enters the always block, behaves like a oscillator.
Does not work mean it execute only once.

I've read Scheduling semantics part in Verilog Standard, as I understand it now, in a time step, all statements in the process are placed in the hierarchical event queue at the same time, until the process is suspended when the timing control statement in the process is encountered. The statements are then sorted and sorted. If the statements are in a begin end block, the statements need to be sorted in the order in which they appear.

As I understand it, both blocking and non-blocking assignments can generate a flapping clock because the timing control statement in the process is detected before the assignment is updated.

Is the evaluation of events in a time step done sentence by sentence? Or there's something wrong with my understanding.

Why can a non-blocking update event trigger a sensitive event at the same time step?
Could You tell me how evaluation and update events enter the hierarchical event queue?

答案1

得分: 3

为了更好地理解这一点,您需要在always循环中展开该语句。

initial #0 clk = 0; //我假设您已经有了这段代码。
initial begin
    @(clk) #10 clk &lt;= ~clk;
    @(clk) #10 clk &lt;= ~clk;
    @(clk) #10 clk &lt;= ~clk;
...
end

这段代码之所以有效,是因为在遇到第一个@clk后,clk被设置为0。它等待10个时间单位,然后执行非阻塞赋值语句。在非阻塞赋值更新clk的值之前,下一个@(clk)就被遇到了。

在第二种情况下,

initial #0 clk = 0; //我假设您已经有了这段代码。
initial begin
    @(clk) #10 clk = ~clk;
    @(clk) #10 clk = ~clk;
    @(clk) #10 clk = ~clk;
...
end

同样,第一个@clkclk被设置为0。但由于现在有一个阻塞赋值语句,clk的更新会先发生,然后遇到@(clk)。所以它等待clk的改变,但这个改变永远不会发生。

事件控制的关键在于它们必须在执行过程线程中的任何事件表达式发生变化之前被遇到。请注意,我添加了#0来确保先看到@。没有延迟的话,就会出现竞争条件。即使在原始代码中使用always结构建模时,仍然存在竞争条件,但大多数用户不会看到这一点,因为模拟器倾向于在initial进程之前启动always进程。

在您的情况下,不需要事件控制。您可以简单地编写:

always #10 clk = ~clk;

甚至更好的写法是

initial begin
   clk = 0; //确保在时间0时不会发生posedge。
   forever #10 clk = ~clk;
end
英文:

To better understand this, you need to unroll the statement in the always loop.

initial #0 clk = 0; // I&#39;m assuming you have this code already. 
initial begin
    @(clk) #10 clk &lt;= ~clk;
    @(clk) #10 clk &lt;= ~clk;
    @(clk) #10 clk &lt;= ~clk;
...
end

This works because clk is set to 0 after encountering the first @clk. It waits 10 time units and then executions the nonblocking assignment statement. The next @(clk) is encountered before the nonblocking assignment updates the value of clk.

In the second case,

initial #0 clk = 0; // I&#39;m assuming you have this code already. 
initial begin
    @(clk) #10 clk = ~clk;
    @(clk) #10 clk = ~clk;
    @(clk) #10 clk = ~clk;
...
end

Again,clk is set to 0 after encountering the first @clk. But since you now have a blocking assignment statement, the update to clk occurs first, and then you encounter the @(clk). So it waits for a change on clk that never happens.

The key thing about event controls they have to be encountered in the procedural thread of execution before any change to the event expression happens. Note that I added a #0 to make sure the the @ is seen first. Without the delay, there is a race condition. There is still a race condition when the original code was modeled with an always construct, but most users do not see this because simulators tend to start always processes before initial processes.

In your case, there is no need for an event control. You can simply write:

always #10 clk = ~clk;

Even better is

initial begin
   clk = 0; // make sure that a posedge does not occur at time 0.
   forever #10 clk = ~clk;
end

huangapple
  • 本文由 发表于 2023年5月8日 00:49:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76195170.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定