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