简体   繁体   English

关于Verilog触发器延迟

[英]About verilog flip flop delay

I want to buffer a single-bit signal "done" with two single-bit flip-flops. 我想用两个单位触发器来缓冲一个“完成”的单位信号。 The done signal will rise for only one clock cycle in my design. 在我的设计中,完成的信号将仅上升一个时钟周期。 So I wrote the following code. 所以我写了下面的代码。

//first level buffer done signal for one cycle to get ciphertext_reg ready
always @(posedge clk or posedge rst) begin
    if(rst)
        done_buf_1 = 1'b0;
    else
        done_buf_1 = done;
end

//second level buffer
always @(posedge clk or posedge rst) begin
    if(rst)
        done_buf_2 = 1'b0;
    else
        done_buf_2 = done_buf_1;
end

In functional simulation, I discover the done_buf_1 rises one cycle after done, but done_buf_2 rises at the same time as done_buf_1. 在功能仿真中,我发现done_buf_1在完成后上升一个周期,但done_buf_2与done_buf_1同时上升。

What is the explanation for this? 这有什么解释?

Thank you! 谢谢!

You've already got answers with the solution ("use non-blocking assignments"), but here's an attempt at why you need to do that. 您已经有了解决方案的答案(“使用非阻塞分配”),但是这里尝试了为什么需要这样做。

Both of your always statements have the same event, so they could run in any order. 您的两个always语句都具有相同的事件,因此它们可以按任何顺序运行。 What seems to be happening is that the first one is running first. 似乎正在发生的事情是第一个先运行。 When the line... 当行...

done_buf_1 = done;

... is hit, it will block until the assignment is complete (it's a "blocking" assignment). ...被点击,它将阻塞直到分配完成(这是一个“阻塞”分配)。 Therefore done_buf_1 takes the new value immediately. 因此,done_buf_1立即采用新值。 This differs from the non-blocking version... 这与非阻塞版本不同...

done_buf_1 <= done;

... which says 'give done_buf_1 the value of done (which I'll evaluate now) at the end of the time slice'. ...表示“在时间片结束时将done_buf_1的值赋予完成(我现在将对其进行评估)”。

Now we move on, and done_buf_2 is assigned. 现在我们继续,并分配done_buf_2。

done_buf_2 = done_buf_1;

Now, if done_buf_1 was updated with a blocking assignment it already has the current value of done , and you'll see both signal rise at the same time. 现在,如果用阻塞分配更新了done_buf_1 ,则它已经具有done的当前值,并且您将看到两个信号同时上升。 If it was a non-blocking assignment then done_buf_1 still has the previous value of done , as it won't be updated until the end of the time-slice, the result being a 2 cycle delay for done_buf_2 . 如果它是非阻塞分配,那么done_buf_1仍具有以前的done值,因为直到时间片结束之前它都不会更新,结果是done_buf_2有2个周期的延迟。

There's also another problem though. 但是,还有另一个问题。 Remember that I said that the always statements could be run in either order because the events were the same? 还记得我说过,因为事件相同,所以always语句可以按任意顺序运行吗? Well if the second one was executed first the code would appear to work as intended ( db2 = db1; db1 = done; No problem). 好吧,如果第二个代码先执行,那么代码似乎可以按预期工作( db2 = db1; db1 = done;没问题)。 So it's worth knowing that using blocking assignments like this gives erratic results especially between tools. 因此,值得一提的是,使用这样的阻塞分配会产生不稳定的结果,尤其是在工具之间。 That can lead to some subtle bugs. 这可能会导致一些细微的错误。

You're using blocking assignments = to model synchronous logic. 您正在使用阻塞分配=对同步逻辑进行建模。 You need to use non-blocking assignments <= . 您需要使用非阻塞分配<=

As others have said: don't use blocking assignments ( = ) for this. 正如其他人所说:不要为此使用阻塞分配( = )。

The key point is that "this" is the job of communicating between different processes. 关键是“这”是不同进程之间进行通信的工作。 The race conditions inherent in blocking assignments make this unpredictable. 阻止分配所固有的竞赛条件使这种情况无法预测。 VHDL takes this so seriously that it separates these types of assignment such that you can't use the wrong one (as long as you keep away from shared variables). VHDL非常认真地对待这一点,以至于将这些类型的分配分开,这样您就不会使用错误的分配(只要您远离共享变量)。

Some interesting writings on the subject from Jan Decaluwe: Jan Decaluwe撰写了一些有关该主题的有趣著作:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM