验证计划制定:验证目标定义、验证范围划分、功能点分解方法、验证矩阵的构建

各位同学,今天我们聊聊验证计划。说实话,很多工程师一上来就写代码、搭环境,结果做到一半发现方向偏了,回头再改,那叫一个痛苦。我早期带项目时就吃过这个亏——验证计划写得太粗,最后验证覆盖率惨不忍睹,不得不延期两周补case。从那以后,我养成了一个习惯:花30%的时间做计划,剩下70%的时间执行。你想想看,这其实是最省时间的做法。

一、验证目标定义:你到底要验证什么?

验证目标不是一句「我要验证这个IP功能正确」就完事了。我个人习惯把目标拆成三个层次:

  1. 功能正确性:所有spec里写的功能,一个都不能少。
  2. 边界健壮性:极端输入、异常场景下,IP不能挂、不能死锁。
  3. 性能达标:吞吐量、延迟、功耗等指标满足要求。

举个例子,我之前验证一个DMA控制器。功能目标很明确:支持链式传输、支持中断、支持地址对齐。但边界目标呢?如果传输长度是0怎么办?如果源地址和目的地址重叠怎么办?如果链表的最后一个节点指向了非法地址怎么办?这些才是真正容易出bug的地方。

重要提醒:验证目标一定要可量化、可衡量。不要写「验证性能良好」,要写「在128位数据宽度下,连续传输1024字节,吞吐量不低于8Gbps」。

二、验证范围划分:哪些该做,哪些不该做?

很多新人容易犯一个毛病:什么都想验证。结果验证计划越写越厚,最后根本做不完。我建议用「三圈法」来划分范围:

  • 内圈(必须验证):IP自身所有的功能点、接口协议、寄存器访问。
  • 中圈(选择性验证):与相邻模块的交互场景、典型系统集成场景。
  • 外圈(暂不验证):全芯片级场景、软件驱动层行为、多IP协同场景。

为什么会这样划分?因为IP验证阶段,你的目标是确保IP本身没问题。系统级的问题,那是下一阶段的事。我曾经见过一个团队,在IP验证阶段花了大量时间搭建全芯片仿真环境,结果IP内部的功能点反而没测透,最后流片回来发现一个很基础的寄存器读写bug——你说冤不冤?

我的经验:验证范围划分完成后,最好写一份「不验证清单」。把明确不做的内容列出来,和设计团队、系统团队对齐。这样能避免后期扯皮。

三、功能点分解方法:把大功能拆成小颗粒

功能点分解,说白了就是把spec里的每一句话,翻译成可验证的测试点。我常用的方法是「功能树」分解法

  1. 先列出顶层功能(比如:支持AXI4总线接口)
  2. 再拆子功能(比如:支持突发传输、支持乱序返回、支持窄传输)
  3. 继续拆到不可再分(比如:突发长度为1、2、4、8、16时,地址对齐与不对齐的组合)

嗯,这里要注意:拆到什么时候为止?我的标准是——一个功能点对应一个测试用例。如果一个测试用例能覆盖多个功能点,那就说明拆得还不够细。

给你看个实际例子。我验证过一个SPI控制器,它的「时钟极性配置」功能,我拆成了这样:

功能点ID 功能描述 测试场景
SPI_CLK_001 CPOL=0, CPHA=0 空闲时SCK为低,数据在上升沿采样
SPI_CLK_002 CPOL=0, CPHA=1 空闲时SCK为低,数据在下降沿采样
SPI_CLK_003 CPOL=1, CPHA=0 空闲时SCK为高,数据在下降沿采样
SPI_CLK_004 CPOL=1, CPHA=1 空闲时SCK为高,数据在上升沿采样
SPI_CLK_005 动态切换CPOL/CPHA 传输过程中修改配置,验证行为正确

你看,一个简单的时钟极性配置,拆出了5个功能点。每个功能点都可以直接对应一个测试用例。这样写出来的验证计划,设计工程师看了也没话说。

避坑指南:我曾经把一个功能点拆得太粗,结果测试用例跑完了,覆盖率报告显示那行代码根本没执行到。后来一查,是因为某个条件分支被遗漏了。所以,功能点分解一定要结合代码覆盖率来反推,看看有没有遗漏的分支。

四、验证矩阵的构建:把计划变成可执行的表格

验证矩阵,说白了就是一张「功能点 vs 测试用例」的映射表。它的作用有两个:一是确保每个功能点都有对应的测试用例,二是方便后期追踪验证进度。

我习惯用这样的格式:

功能点ID 功能描述 测试用例ID 测试用例名称 验证方法 状态
SPI_CLK_001 CPOL=0, CPHA=0 TC_SPI_CLK_001 时钟模式0基本传输 定向测试 PASS
SPI_CLK_002 CPOL=0, CPHA=1 TC_SPI_CLK_002 时钟模式1基本传输 定向测试 PASS
SPI_CLK_003 CPOL=1, CPHA=0 TC_SPI_CLK_003 时钟模式2基本传输 定向测试 FAIL
SPI_CLK_004 CPOL=1, CPHA=1 TC_SPI_CLK_004 时钟模式3基本传输 定向测试 PASS
SPI_CLK_005 动态切换CPOL/CPHA TC_SPI_CLK_005 传输中切换时钟模式 随机测试+断言 PASS

构建验证矩阵时,有几点经验分享给你:

  • 一个功能点可以对应多个测试用例:比如边界场景、异常场景、随机场景。
  • 一个测试用例可以覆盖多个功能点:比如一个随机测试,可能同时覆盖了时钟模式、数据长度、地址对齐等多个功能点。
  • 状态列要实时更新:PASS、FAIL、BLOCKED、NOT_RUN,每个状态都要有明确的定义。

我的小技巧:验证矩阵最好用Excel或者Google Sheets来维护,方便多人协作。我习惯在矩阵里再加一列「覆盖率贡献」,记录这个测试用例覆盖了哪些代码行、哪些分支。这样后期做覆盖率分析时,一眼就能看出哪些功能点还缺测试。

五、总结一下

验证计划制定,其实就是一个「从模糊到清晰」的过程。先定义目标,再划定范围,然后拆解功能点,最后构建验证矩阵。每一步都走扎实了,后面的验证执行才会顺畅。

我记得有一次,一个新人问我:「老师,验证计划写这么细,是不是太浪费时间了?」我反问他:「你愿意花一周时间写计划,还是愿意花一个月时间补bug?」他想了想,默默回去改计划了。

好了,这一章就到这里。下一章我们聊聊「验证环境搭建:从零开始搭建一个可复用的UVM验证平台」,到时候我会分享一些我在搭建环境时踩过的坑,保证让你少走弯路。