2

我想用两个单比特触发器缓冲一个“完成”的单比特信号。在我的设计中,完成信号只会上升一个时钟周期。所以我写了下面的代码。

//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

在功能仿真中,我发现 done_buf_1 在完成后上升一个周期,但 done_buf_2 与 done_buf_1 同时上升。

对此有何解释?

谢谢!

4

3 回答 3

3

您已经得到了解决方案的答案(“使用非阻塞分配”),但这里尝试说明您为什么需要这样做。

您的两个always语句都具有相同的事件,因此它们可以按任何顺序运行。似乎正在发生的事情是第一个先运行。当线路...

done_buf_1 = done;

...被击中,它将阻塞直到分配完成(这是一个“阻塞”分配)。因此 done_buf_1 立即采用新值。这与非阻塞版本不同......

done_buf_1 <= done;

...它说'给 done_buf_1 在时间片结束时完成的值(我现在将评估)'。

现在我们继续,并分配了 done_buf_2。

done_buf_2 = done_buf_1;

现在,如果done_buf_1使用阻塞分配对其进行了更新,则它的当前值为done,您将看到两个信号同时上升。如果它是一个非阻塞赋值,那么它done_buf_1仍然具有之前的值done,因为它直到时间片结束才会更新,结果是 2 个周期延迟done_buf_2

不过还有另一个问题。还记得我说过,因为事件是相同的,因此 always 语句可以按任意顺序运行吗?好吧,如果首先执行第二个,则代码似乎可以按预期工作(db2 = db1; db1 = done;没问题)。所以值得知道的是,使用像这样的阻塞分配会产生不稳定的结果,尤其是在工具之间。这可能会导致一些微妙的错误。

于 2012-06-18T08:20:09.193 回答
2

您正在使用阻塞分配=来模拟同步逻辑。您需要使用非阻塞分配<=

于 2012-06-16T17:53:14.087 回答
1

正如其他人所说:不要=为此使用阻塞分配()。

关键是“this”是不同进程之间通信的工作。阻塞分配中固有的竞争条件使这种情况变得不可预测。VHDL 非常重视这一点,它将这些类型的赋值分开,这样你就不能使用错误的赋值(只要你远离共享变量)。

Jan Decaluwe 关于这个主题的一些有趣的著作:

于 2012-06-18T11:03:09.317 回答