4. 数字仿真引擎核心机制

在混合信号协同仿真中,数字侧通常由事件驱动(event-driven)仿真器承担,例如 Verilog 的 vsim、VHDL 的 GHDL 或商业仿真内核。它与模拟侧 SPICE 的“时间步进”求解方式截然不同:模拟求解器按固定或自适应时间步长推进,而数字仿真器只在“有事件发生”的时刻推进时间。理解事件驱动机制,是判断混合仿真中数字延迟、采样时刻与跨域同步是否正确的关键。

事件、时间轮与调度队列

数字仿真器的核心数据结构是时间轮(time wheel)与事件队列。每个事件由“时间戳 + 信号 + 新值”组成,被插入到对应的时间槽中。仿真器维护一个“当前仿真时间”,每次从队列中取出时间戳最小的事件,把时间推进到该时刻,然后执行该事件引发的进程。若同一时刻存在多个事件,则按调度区域(region)顺序处理,而不是按插入顺序。

Verilog 的调度分为若干区域:Active、Inactive、NBA(Non-Blocking Assignment)、Observed、Reactive 等。阻塞赋值 = 在 Active 区立即更新并可能触发后续进程;非阻塞赋值 <= 则先计算右值,把更新排入 NBA 区,在当前时间步末尾统一生效。这一区别直接决定了时序逻辑是否会出现竞争。例如:

always @(posedge clk) begin
  q1 = d;        // 阻塞:立即更新,可能影响同一时刻其他语句
  q2 <= q1;      // 非阻塞:读取旧 q1,NBA 区更新
end

若把 q2 <= q1 写成 q2 = q1,则 q2 会读到本时刻刚被阻塞赋值更新的 q1,形成与预期不同的“穿透”行为。这正是事件调度区域存在的意义:用区域划分消除同一时间步内的求值顺序歧义。

事件驱动数字仿真:时间轮与调度区域 仿真时间 → t=10ns t=15ns t=20ns t=25ns t=30ns 同一时间步内的调度区域顺序 Active 区 阻塞赋值 / 连续赋值 Inactive 区 零延迟事件 NBA 区 非阻塞赋值更新 Observed 断言采样 延迟建模:惯性延迟 vs 传输延迟 惯性延迟:窄脉冲被滤除(#5 后新事件覆盖旧事件) 传输延迟:所有脉冲按时间顺序保留(适合连线建模)

延迟建模:惯性延迟与传输延迟

数字仿真中的延迟不是“等待”,而是把事件重新排入未来时间槽。Verilog 提供两类延迟模型:惯性延迟(inertial delay)与传输延迟(transport delay)。惯性延迟是默认行为,它模拟真实门电路的惯性:如果输入脉冲宽度小于延迟值,输出不会响应。例如 assign #5 y = a;,当 a 在 2ns 内快速翻转两次,第一次的更新事件会被第二次覆盖,y 不产生窄脉冲。传输延迟则用 assign #5 y = transport a; 表达,所有事件按顺序保留,适合建模理想连线或长走线。

在混合信号协同仿真中,数字输出到模拟域的接口通常需要显式延迟。若数字侧使用惯性延迟,而模拟侧按连续时间接收,则窄脉冲可能在跨域时被“吞掉”。因此跨域连接建议使用传输延迟或显式插入延迟单元,并在协同仿真配置中声明接口的采样时刻。

数字逻辑值系统:四值与九值

Verilog 使用四值逻辑:0、1、x(未知)、z(高阻)。VHDL 的 std_logic 扩展为九值,包括 'U'(未初始化)、'X'(强未知)、'0'、'1'、'Z'、'W'(弱未知)、'L'、'H'、'-'(无关)。这些值在仿真开始时默认是 x 或 'U',必须通过复位或初始化赋值才能进入确定状态。

逻辑值系统直接影响跨域映射。当数字信号为 x 或 z 时,模拟侧无法直接解释为电压。常见做法是:在接口模块中把 x 映射为中间电平或高阻,把 z 映射为高阻态,并在协同仿真控制脚本中设置“未知值处理策略”。若忽略这一点,混合仿真可能在复位前出现不确定的模拟电压,导致收敛失败或误判。

一个可复现的调度观察示例

下面给出一个用于观察调度顺序的测试平台片段。它不依赖具体工具,可在任意 Verilog 仿真器中运行。示例参数为假设值,用于说明机制,不代表实测结果。

module sched_demo;
  reg clk = 0, a = 0, b = 0;
  always #5 clk = ~clk;          // 10ns 周期

  always @(posedge clk) begin
    a = 1;                        // Active 区阻塞赋值
    b <= a;                       // NBA 区读取旧 a
    $display("T=%0t a=%b b=%b", $time, a, b);
  end
endmodule

在 t=5ns 的第一个上升沿,a=1 立即生效,而 b<=a 读取的是赋值前的 a(0),因此该时刻打印 a=1 b=0;到 NBA 区结束后 b 才变为 1。若把 b<=a 改为 b=a,则同一时刻打印 a=1 b=1。这个差异就是调度区域带来的可观察结果,也是排查数字侧竞争问题的基本手段。

在混合信号协同仿真中,建议把数字侧所有跨域输出统一使用非阻塞赋值或显式延迟,避免在 Active 区直接驱动模拟接口,从而减少跨域采样时刻的不确定性。

时间轮与混合仿真的时间同步

混合仿真器需要把数字事件时间与模拟时间步对齐。常见策略是:模拟求解器推进到下一个“数字事件时间”之前,先让数字仿真器处理完该时刻所有区域的事件,再把数字输出保持到模拟侧。若数字侧存在零延迟组合环路,时间轮会在同一时刻反复触发,仿真器可能报“零延迟振荡”。此时应检查组合逻辑是否形成无延迟反馈,必要时插入 #1 或使用传输延迟打破环路。

掌握事件驱动机制后,就能理解为什么数字仿真“快”而模拟仿真“慢”:数字只在事件时刻计算,空闲时间被跳过;模拟必须持续积分。混合仿真的性能瓶颈往往不在数字侧,而在跨域接口的同步频率与模拟求解器的步长控制。合理设置数字事件密度与模拟步长上限,是协同仿真调优的核心参数之一。