数字与模拟电路的联合仿真:Icarus Verilog 与 NGSpice 桥接的两种方案
现代电子系统需要集成数字和模拟组件,这使得混合信号仿真变得至关重要。为了应对这一挑战,我们通过开发两种架构,在 Icarus Verilog 和 NGSpice 之间实现了桥接。每种架构都有其基本局限性,但它们已经能够解决从 SAR ADC 到 sigma-delta 调制器等实际任务。
混合信号仿真的基础:事件 vs. 连续性
数字电路使用事件建模:仿真器仅在信号变化时激活(时钟边沿、触发器翻转)。Icarus Verilog 和其他数字仿真器就是这样工作的——系统在事件之间“休眠”,从而确保高性能。模拟电路则需要连续建模:SPICE 引擎(NGSpice、Spectre)将时间分解成小步长,在每个区间求解微分方程。这种方法准确但资源消耗大,尤其在有尖锐边沿或反馈回路时。
联合仿真的关键挑战在于调和这些根本不同的范式。数字仿真器处理离散事件,而模拟仿真器需要平滑的时间流。当结合 SAR ADC(模拟比较器与数字逻辑交互)时,会出现困境:如何在引擎间传递数据而不丢失关键事件?
桥接架构:共同原则
两种实现都使用相同核心技术:
- VPI (Verilog Procedural Interface) 用于与 Icarus 交互
- 动态库 libngspice.so
- 使用信号量的流式机制
- 独立的 NGSpice 执行线程
核心元素是系统任务 $spice_sync(),在时钟信号边沿调用。它执行完整交换周期:通过 alter 命令将数字值传递给 SPICE,查询模拟电压,并更新 Verilog 中的实数变量。这允许在 GTKWave 中将模拟信号与数字信号显示在同一时间轴上。
always @(posedge clk_fast) begin
$spice_sync();
if (tb.Vcmp > vref_th) begin
// Reaction to event
...
end
end
expose_analog_N 机制自动同步模拟变量,使其可供数字逻辑访问。桥接两侧的包装对象处理边沿和延迟。
经典方案:同步轮询
在此实现中,Verilog 在每次 $spice_sync() 调用时发起交换。仿真器记录当前时间,在信号量上阻塞,将控制权交给 NGSpice,后者仿真到该时间点并返回数据。
优势:
- 完全确定性
- 可预测性能
- 实现简单(约 2000 行代码)
关键局限性:
- 时钟边沿之间模拟事件完全不可见。例如,如果比较器在 5.2 ns 切换,而下一个时钟在 10.0 ns,数字逻辑将延迟 4.8 ns 才检测到变化,这使得 SAR ADC 或 DC-DC 转换器中的反馈回路不可能实现。
- 强制过采样:要捕获快速事件,需要人为提高时钟频率(例如到 500 MHz),这会损害性能。
此方案仅适用于模拟事件与时钟边沿对齐,或使用高频时钟同步的任务。
替代方案:前瞻分析
为了克服经典方法的局限性,我们实现了前瞻机制。NGSpice 获得许可“提前运行”固定间隔,通过可配置传感器跟踪模拟事件。mixed_bridge.cfg 中的示例规则:
analog_event_0 = threshold outp rising 1.2 | time_var=tb.analog_event_time id_var=tb.analog_event_id
当条件触发时,SPICE 暂停并通过 cbAfterDelay 回调在 Verilog 中发起事件。
优势:
- 能够检测异步模拟事件
- 可配置灵活性(阈值、持续时间、能量条件)
- 低频时钟下负载降低
根本缺陷:
- 由于离散时间积分,SPICE 步长之间的事件可能被遗漏
- 因果性违反:
alter命令(数字信号变化)仅在下一仿真阶段应用,这对 DAC 至关重要 - 每个分析窗口限一个事件
- 选择前瞻间隔长度的启发式导致非确定性
- 实现复杂(3500+ 行代码 + 配置解析器)
关键差异对比
两种架构的主要权衡体现在五个方面:
- 事件检测: 经典方法完全遗漏时钟间事件,替代方案部分捕获但有遗漏风险
- 因果性: 经典方案中 DAC→模拟链接正确;替代方案中可能存在时序不匹配
- 性能: 同步方法提供稳定速度;前瞻在短间隔时可能急剧变慢
- 确定性: 仅经典实现保证可重现结果
- 集成复杂性: 替代方案需要微调启发式并分析电路时序
主要结论
- 没有完美方案: 由于建模范式的根本差异,两种架构都有固有局限性
- 选择取决于任务: 替代方案适合脉冲稀疏的 sigma-delta 调制器;经典方案加过采样适合时序严格的 SAR ADC
- 实际适用性: 该工具已用于验证模拟环境中的数字逻辑和脉冲计数
- 可视化: 两者均支持在 GTKWave 和 gnuplot 中统一时间轴显示组合信号
- 展望: 集成事件队列并使用
cbNextSimTime可缓解局限性
实际实现与使用示例
考虑将桥接用于 sigma-delta 调制器。模拟部分生成短脉冲,数字计数器必须统计它们。在经典方案中,只需以超过脉冲持续时间的频率调用 $spice_sync()。示例 Verilog 代码:
module DSMCounter(
input i_clk,
input i_rst,
input i_Qbar,
output reg[31:0] o_cntQbar,
output reg o_ready
);
parameter CNT_CLK = 22;
reg [31:0] cnt;
reg [31:0] cntQbar;
always @(posedge i_clk) begin
if(i_rst) begin
cnt <= 0;
cntQbar <= 0;
o_cntQbar <= 0;
o_ready <= 0;
end else begin
o_ready <= 0;
if(i_Qbar == 1) begin
cntQbar <= cntQbar + 1;
end
if(cnt == CNT_CLK-1) begin
o_cntQbar <= cntQbar;
o_ready <= 1;
cnt <= 0;
cntQbar <= 0;
end else begin
cnt <= cnt + 1;
end
end
end
endmodule
在替代实现中,可以使用 analog_event 的脉冲检测规则降低同步频率。但这需要仔细调整前瞻参数以避免遗漏。
运行时,需要共享 NGSpice 构建(--with-ngshared)。桥接配置通过 mixed_bridge.cfg 设置,定义同步点和事件检测规则。两种实现均为开源,但需针对具体任务测试。
未来方向包括实现事件队列而非单一标志,将 maxstep 集成到桥接配置中,并使用 cbNextSimTime 实现精确时间控制。完整方案需要为 NGSpice 添加事件 API。
— Editorial Team
暂无评论。