You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Verilog与VHDL如何处理(n+delta)周期后的冲突赋值以正确解决电路毛刺?

Verilog与VHDL中OR门毛刺场景的行为机制解析

咱们先把问题背景理清楚:假设有一个实现((a AND b) OR c)的组合逻辑电路,输入a、b、c是同步变化的(比如都来自时钟寄存器输出)。这里AND门延迟可忽略,OR门有5ns的显著延迟,我们用两个独立进程来建模,代码如下:

Verilog 实现

// 进程1:计算AND门输出
always @(a, b) begin
    temp <= a & b;
end

// 进程2:带延迟的OR门输出
always @(temp, c) begin
    out <= #5 temp | c;
end

VHDL 实现

-- 进程1:计算AND门输出
process(a, b)
begin
    temp <= a and b;
end process;

-- 进程2:带延迟的OR门输出
process(temp, c)
begin
    out <= temp or c after 5ns;
end process;

当输入从(a=1, b=1, c=0)跳变到(a=0, b=1, c=1)时,会出现一个容易混淆的调度场景:

  • temp(AND门输出)会在0ns的后续delta周期内从1变为0,触发OR门的赋值调度;
  • c同时从0变为1,也会触发OR门的赋值调度。

如果按照简单模型,可能会误以为两个调度都在5ns执行,且执行顺序错误会导致out错误停留在0,但实际上Verilog和VHDL都有明确的机制保证结果正确,核心逻辑和你之前设想的三种机制都不同:


核心机制:延迟赋值的右侧表达式触发时立即计算

无论是Verilog的<= #5 ...还是VHDL的after 5ns延迟赋值,它们的执行流程都是两步走:

  1. 触发时刻计算值:当敏感信号(temp或c)发生变化时,立即计算延迟赋值右侧表达式的当前值(而非等到延迟时间点再计算);
  2. 调度未来赋值:把“在指定延迟后(这里是5ns)将该计算值赋给目标信号”的事件,放入对应时间点的事件队列。

放到咱们的场景里具体看:

  • 当c在0ns从0变为1时,触发进程2,此时temp还没更新(还是1),计算temp | c得到1 | 1 = 1,于是调度“5ns后给out赋值1”;
  • 当temp在0ns的后续delta周期从1变为0时,再次触发进程2,此时c已经是1了,计算temp | c得到0 | 1 = 1,于是又调度“5ns后给out赋值1”。

到5ns时,两个调度事件执行的都是给out赋值1,无论执行顺序如何,最终out的结果都是正确的1,不会出现错误的0。


两种语言的细节差异

虽然核心逻辑一致,但两者在事件队列的管理上有细节区别:

  • Verilog:依赖分层事件队列(Stratified Event Queue),延迟赋值的事件会被放入「未来时间队列」的对应时间点,同一时间点的事件会按调度顺序执行,但由于每个事件的赋值是预先计算好的固定值,最终结果只取决于所有赋值的内容,而非顺序;
  • VHDL:将延迟赋值视为信号的事务(Transaction),同一信号的事务会被放入事件队列,到达指定时间后按调度顺序处理,同样,每个事务的赋值是预先计算的固定值,最终信号值取最后一次赋值的结果(但在这个场景里两次赋值都是1,结果一致)。

简单来说,两种语言都通过「预先计算赋值结果,再调度未来执行」的方式,从根源上避免了因延迟时间点输入变化导致的错误,完美解决了你担心的调度顺序问题。

内容的提问来源于stack exchange,提问作者Martin Geisse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 12:44:09