4. 验证阶段根因:验证计划遗漏、仿真环境错误、覆盖率不足
验证阶段出问题,说实话是最让人头疼的。为什么?因为设计代码已经写完了,你满心以为可以 tapeout 了,结果验证告诉你——还有坑。而且这些坑往往藏得很深,流片回来才暴露。
我个人习惯把验证阶段的根因分成三类:计划没想全、环境搭错了、覆盖没到位。咱们一个一个聊。
4.1 验证计划遗漏:corner case 没覆盖
什么叫 corner case?就是那些「正常情况不会出现,但一旦出现就崩了」的场景。比如 FIFO 满的时候还在写、跨时钟域采到亚稳态、复位释放瞬间的毛刺……
我在项目中遇到过最典型的一个例子:一个 SPI 接口的从机,验证只测了标准模式(CPOL=0, CPHA=0),结果客户用模式3(CPOL=1, CPHA=1)去配,数据全错。流片回来才发现,改版又花了两周。
为什么会遗漏?说白了,验证计划写得太「理想化」了。大家只盯着功能列表,没去思考边界。
- 接口协议的所有模式(SPI、I2C、UART 的每种配置)
- FIFO 空/满/半满/溢出
- 复位释放时序(异步复位同步释放的窗口)
- 时钟门控使能/关闭瞬间
- 低功耗模式切换(唤醒、睡眠、保持)
4.2 仿真环境错误:testbench bug 与激励错误
这个坑更隐蔽。你以为是 DUT 的 bug,结果查了半天,是 testbench 写错了。我见过最离谱的一次:验证工程师把时钟周期配成了 20ns,但实际设计跑的是 10ns,所有时序仿真都通过了——因为仿真环境里根本测不到 setup time 违例。
testbench 的 bug 通常分两类:
- 激励错误:比如给错了配置寄存器、发错了命令序列、数据宽度不匹配
- 监测错误:比如 scoreboard 比较逻辑写反了、断言条件写错了
嗯,这里要注意:仿真环境本身也是「代码」,它一样需要 review 和验证。我建议把 testbench 当成 RTL 代码一样对待——做代码检查、做 lint、做覆盖率分析。
4.3 覆盖率不足:代码、功能、断言
覆盖率这东西,很多人觉得是「交差用的」。其实不然。覆盖率是你验证工作的体检报告。
我把它分成三层:
| 覆盖率类型 | 检查什么 | 常见遗漏 |
|---|---|---|
| 代码覆盖率 | RTL 代码的每一行、每个分支、每个状态是否被执行 | default 分支、else 分支、casex 的未匹配项 |
| 功能覆盖率 | 设计规格中定义的功能点是否被覆盖 | 跨时钟域场景、异常中断、错误恢复路径 |
| 断言覆盖率 | 你写的断言(assertion)是否被触发过 | 断言写了但从来没被激活过,等于没写 |
举个例子:代码覆盖率 100% 不代表功能没问题。你想想看,一个状态机所有状态都跑到了,但状态跳转的时序错了——代码覆盖率看不出来。这时候就需要功能覆盖率和断言来补位。
下面这张图是我自己总结的验证阶段根因分析框架,帮你快速定位问题出在哪一层:
验证阶段的问题,说白了就是「你以为你测全了,其实没有」。我见过太多团队在 tapeout 前一周疯狂补 case,结果越补越慌。为什么?因为前期计划没做细,环境没搭稳,覆盖率没盯紧。
嗯,这一章的内容就到这里。记住:验证不是走流程,是给芯片上保险。每一行 testbench 代码、每一个断言、每一个覆盖率点,都可能是救你一次流片的关键。
公众号:蓝海资料掘金营,微信deep3321