做DFT的工程师应该都体会过这种时刻:ATPG跑了一整天,打开覆盖率报告一看,卡在94.3%再也不动了。上头催着tapeout,质量部门咬着缺陷率不放,你盯着那台机器的RTL和网表,不知道还能从哪再榨出几个百分点的coverage。这个场景我在好几个项目里都经历过,coverage这东西看起来就是一个百分比,但背后牵扯的故障模型、约束设置、scan架构、ATPG策略,一层套一层,真要把数字往上推,靠的不是运气,而是对测试原理的深度理解和对工具流程的精准掌控。
这篇文章就把我做DFT这几年跟ATPG coverage死磕的经验整理出来,从coverage是怎么算出来的,到设计侧、ATPG策略侧、约束侧分别有哪些提升手段,再到覆盖率卡住时怎么定位瓶颈,全部串起来讲一遍。适合正在做DFT、想转DFT的芯片设计工程师,以及所有被coverage指标追着跑的人。
1. 覆盖率是什么,为什么它是DFT的命门
1.1 从缺陷到故障模型:coverage是怎么算出来的
要理解coverage,先得理解故障模型。芯片制造过程中,光刻、掺杂、金属线沉积,任何一个环节出了偏差,都可能造成物理缺陷。一个真实缺陷可能是金属线断了、可能是两个相邻节点短路了、可能是晶体管的阈值电压飘了。如果ATPG直接去枚举这些物理缺陷,数量会爆炸,而且没法在逻辑层面建模。
所以业界把物理缺陷抽象成逻辑故障模型。最常用的是单固定故障模型,也就是某个节点的信号永远被固定在高电平或低电平的故障,简写是SA1或者SA0。还有一个日常必用的是跳变故障模型,用来捕捉时序问题,激励一个节点从0到1或者从1到0的跳变,再看它能不能在指定的时序窗口内完成。每类故障模型对应着不同的物理缺陷类型,这也是为什么芯片测试通常要跑多套pattern、多套覆盖率。
coverage的计算公式其实特别朴素:
coverage = 检测到的故障数 / 总的可检测故障数但是这里有两个细节经常被忽略。第一,分母不是所有物理节点的所有可能故障,而是经过故障等价合并和故障折叠之后得到的故障列表。两个故障如果无法被任何测试向量区分,就被折叠成一个故障。第二,很多人没注意分子分母都排除了不可测故障,也就是那些因为设计本身冗余、或者因为约束设置导致根本无法激励或观测的故障。所以coverage这个百分比,反映的是ATPG工具在给定故障列表和约束条件下,用pattern把这些故障拉出来并传播到观测点的能力。
1.2 覆盖率高低直接决定流片后的质量指标
做DFT的人天天听质量部门报DPPM这个指标,也就是每百万颗芯片中的缺陷数。测试覆盖率跟DPPM是一个强相关的关系。简单说,coverage越高,漏到客户手里的缺陷芯片越少。很多设计公司对scan测试有硬性要求,stuck-at覆盖率不能低于98%,transition覆盖率不能低于90%,达不到的话质量审计那一关就过不去。
但coverage也不是越高越好,这句话说出来很多人不爱听。越往高处走,每提升0.1个百分点,消耗的pattern数量、测试时间和CPU运算时间都在指数级上升。一个block的stuck-at从99%推到99.5%,pattern数量可能直接翻倍,测试成本跟着涨。所以真正成熟的DFT工程师,不是追求coverage上限,而是追求在成本和时间约束下,coverage达到合理的目标值,并且能清楚地解释每一个覆盖不到的点是什么原因。这比闷头跑flow刷数字重要得多。
2. 提升成功率前,先搞懂ATPG的故障与约束机制
2.1 故障分类与等价折叠:别被coverage数字骗了
打开ATPG工具的报告,最核心的就是fault class分布。常见的有这么几类:detected代表测试向量确定能检测;undetected是分析后没有测试向量能覆盖;potentially detected是工具通过近似逻辑分析认为可能在某种条件下能被检测,但不完全确定;untestable里面又可以细分成多种原因。
这几个分类直接决定了你下一步该怎么发力。如果undetected的数量很多,说明要么测试向量生成不充分,要么设计本身有隐患。如果untestable占了大头,先别急着调ATPG参数,因为这类故障大概率是设计或者约束造成的,需要回到网表和SDC上去找原因。
fault equivalent类的折叠技术也要留意。举个例子,一个与门输入端接0,这个门的输出被固定为0,如果输出又接到后级的某个引脚,在逻辑上会形成一条故障传播的等价链。ATPG工具会把这条链上的若干故障合并成一个代表故障,从而减少故障总数和计算量。合理利用等价折叠,可以显著降低pattern数量和ATPG运行时间,但代价是单故障丢失细节。现代工具的故障折叠算法已经很成熟,一般不需要工程师手动干预,但理解这个原理有助于读懂coverage报告里的故障总数为什么不是物理节点数。
2.2 约束条件如何把coverage往下拽
ATPG工具的约束来源五花八门,但基本可以分三类。第一类是scan和test相关的约束,比如test mode信号、scan enable信号、时钟和复位在测试模式下的固定值,这些是ATPG flow必须设置的。第二类是设计逻辑本身的约束,比如一些异步信号需要保持稳定、某些寄存器在测试模式下不能翻转,这些通常由SDC或者专用的test constraint文件带进来。第三类是IO和模拟IP相关的约束,比如某些数字引脚驱动的是模拟模块的偏置电压,在测试时不能随便跳变,往往要约束到指定值。
真正把coverage拉下来的,往往不是第一类,而是第二类和第三类。我见过一个项目,coverage卡在92%怎么都上不去,查到最后是IO pad的上下拉配置在测试模式下全部被约束到了1,一排双向引脚全部只能输入,导致内部一大片逻辑失去了可控性。所以当你排查覆盖率瓶颈时,用工具把fault list导出来,按约束类型分类做pareto分析,哪个逻辑单元贡献的fault loss最多,就去查它周边的约束条件,这样比盲调参数高效得多。
2.3 ATPG的运转逻辑:为什么pattern能提高coverage
ATPG工具生成测试向量的过程,本质上是一个搜索过程。它先选一个目标故障,尝试在逻辑锥内反向推理,找出能激活这个故障的输入条件,也就是可控性分析;再找一条从故障点到观测点的路径,保证故障效应能传出去,也就是可观测性分析。如果这两个条件都能满足,工具就基于这个条件生成一个测试向量,然后用模拟器验证这个向量是否真的检测到了目标故障。
这个过程看起来直白,实际计算极其复杂。所以现代ATPG工具引入了各种剪枝策略、启发式算法和故障分组技巧。工具默认的策略通常是尽量用最少的pattern覆盖最多的故障,这就需要在生成向量时做动态压缩。当你发现coverage上不去,先看看pattern数量是不是太少。如果pattern数很少但覆盖率已经很高,大概率是工具在压缩上做得太激进,或者约束给得太死。如果pattern数很多但覆盖率还是低,那方向错了,加码跑更多pattern也白搭,得从设计侧找原因。
3. 设计侧入手:改架构和约束,比死啃工具参数更有效
3.1 scan chain设计和测试点插入的全局思路
coverage提升最立竿见影的,其实是设计侧的手段。scan chain本身的配置影响就很大。chain上是不是有长组合逻辑路径导致capture时序崩了、有没有跨时钟域的flop被错误串联、有没有memory和IP block造成的观测盲区,这些问题都能从ATPG报告里翻出来。
另一个常用手段是test point insertion,也就是测试点插入。原理很简单,芯片里总有一些逻辑,控制难度极高或者观测难度极高,导致大量故障测不到。测试点的作用就是在逻辑锥里人为引入一个可控或可观测的端口,一般是增加一个test_mode信号控制的缓冲器或者观测寄存器。插入测试点之后,原本测不到的故障变得可测,coverage立刻就上去了。
但测试点不是越多越好,每个测试点都会带来面积、时序和功耗的代价,而且插入位置不对还会引入新的时序风险。比较稳妥的做法是先用ATPG工具做一次coverage loss报告,定位到具体的失控逻辑区域,再结合网表分析在这个区域的关键节点布测试点。我之前在某个模块里插了八个测试点,transition coverage直接涨了四个百分点,效果很直观,但也花了两天时间反复仿真验证时序收敛。
3.2 从RTL阶段就开始留意coverage友好性
很多RTL工程师写代码的时候脑海里没有DFT这个概念,结果到综合阶段DFT工程师一看网表就头大。RTL里常见的coverage杀手有这几类:大片组合逻辑没有寄存器隔离,造成逻辑锥过大,可控性和可观测性都很差;跨时钟域的meta硬打没有做同步处理,ATPG约束为了防亚稳态只能把一大片逻辑全部map到不可控;异步复位逻辑直接接了异步信号,没有做复位同步器;还有各种门控时钟、多通道选择器,数据路径上的X态传播更是重灾区。
所以真正有效的coverage管理,是从RTL阶段就把DFT规则融入设计规范。比如规定所有寄存器的复位信号必须来自复位同步器,规定状态机进入测试模式后必须停留在已知状态,规定跨时钟域的数据在测试模式下要有明确的通路。这些看起来是设计规范问题,但每一条后面都牵动了ATPG的coverage。与其等到网表阶段拿一堆测试点往上堆面积,不如让RTL设计一开始就往coverage友好方向靠。
3.3 X态对coverage的隐性压制
X态对coverage的压制,是DFT工程师最容易忽略但又影响最深的问题。很多工程师以为X态只影响仿真的一致性,实际上在ATPG里,X态会直接阻碍故障的传播和观测。举个例子,一条逻辑路径上只要有一个由未初始化存储器、异步接口或者跨时钟域产生的X态信号,这条路径后面的故障就无法被观测到,ATPG工具会保守地把相关故障标为不可测或者潜在可测。
X态对transition coverage的杀伤力比对stuck-at更大。因为捕捉跳变关心的是时序窗口内信号能否跳转到正确值,X态不仅仅让值不确定,还会让跳变检查完全失效。某个模块如果因为RAM有未初始化区域导致大量X态传递到了输出路径上,transition覆盖率掉个十几个百分点都很正常。
处理X态的手段通常有三条路:在设计中增加X态压缩逻辑或者复位逻辑让信号在测试模式进入确定值;在ATPG约束阶段对某些X态源做定值处理;或者使用X态阻断技术,在关键路径上插入X态抑制逻辑。但无论哪条路,核心都是先定位X态从哪里产生、传播到哪里结束,再决定是在源头堵还是在传播路径上切断。
4. ATPG策略侧:约束、时钟和压缩参数,每一样都能挤出一个百分点
4.1 约束设计的具体操作和反面案例
ATPG约束文件是整个测试流程里最容易被低估的部分。很多人拿到RTL和SDC就直接开始跑ATPG,约束只是简单复制粘贴之前项目的,这是最典型的翻车现场。每个芯片的测试模式约束都应该单独写、单独review,因为约束一旦给错了,要么是ATPG直接报violation,要么是coverage莫名奇妙地变差。
一个很实际的案例,某次我接手一个项目的ATPG,发现一组复位信号在测试模式下被约束成了非复位状态,但实际测试机台上复位信号是由ATE的pattern控制的。这个错误约束导致所有涉及该复位域的寄存器在ATPG阶段被标记为不可初始化,stuck-at coverage直接少了三个点。找到问题后,把复位信号的约束改成由pattern控制,coverage立刻就恢复了。所以约束设计的核心原则是:测试模式的信号控制权,必须跟最终实际测试机台的控制方式保持一致。
还有一些约束设计细节值得注意。比如PLL和模拟IP在测试模式下的配置,通常需要约束为fixed值;双向IO的方向信号要约束到指定的buffer方向和输入使能;非扫描存储器比如RAM的读写控制信号也要给出明确的约束,避免在ATPG阶段产生X态。这些约束不能一股脑全写死,因为约束本身就是给coverage上的一道锁,锁太多了pattern施展不开,锁少了又会有时序和X态风险,平衡点只能靠对设计的清楚理解和反复迭代来找。
4.2 launch和capture时钟策略对transition coverage的影响
transition coverage的提升,很大一块要靠launch和capture时钟的正确设置。这里有两个疑问经常困住新人:一个是用快速时钟还是慢速时钟来捕获跳变,另一个是launch数据来自shift还是来自功能路径。
SCAN测试里shift阶段用slow shift clock把所有数据搬进scan chain,capture阶段通常要分为launch和capture两步。如果采用launch from shift的方式,也就是shift最后一拍直接作为跳变发起时钟,那么被测路径的起始点就是scan cell本身,这种方式的覆盖率通常更高,但要求时钟控制能精确到最后一拍。launch from capture则是通过功能路径上的组合逻辑发起跳变,更贴近真实功能时序,但覆盖率一般更低。
实际做下来,两种方式各有适用场景。对于高频模块建议用launch from capture来模拟真实功能路径压力,对于低速模块优先用launch from shift以提升覆盖。到了ATPG工具里,就是设置capture clock group、capture procedure、timing window这几个参数的事。很多人只知道把capture clock设置成和功能时钟同频,却忽略了launch和capture之间的约束关系,结果跑出来的transition pattern要么覆盖很低,要么在机台仿真的时候大量fail。这里面的坑只能用silicon debug的教训来填。
4.3 动态压缩、故障分组和pattern生成的实战参数
ATPG工具里的压缩选项,直接影响pattern数量和覆盖率之间的关系。动态压缩的原理是,在生成一个新的测试向量时,工具会反复尝试把它和之前已经生成的向量合并且补充覆盖新的故障,从而减少总pattern数。压缩等级调高,pattern数量显著下降,覆盖率可能会轻微下降。压缩等级调低,pattern变多,覆盖率提升空间大一些,但测试时间和成本跟着涨。
fatture group的用法也值得一提。现代ATPG工具支持把故障列表按逻辑层次或者模块划分成多个group,然后分别做ATPG。做group的好处是定位问题快,某个group覆盖率低了可以单独对这个group调参数,不用整个设计重跑。另一个实用技巧是增量ATPG,当设计的某个模块有改动时,只从旧的未覆盖故障列表出发重新生成pattern,而保留之前已生成的合格pattern,这样能大幅节约回归时间。
还有个参数容易被忽略,就是pattern的weight或者优先级。有些high coverage模式,比如gate exhaust模式,会让工具穷举更多的解空间来生成pattern,覆盖率确实更高,但运算时间也指数级增长。这里要平衡的是project schedule和coverage目标,正常情况下不建议一上来就跑最高档压缩,应该先跑默认档位看基线,再逐步加压。
5. 覆盖率卡死后的排查套路与实操记录
5.1 从coverage loss报告定位瓶颈环节
coverage卡住不动的时候,第一步不是改参数,而是把coverage loss分析报告打开,按fault class做分类统计。通常undetected和untestable是两类完全不同的处理方向。undetected说明设计约束下应该能测但工具没测到,可能是pattern生成不充分、约束过紧、或者故障在逻辑锥深处缺乏观测点。untestable则要再区分是设计逻辑冗余本身不可测,还是约束导致不可测,还是电路结构特殊导致没有测试方法。
我习惯的做法是做一张pareto表,把top fault loss的模块名、故障类型、所属时钟域、经过的逻辑锥列出来。如果某个模块贡献的loss特别重,我会单独用debug工具打开这个模块的电路图或者原理图,看懂这条路径上到底发生了什么。很多时候,原因就那么几类:输出被锁存逻辑挡住了,X态源头在某个memory,或者故障逻辑被一个恒定的约束信号完全卡死。
5.2 典型问题速查表和调试命令记录
下面这份速查表是我自己整理的,分享出来给大家做个参考。遇到问题对照着查,比从头分析快很多。
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| stuck-at覆盖低 | 约束过紧导致大量逻辑不可控 | 检查test constraint中的fixed值,尤其是复位和IO方向 |
| transition覆盖低 | capture clock约束不正确 | 核查launch/capture时钟设置和时序窗口 |
| 某个block覆盖极低 | scan chain连接错误或X态阻塞 | 检查该block的chain连接和X态传播路径 |
| pattern数量激增但覆盖不涨 | undetected故障过多 | 做coverage loss分析,定位undetected故障分布 |
| 大量fault被标为UO | X态或不可控信号 | 定位X态源,考虑增加测试点或X态阻断 |
| 报告里一堆TI | 逻辑被测试模式信号固化 | 检查TI故障点是否被测试点插入可以改善 |
ATPG工具里的debug命令也很有用。一般的调试思路是:选一个代表性的undetected故障,用故障列表追踪工具看它为什么无法被激励或观测。工具会告诉你这一步是可控性失败还是可观测性失败。如果是可控性失败,去看看激活条件里涉及哪些信号,这些信号的约束值是什么;如果是可观测性失败,沿着传播路径往后走,看它在哪个节点上被X态或常量信号截断了。
5.3 violation和DRC错误对coverage的连锁反应
ATPG之前一定会跑design rule check,也就是DFT规则检查。很多工程师run完check看到有几个violation,觉得不影响综合和仿真就忽略了,实际上这些violation往往就是coverage上不去的元凶。
最常见的violation是组合逻辑环路、不可控制时钟、异步set/reset信号未处理、锁存器违规。这些规则问题会直接影响ATPG能不能正确地控制scan cell和时钟,有些工具因为violation严重会自动禁用某些pattern类型,覆盖率自然就下来了。所以我的建议是,每次ATPG run之前先把DRC clean掉,至少要把和时钟、复位、扫描结构相关的violation全部解决。
5.4 实战记录:一次从92.7%到98.2%的覆盖率提升
最后分享一个真实的项目记录,这个项目我做下来收获很大。当时一个中规模数字模块,stuck-at覆盖率上线后停在92.7%,离要求的98%差了五个多点。我先做了coverage loss分析,发现大量故障集中在两个区域:一个是有异步接口的逻辑优化区,另一个是一片RAM输出后的控制逻辑。
第一个区域的问题很典型,异步接口的数据没有做同步处理,ATPG约束为了防止亚稳态,直接把好几个寄存器标成不可测。我的处理是找到接口数据在测试模式下是否可以被外部强制,如果可以就加一条测试模式约束把异步通路固定下来。第二个区域的问题是RAM输出没有已知初始值,导致后面一片组合逻辑的观测路径被X态切断。处理方式是在ATPG约束里对RAM输出做简化初始化,模拟成全0的已知输出,同时在scan测试时不check RAM的输出。
每一步调整后我会重新跑ATPG看coverage变化,确保没有引入新的失效pattern。最终stuck-at覆盖稳定到了98.2%,transition覆盖也从86%提到了90%以上。这个案例让我体会很深——coverage提升不是一个一次性动作,而是设计分析、约束优化、ATPG参数调整循环迭代的过程。每一轮可能只涨零点几个点,但积少成多,最终能把一个不达标的项目拉回正轨。
6. 关于coverage的最后一个认知
做了这么多个项目的DFT,我越来越觉得coverage不是一个单纯的数字指标,它是整个设计质量在测试维度上的投影。RTL写得好不好、时钟约束干净不干净、测试模式信号规划得合理不合理,最后都会在覆盖率报告里暴露出来。被coverage卡住的时候,与其怀疑工具参数没调好,不如先回过头看看设计本身有没有埋下地雷。
我也越来越看重coverage的trend分析而不是单点值。同一个模块,这版比上版覆盖率降了两个点,哪怕还达标,也要认真查一查是不是设计改动引入了新的不可测逻辑。coverage的下降从来不是无缘无故的,背后通常是DFT规则的松动或者约束的错误变更。养成看趋势、看diff的习惯,很多风险能在tapeout之前就拦下来。