Verilog 验证平台全景概览
阶段 | 目标 | 典型产出 |
---|---|---|
需求分析 | 明确设计规格、接口时序、覆盖需求 | 验证计划 (Test Plan) |
环境架构 | 设计分层 TB、编写 BFM/Monitor/Scoreboard | TB 框架代码 |
用例开发 | Directed & 随机用例、断言、覆盖模型 | Testcase/Assertion/Coverage |
回归执行 | 脚本化仿真 & 波形收集 | Regression Report |
结果分析 | 覆盖率闭环、Bug 修复 | Coverage Report |
核心理念:自检式、覆盖驱动、可重用 —— 让测试自动告诉你“对/错”和“覆盖度是否充分”。
1 基础 Testbench(纯 Verilog)
`timescale 1ns/1ps
module tb_top;
// 1. 接口信号
reg clk, rst_n;
reg [7:0] din;
wire [7:0] dout;
wire valid;
// 2. 实例化 DUT
my_dut u_dut (
.clk (clk),
.rst_n (rst_n),
.din (din),
.dout (dout),
.valid (valid)
);
// 3. 时钟 & 复位
initial clk = 0;
always #5 clk = ~clk; // 100 MHz
initial begin
rst_n = 0; repeat(10) @(posedge clk);
rst_n = 1;
end
// 4. 激励
initial begin
wait(rst_n);
repeat(100) begin
@(posedge clk);
din = $random;
end
end
// 5. 自检
always @(posedge clk) begin
if (valid && dout !== golden(din))
$error("Mismatch: din=%h dout=%h", din, dout);
end
// 6. 结束条件
initial begin
#20000; $display("TB finished"); $finish;
end
// 7. 参考模型
function [7:0] golden(input [7:0] x);
golden = {x[3:0], x[7:4]}; // 示例 RTL 等价行为
end
endmodule
要点
- DUT 例化:信号命名与方向一致,杜绝悬空。
- 时钟/复位:
always #T/2 clk=~clk
+ 可编程复位长度。 - 激励:从简单 → 复杂;可使用
initial begin
、任务(task
)或文件 I/O。 - 参考模型:写在 TB 内或调用 C/Python 模型确保 可对比。
- 自检输出:
$error/$fatal
让仿真 立即失败;$display
仅记录日志。 - 仿真结束:
$finish
或检测覆盖率 100 % 后自动退出。
2 任务、函数与文件 I/O
- 任务
task
:可含延时,常用于突发总线事务 (task axi_write(addr, data);
) - 函数
function
:组合逻辑 / 黄金模型,无时间控制。 - 文本/二进制文件:
$fread/$fwrite
、$readmemh
用于大规模激励 (图像帧、波形)。
3 分层验证平台架构
tb_top
├── clk_gen / rst_gen
├── cfg_if // 配置接口 BFM
├── data_in_bfm // 产生输入流
├── monitor // 采集 DUT 输出
├── scoreboard // 参考模型 + 自动比对
├── coverage // 功能覆盖点
└── testcase.sv // 调度场景
- BFM (Bus Functional Model):把信号级握手机制封装成 任务接口,调用者无需关心时序细节。
- Monitor:被动窥探总线,送入 Scoreboard + 覆盖模型。
- Scoreboard:融合黄金/算法模型,负责结果对比 & 错误定位。
- 环境可配置:仿真参数通过
+define+SEED=xx
或 YAML/JSON 传入,方便批量回归。
4 随机化与覆盖驱动(SystemVerilog 重点)
如果纯 Verilog 无法满足大规模随机验证,SystemVerilog + UVM 是工业事实标准。
4.1 随机化
class pkt;
rand bit [7:0] id;
rand bit [31:0] payload[];
constraint c_id { id inside {[1:255]}; }
endclass
- 使用
randomize()
产生不同 ID / 长度 / 内容。 - 约束 (constraint) 确保合法边界;同时可写 非法约束 测试异常路径。
4.2 覆盖率
covergroup cg @(posedge clk);
coverpoint id { bins all[] = {[0:255]}; }
coverpoint length = payload.size();
endgroup
- 测试结束收集
cg.get_coverage()
, 逼近 ≥ 90 % → 认为功能覆盖充分。 - 代码覆盖(line/branch/fgm)同等重要,由仿真器生成报告。
5 Assertion-Based Verification (ABV)
// 同步断言:请求后两拍内必须有响应
ap_req_rsp: assert property (@(posedge clk) disable iff(!rst_n)
req |-> ##[1:2] (grant && !err))
else $fatal("Protocol violation");
- 即时暴露 协议/时序错误,定位精确到周期。
- 推荐分类:协议、时序、覆盖 断言。
- 可在 RTL 与 TB 中双重加入,早期预防 Bug。
6 UVM 方法学(快速掠过)
组件 | 作用 |
---|---|
uvm_env |
顶层容器,挂载 agent/scoreboard |
uvm_agent |
BFM (driver) + monitor + sequencer |
uvm_sequence |
事务流脚本,抽象“场景” |
uvm_config_db |
参数下发通道 |
uvm_report_* |
统一日志、错误等级管理 |
优势:分层封装 → 可重用;自动化报表;丰富的 Factory/Callbacks → 易扩展。
门槛:学习曲线陡峭,小型项目可用 “轻量 UVM” 或 cocotb 替代。
7 Python/cocotb 协同
- cocotb:Python 协程驱动仿真器 (VCS/ Questa/ Verilator),写测试 像写脚本。
- 生态充裕:
numpy/scipy
处理图像、scikit-image
生成黄金数据;与 CI/CD 易融合。 - C-语言 DPI / FLI 亦可混合,加速高级算法对比。
8 脚本化回归
# run.py
for seed in {1..1000}; do
vsim -c +UVM_TEST=my_case +SEED=$seed -do "run -all; quit" \
| tee log_$seed.txt
done
# 解析日志收敛覆盖
./cov_merge.sh
- Makefile / Python 调度多核并行仿真。
- 日志自动归档;失败用例收集波形 (
$dumpfsdb
) 便于调试。
9 常见陷阱 & 最佳实践
问题 | 建议 |
---|---|
激励与黄金模型不一致 | 单一事实来源:统一参考模型 + Scoreboard |
TB 时钟抖动导致假失败 | 所有 BFM 用同一 clk 驱动,必要时加入 ##0 同步 |
随机化用例不可重复 | 记录 SEED ;必要时锁定约束子集 |
长仿真慢 | 波形分层($dumpvars(1,u_dut) )、使用 +acc= 精选信号 |
覆盖挂死 | 交叉点过多 → 分级收敛;删除不必要 cross |
结语
- 从 纯 Verilog 自检 TB 开始 → 引入 分层结构 & 参考模型 → 过渡到 随机化 + 覆盖 → 最终掌握 UVM / cocotb 高阶验证。
- 始终紧扣三条红线:发现 Bug、证明无 Bug、量化验证完备性。