开源 vs 商业 Verilog 仿真器对比

对比概述

特性 Verilator Icarus Verilog ModelSim DE Vivado xsim
许可证 开源 (LGPL) 开源 (GPL) 商业 Vivado 捆绑
语言支持 可综合 Verilog/SystemVerilog Verilog-2005 + 有限 SV 完整 VHDL + Verilog + SV 完整 VHDL + Verilog + SV
输出形式 C++ 周期精确模型 VVP 中间形式 原生编译仿真 原生编译仿真
波形格式 VCD / FST (通过 --trace) VCD / FST / LXT WLF (专有格式) WDB (专有格式)
仿真速度 比 Icarus 快 10-50 倍 基准 比 Icarus 快 2-5 倍 比 Icarus 快 3-8 倍
编译速度 中等(含 C++ 编译步骤) 慢(需要大量 elaboration) 中等
SVA 断言 有限(仅基本立即断言) 不支持 完整并发 SVA 完整并发 SVA
覆盖率 无内置支持 完整功能 + 代码覆盖率 完整功能 + 代码覆盖率
验证 (UVM) 通过 Verilator+UVM 桥接 不支持 完整 UVM-1.2 完整 UVM-1.2
CI/CD 友好度 优秀 优秀 需要许可证服务器 需要许可证服务器
GUI 调试器 无(外接 GTKWave) 无(外接 GTKWave) 完整交互式调试器 Vivado 集成逻辑分析仪

基准测试:编译与仿真速度

测试对象为一个中型 RISC-V 核心(约 15K 行 Verilog,约 3K 个触发器),在 AMD Ryzen 5950X(16 核 32 线程)、64 GB 内存、Ubuntu 24.04 上进行。

编译(Elaboration)时间

工具 首次运行 缓存后 说明
Icarus 2.1s 2.1s 始终完整编译
Verilator 4.8s 0.3s 首次后利用 C++ 增量构建
Vivado xsim 12.3s 6.1s Elaboration + 优化
ModelSim 18.7s 9.2s vlog + vopt elaboration

仿真速度(100 万周期,Dhrystone 基准测试)

工具 实际耗时 相对速度 说明
Verilator 0.9s 1.0x(最快) C++ 编译模型,无事件调度开销
Vivado xsim 6.4s 慢 7.1 倍 事件驱动引擎
ModelSim 8.1s 慢 9.0 倍 事件驱动引擎
Icarus 18.2s 慢 20.2 倍 纯解释执行 VVP

波形文件大小(100 万周期,追踪 200 个信号)

工具 格式 文件大小 说明
Verilator FST 48 MB 块级压缩
Icarus FST 52 MB 同格式,略大
Verilator VCD 1.8 GB ASCII 格式——长时间仿真应避免使用
ModelSim WLF 95 MB 专有格式,查看器响应快
Vivado xsim WDB 110 MB 专有格式,与 Vivado GUI 绑定

SystemVerilog 特性支持矩阵

特性 Verilator Icarus ModelSim Vivado xsim
always_ff, always_comb 支持 部分支持 支持 支持
接口 (interface/modport) 支持 不支持 支持 支持
包 (package/import) 支持 不支持 支持 支持
枚举类型 (enum) 支持 不支持 支持 支持
结构体 (struct/typedef) 支持 不支持 支持 支持
断言(立即断言) 支持 不支持 支持 支持
断言(并发 SVA) 有限支持 不支持 支持 支持
覆盖率 (covergroup) 不支持 不支持 支持 支持
约束 (rand/constraint) 不支持 不支持 支持 支持
类 (OOP) 不支持 不支持 支持 支持
UVM 通过桥接 不支持 支持 支持
generate / genvar 支持 支持 支持 支持
多维数组 支持 部分支持 支持 支持
$clog2, $bits 支持 支持 支持 支持
DPI-C (import "DPI-C") 支持 部分支持 支持 支持
force / release 支持 支持 支持 支持

开源工具在 CI/CD 中的集成

Verilator 在 CI 中的使用

Verilator 的 lint 模式是代码质量的第一道防线。它能零仿真成本地捕获综合不匹配、位宽截断和组合逻辑环路等问题。


# .github/workflows/verilog-lint.yml
name: Verilator Lint

on: [push, pull_request]

jobs:
lint:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: 安装 Verilator
run: sudo apt install -y verilator
- name: 运行 Lint 检查
run: |
verilator --lint-only -Wall -Wno-DECLFILENAME \
-I rtl/ -I ip_common/rtl/ \
-f rtl/filelist.f \
--top-module top

Icarus Verilog 在 CI 中的使用

Icarus 非常适合 CI 中的回归测试,因为它启动快,且能完美兼容标准 Verilog-2001/2005。


# .github/workflows/regression.yml
name: Icarus 回归测试

on: [push, pull_request]

