关于verilog触发器延迟

关于verilog触发器延迟,verilog,Verilog,我想用两个单位触发器缓冲一个单位信号“完成”。在我的设计中,done信号只会上升一个时钟周期。所以我写了下面的代码 //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;

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

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

对此有何解释


谢谢大家!

您正在使用阻塞分配来建模同步逻辑。您需要使用非阻塞分配
您已经得到了解决方案的答案(“使用非阻塞分配”),但下面尝试一下为什么需要这样做

您的两个
始终
语句都有相同的事件,因此它们可以按任意顺序运行。似乎正在发生的是,第一个正在运行。当这条线

done_buf_1 = done;
。。。如果被击中,它将阻塞直到分配完成(这是一个“阻塞”分配)。因此,done_buf_1立即获取新值。这与非阻塞版本不同

done_buf_1 <= done;
现在,如果用阻塞分配更新了
done\u buf\u 1
,它的当前值已经是
done
,您将看到两个信号同时上升。如果是非阻塞分配,则
done\u buf\u 1
仍具有以前的值
done
,因为它在时间片结束之前不会更新,结果是
done\u buf\u 2
有2个周期的延迟


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

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

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

Jan Decauwe关于这个主题的一些有趣的文章:


我几乎不了解任何verilog,对此我也不太确定,但您是否需要使用See here来很好地解释阻塞和非阻塞语句:@Tim谢谢您的参考!我对你分享的第二篇文章的解释感到困惑。s、t、u之间的关系是什么?s、t、u是在三个单独的进程中执行的信号更新,其中一个进程触发进程P和Q运行。关键是不需要任何关系,不管它们以什么顺序运行,因为P和Q在更新完成之前都不会执行。
done_buf_2 = done_buf_1;