第三章:验证计划——如何制定一份可执行的VPlan
说实话,我刚入行那会儿,觉得验证计划就是走个过场。
项目经理催着要,我就随便列几个测试用例,写个覆盖率目标,交差了事。结果呢?项目后期天天加班,不是漏场景就是测不全,最后还得靠老员工救火。
后来我才明白——一份好的VPlan,是整个验证工程的蓝图。它不光是文档,更是你和设计、架构、后端沟通的桥梁。
3.1 验证计划到底长什么样?
我习惯把VPlan分成三个层次:
- 策略层:回答“测什么、怎么测、测到什么程度”
- 执行层:列出具体的测试用例、检查点、覆盖率目标
- 管理层:时间节点、资源分配、风险预案
你想想看,如果连测什么都不清楚,那后面写testbench、跑仿真,不就成了无头苍蝇?
核心原则:VPlan不是写给别人看的,是写给自己和团队用的。它必须可执行、可追踪、可度量。
3.2 第一步:吃透设计规格
我见过太多人,拿到设计文档扫两眼就开始写计划。结果呢?漏掉关键功能,或者理解错了协议。
我个人习惯,先花一天时间通读设计规格,然后做三件事:
- 画功能框图:把模块的输入输出、内部状态机、数据通路画出来
- 列接口清单:所有协议接口、配置寄存器、中断信号
- 找边界条件:FIFO满空、超时处理、异常复位、跨时钟域
举个例子,我之前做DMA控制器验证。设计文档说“支持链式描述符”,但没提描述符指针为NULL时怎么办。我追问了架构师,才发现这是个未定义行为——最后我们决定在验证计划里加一个“空指针异常处理”的测试用例。
小技巧:把设计文档里的“Note”、“Remark”、“Assumption”全部标红。这些地方往往是坑。
3.3 第二步:分解功能点
功能点分解,说白了就是把“这个模块要干啥”拆成“每个场景怎么测”。
我常用的方法是功能覆盖组(Functional Coverage Group)的思路:
| 功能点ID | 功能描述 | 验证方法 | 优先级 |
|---|---|---|---|
| F1 | 正常写操作:地址对齐、数据宽度匹配 | 定向测试 + 随机测试 | P0 |
| F2 | 写操作地址未对齐 | 错误注入测试 | P1 |
| F3 | 写操作时总线超时 | 时序反压测试 | P1 |
| F4 | 写操作与读操作重叠 | 并发场景测试 | P0 |
嗯,这里要注意:优先级P0是必须测的,P1是尽量测,P2是时间允许再测。别一上来就想覆盖所有,那不现实。
3.4 第三步:设计测试用例
有了功能点,接下来就是写具体的测试用例。我建议每个功能点至少对应一个定向测试和一个随机测试。
定向测试用来验证基本功能,随机测试用来踩边界和组合场景。
// 定向测试示例:验证写操作地址对齐
task test_write_aligned();
logic [31:0] addr = 32'h1000;
logic [31:0] data = 32'hA5A5A5A5;
// 发起一次32位对齐写
bus_write(addr, data, 4'b1111);
// 检查写响应
wait(bus_resp == OK);
// 读回验证
bus_read(addr, 4'b1111);
assert(bus_rdata == data);
endtask
// 随机测试示例:随机地址、随机数据、随机字节使能
task test_write_random();
repeat (1000) begin
rand_addr = $urandom_range(0, 32'hFFFF);
rand_data = $urandom;
rand_be = $urandom & 4'hF;
bus_write(rand_addr, rand_data, rand_be);
// 检查响应
...
end
endtask
我曾经踩过的坑:随机测试的种子没固定。结果回归时同一个用例每次跑的结果都不一样,根本没法复现bug。后来我强制每个随机用例都记录种子,并在日志里打印出来。
3.5 第四步:定义覆盖率目标
覆盖率不是越高越好,而是够用就好。
我一般这样定目标:
- 代码覆盖率:行覆盖≥90%,条件覆盖≥85%,状态机覆盖100%
- 功能覆盖率:所有P0功能点100%,P1功能点≥90%
- 断言覆盖率:所有协议断言100%触发过
为什么状态机要100%?因为状态机漏掉一个状态,很可能就是死锁或者跑飞。我在一个项目里就遇到过,状态机有个“IDLE→WAIT”的跳转从来没被触发过,结果芯片在特定条件下直接卡死。
3.6 第五步:制定时间线和里程碑
VPlan里必须包含时间规划。我习惯用倒推法:
- 先定死芯片tape-out日期
- 往前推验证冻结日期(一般提前2周)
- 再推回归测试完成日期
- 最后推测试用例开发完成日期
举个例子:
| 里程碑 | 时间 | 交付物 |
|---|---|---|
| VPlan评审 | 第1周 | 验证计划文档 |
| Testbench搭建 | 第2-3周 | 可运行的仿真环境 |
| 定向测试完成 | 第4-5周 | 所有P0用例通过 |
| 随机测试+回归 | 第6-8周 | 覆盖率达标 |
| 验证冻结 | 第9周 | 验证报告+覆盖率报告 |
我的习惯:每周五下午开30分钟验证站会,只看三件事——本周完成了什么、下周要做什么、有没有阻塞项。别搞成汇报大会,那没用。
3.7 第六步:风险识别与预案
做验证的都知道,计划永远赶不上变化。
我一般会在VPlan里专门列一个风险清单:
- 设计延迟:RTL交付晚了,验证时间被压缩 → 预案:先测核心功能,边缘功能后补
- 工具问题:仿真器bug或者license不够 → 预案:准备备用工具链,提前申请额外license
- 需求变更:架构师临时加功能 → 预案:评估影响范围,和项目经理协商延期或者砍需求
说白了,VPlan不是死文档。它要随着项目推进不断更新。我见过最离谱的项目,VPlan写完就没人管了,最后验证结束才发现覆盖率只有60%。
3.8 总结:一份好VPlan的检查清单
最后,我分享一个自检清单。每次写完VPlan,我都会过一遍:
- 所有功能点是否都覆盖到了?有没有遗漏的边界?
- 每个测试用例是否有明确的通过/失败标准?
- 覆盖率目标是否可量化、可追踪?
- 时间规划是否留了缓冲?
- 风险是否都识别了?预案是否可行?
嗯,做到这五点,你的VPlan基本就及格了。剩下的,就是在执行中不断迭代优化。
记住一句话:验证计划的质量,决定了验证项目的成败。别把它当成负担,它其实是帮你省时间的利器。
公众号:蓝海资料掘金营,微信deep3321