一、故障仿真概述:故障仿真的定义、目的与在芯片验证流程中的位置

1.1 什么是故障仿真?

故障仿真,说白了就是「故意搞破坏」。

我们往设计里注入各种故障——比如某个寄存器 stuck-at-0 了、某条信号线短路了、某个存储单元坏了——然后跑仿真,看看芯片会怎么反应。我个人习惯把它叫做「芯片的体检」,而且是压力测试那种。

你想想看,一颗芯片流片回来,要是某个晶体管坏了,系统能不能自己发现?能不能安全降级?会不会直接死机?这些问题,都得靠故障仿真来回答。

故障仿真的核心定义:通过人为注入故障模型,模拟芯片在实际使用中可能出现的物理缺陷,验证芯片的故障检测能力和容错机制是否有效。

1.2 我们为什么要做故障仿真?

这个问题我问过不少刚入行的工程师。有人说是为了满足车规要求,有人说是为了做测试覆盖率。都对,但不够全面。

我个人总结下来,故障仿真有三大目的:

  1. 验证故障检测机制——芯片里那些 BIST(内建自测试)、ECC(纠错码)、奇偶校验,到底能不能抓到故障?我在一个项目里遇到过,ECC 逻辑设计有 bug,单比特翻转能纠正,双比特翻转却直接静默了……要不是做了故障仿真,这颗芯片流片回来就是个大坑。
  2. 评估测试覆盖率——你的测试向量到底能测出多少故障?90% 还是 99%?这个数字直接决定了芯片的出厂质量。
  3. 验证安全机制——ISO 26262、DO-254 这些标准,都要求你证明芯片在故障情况下能安全运行。故障仿真就是最直接的证据。

我的经验:故障仿真不是「做一次就完事」的。我建议在项目早期就开始搭建故障仿真环境,哪怕只是跑几个简单的故障模型。等到 RTL 冻结了再开始做,你会发现很多问题已经来不及改了。

1.3 故障仿真在芯片验证流程中的位置

这个问题很重要。很多团队把故障仿真放在最后,当成「交差」的环节。其实不对。

我们来看看典型的芯片验证流程:

需求分析 架构设计 RTL 实现 功能验证 故障仿真 (本课程核心) 综合与 DFT 时序分析 物理设计 流片 反馈迭代 本课程重点 标准验证流程 反馈迭代路径

看到了吗?故障仿真不是孤立的。它和功能验证、DFT(可测试性设计)、甚至物理设计都有关系。

我一般把它放在功能验证之后、综合之前。为什么?因为功能验证跑通了,说明设计逻辑是对的。这时候注入故障,才能区分「设计 bug」和「物理缺陷」。如果你功能验证都没跑通就做故障仿真,那结果根本没法看——到处都是故障,你分不清是设计问题还是真的缺陷。

注意:千万不要把故障仿真拖到流片前才做。我曾经在一个项目中吃过这个亏——故障仿真发现安全机制有漏洞,但 RTL 已经冻结了,只能做 ECO(工程变更单),多花了三周时间。如果早点做,这些完全可以在正常设计周期内解决。

1.4 故障模型:我们到底在模拟什么?

故障仿真不是乱来的。我们有标准的故障模型,每个模型对应一种物理缺陷。

故障模型 物理对应 常见场景
Stuck-at-0/1 信号线短路到电源或地 金属桥接、晶体管击穿
Transition Delay 信号翻转速度变慢 工艺偏差、老化
Bridging Fault 两条信号线短路 金属毛刺、颗粒污染
Open Fault 信号线断路 通孔失效、电迁移
Single Event Upset 存储单元翻转 宇宙射线、α粒子

嗯,这里要注意:实际项目中,我们不会对所有模型都做仿真。成本太高了。我一般会根据芯片的应用场景来选择——车规芯片重点做 stuck-at 和 SEU,消费类芯片可能只做 stuck-at。

1.5 一个简单的故障仿真示例

光说不练假把式。我们来看一个最简单的例子——对一个 2 输入与门做 stuck-at 故障仿真。

// 原始设计:一个简单的与门
module and_gate (
    input  a, b,
    output y
);
    assign y = a & b;
endmodule

// 故障注入:将输入 a 固定在 0
module and_gate_faulty (
    input  a, b,
    output y
);
    // 注入 stuck-at-0 故障到 a
    wire a_faulty = 1'b0;  // 故障注入点
    assign y = a_faulty & b;
endmodule

跑仿真看看:

// 正常情况
a=0, b=0 → y=0
a=0, b=1 → y=0
a=1, b=0 → y=0
a=1, b=1 → y=1

// 故障情况(a stuck-at-0)
a=0, b=0 → y=0
a=0, b=1 → y=0
a=1, b=0 → y=0
a=1, b=1 → y=0  // 这里出错了!应该输出1

看到了吗?当 a 被固定在 0 时,无论 b 是什么,输出永远是 0。这个故障只有在 a=1, b=1 时才能被检测到。所以,你的测试向量必须包含这个组合,否则故障就「逃逸」了。

我的建议:写测试向量时,别只盯着功能覆盖率。想想看——你的向量能不能把每个节点的 stuck-at 故障都「激活」并「传播」到输出?这才是故障仿真的核心思想。

1.6 故障覆盖率:一个必须懂的指标

故障仿真做完了,你怎么知道做得好不好?看故障覆盖率。

公式很简单:

故障覆盖率 = (检测到的故障数 / 总故障数) × 100%

但实际没那么简单。我见过不少团队,故障覆盖率做到 99% 了,流片回来还是有质量问题。为什么?因为故障模型不够全,或者故障列表本身就有问题。

举个例子:你只注入了 stuck-at 故障,但芯片实际失效是因为时序问题。那你的故障覆盖率再高也没用。所以,故障模型的选择和故障列表的构建,比跑仿真本身更重要。

行业经验:对于车规级芯片(ASIL-D),故障覆盖率通常要求 >99%。消费类芯片一般在 95% 以上。但记住,这只是数字。真正重要的是——你覆盖了哪些故障?漏掉了哪些?

1.7 小结

故障仿真不是什么高深莫测的技术。说白了,就是「先搞破坏,再检查修复能力」。它在芯片验证流程中处于承上启下的位置——上接功能验证,下连 DFT 和物理设计。

我个人觉得,做故障仿真最重要的不是工具怎么用,而是思维方式的转变。你得从「设计能不能正常工作」切换到「设计坏了能不能被检测到」。这两种视角完全不同,但缺一不可。

嗯,这一章就到这里。记住:故障仿真不是交差用的,它是真正能帮你发现芯片「隐藏缺陷」的手段。


专注资料整理