关于verilog触发器延迟

时间:2012-06-16 16:12:03

标签: verilog

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

//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同时上升。

对此有何解释?

谢谢!

3 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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

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