jobs:
regression:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: 安装工具
run: sudo apt install -y iverilog
- name: 运行回归测试
run: |
for tb in sim/tb_*.v; do
module=$(basename "$tb" .v)
echo "运行 $module..."
iverilog -g2012 -I rtl/ -I ip_common/rtl/ -o sim/$module.vvp $tb
vvp sim/$module.vvp | tee sim/${module}.log
if grep -q "FAIL" sim/${module}.log; then
echo "失败: $module"
exit 1
fi
done
echo "所有测试通过"

自检 Testbench 模式

要让任何 CI 流程正常工作,Testbench 必须具备自检能力。以下是一个良好的模式:


// sim/tb_alu.v
module tb_alu;
    reg clk = 0;
    always #5 clk = ~clk;

// DUT 实例化
reg [31:0] a, b;
reg [3:0] op;
wire [31:0] result;
alu dut (.clk(clk), .a(a), .b(b), .op(op), .result(result));

integer pass = 0, fail = 0;

task check(input [31:0] expected, input [255:0] msg);
if (result !== expected) begin
$display("失败: %s | 得到 %h, 期望 %h", msg, result, expected);
fail = fail + 1;
end else begin
$display("通过: %s", msg);
pass = pass + 1;
end
endtask

initial begin
$dumpfile("tb_alu.fst");
$dumpvars(0, tb_alu);

// 加法测试
a = 32'd10; b = 32'd20; op = 4'd0; #10;
check(32'd30, "加法 10+20");

// 减法测试
a = 32'd100; b = 32'd30; op = 4'd1; #10;
check(32'd70, "减法 100-30");

// 最终报告
$display("=== 汇总: %0d 通过, %0d 失败 ===", pass, fail);
if (fail > 0) $fatal(1, "回归测试失败");
$finish;
end
endmodule

ModelSim 在 CI 中的使用(需许可证服务器)

ModelSim 在 CI 中使用需要网络可达的许可证服务器。使用 vsim -c 进入批处理模式并捕获退出码。


#!/bin/bash
# ci_modelsim.sh — Jenkins/GitHub Actions Runner 上的 ModelSim 回归测试

export MGLS_LICENSE_FILE="[email protected]:[email protected]"

# 编译所有源文件
vlib work
vlog +acc +cover -work work -f rtl/filelist.f
vlog +acc +cover -work work sim/tb_top.sv

# 运行仿真并收集覆盖率
vsim -c -coverage -do "coverage save -onexit cov.ucdb; run -all; quit" work.tb_top

# 检查结果
if [ $? -ne 0 ]; then
echo "ModelSim 仿真失败"
exit 1
fi

# 生成覆盖率报告
vcover report -html cov.ucdb -output coverage_report/
echo "覆盖率报告: coverage_report/index.html"

选型决策框架


                     ┌─────────────────────────────┐
                     │ 是否需要代码覆盖率           │
                     │ 或功能覆盖率?               │
                     └──────────────┬──────────────┘
                            是 │          │ 否
                     ┌──────────┘         └───────────┐
                     ▼                               ▼
              使用 ModelSim                   ┌──────────────────────┐
              或 Vivado xsim                  │ 是否使用 SystemVerilog│
                                              │ 接口/结构体/包/SVA? │
                                              └──────────┬───────────┘
                                                    是 │     │ 否
                                              ┌──────────┘     └──────────┐
                                              ▼                           ▼
                                       ┌──────────────┐           ┌──────────────┐
                                       │ Verilator 或 │           │ 需要最快仿真  │
                                       │ ModelSim     │           │ 速度?        │
                                       └──────────────┘           └──────┬───────┘
                                               │                  是 │    │ 否
                                               ▼                       ▼     ▼
                                       这是 CI Lint 步骤           Verilator  Icarus
                                       (不需要波形)?
                                           │        │
                                       是 │        │ 否
                                           ▼        ▼
                                       Verilator  ModelSim
                                       --lint     (含波形+调试)

快速选型规则

波形查看器质量对比

特性 GTKWave ModelSim Wave Vivado Wave
信号搜索/过滤 基础正则 高级 + 层次结构 层次树
模拟波形视图 支持 支持 支持
总线基数(十六进制/二进制/十进制/ASCII) 全部 全部 全部
时间光标 + 差值测量 支持 支持 支持
信号比较(差异) 不支持 支持 不支持
数据流(驱动源追踪) 不支持 支持 不支持
存储器内容查看器 有限 完整 完整
Tcl 脚本化 通过 Tcl 命令 完整 Tcl API 完整 Tcl API
远程查看 FST 文件可移植 需转换 WLF 需转换 WDB

总结建议

对于一个既做 FPGA 又做 ASIC 工作的团队,理想的工具配置是:

这样既能享受开源工具在 CI 中的速度优势,又能在需要时获得商业工具的调试能力,无需为每台 CI Runner 都购买额外的商业许可证。