☰
ATPG覆盖率突破:Clock PO与RAM Sequential模式实战解析
2026/10/7 6:31:33 网站建设 项目流程

做DFT这几年,我统计过一个不算严谨的数据:大多数测试工程师日常接触的ATPG pattern,85%以上是Basic Scan。这本身没毛病——标准扫描结构下,Basic Scan的生成流程最成熟、pattern体积最可控、解析也最省心。但一碰到两类设计,Basic Scan就开始露怯:一类是内部有时钟生成逻辑的,另一类是嵌了几块RAM却没有独立BIST的。前者要么覆盖率趴窝,要么pattern在仿真和ATE上反复横跳;后者直接给你报一堆unobservable。

这篇就专门拆这两种模式:Clock PO和RAM Sequential。它们不像Basic Scan那么“百搭”,但针对的场景非常明确——Clock PO解决的是内部时钟的可控和可观测,RAM Sequential解决的是存储阵列的读写序列测试。我会把它们的原理、工具约束方式、以及我在实际项目中怎么组合使用一次讲清楚。文章里的命令写法参考了TetraMAX和Tessent的通用风格,具体到某个版本项目里,还是要以自己的库和脚本为准,但思路是通用的。

1. Basic Scan的边界在哪:为什么它覆盖不了时钟逻辑和存储阵列

1.1 Basic Scan的经典时序:Shift、Launch、Capture

Basic Scan之所以能成为ATPG的事实标准,核心在于它把复杂的时序逻辑测试问题,转换成了组合逻辑测试问题。扫描链把所有触发器串成一条或者几条超长的移位寄存器,测试过程分成三个大阶段:

  • Shift阶段:scan enable拉高,所有扫描单元首尾相连。测试时钟连续翻转,每来一个沿,就从主输入移入一位数据,同时把上一轮捕获的响应往主输出方向推。shift的频率通常比功能时钟低很多,常见10MHz到50MHz之间,目的是绕开扫描链布线的时序收敛问题。
  • Capture阶段:shift完毕,scan enable拉低。此时每个扫描单元的Q端输出已经稳定,组合逻辑开始工作。给一个或几个capture脉冲,让组合逻辑的响应在时钟沿处被捕获回扫描单元。
  • Unload阶段:scan enable重新拉高,响应数据一边从扫描链末端移出,一边把下一条向量移入,这一过程是重叠的,所以吞吐率很高。

对stuck-at fault,capture只需要一个脉冲;对transition fault,需要两个脉冲——第一个脉冲launch,第二个脉冲capture。这就是为什么TDF pattern的capture窗口比SAF复杂得多,也更容易出问题。很多人在Clock PO模式上的困惑,恰恰是从这里开始:当capture时钟是由内部PLL分频产生的时候,你到底该让工具怎么理解这条时钟路径?

1.2 覆盖率上不去的三类典型未覆盖点

在纯数字逻辑设计里,Basic Scan覆盖90%以上的可测故障是常态,纯逻辑甚至能推到99%。但真实芯片很少这么干净。我总结下来,Basic Scan覆盖率卡住,通常就是三类东西在拖后腿:

第一类是内部时钟生成逻辑。PLL、分频器、时钟门控单元(ICG)的使能端、以及时钟MUX的选择端,这些逻辑要么在测试模式下被固定死,要么因为时钟路径太深,扫描链观测不到。尤其ICG的EN端stuck-at故障,如果没有对门控时钟做特殊处理,Basic Scan基本无能为力。原因很直白:捕获窗口就那么几个沿,时钟门的EN信号变化还没来得及传到数据路径,捕获已经结束了。

第二类是存储单元阵列。RAM的核心阵列不是标准单元,触发器扫描链根本伸不进去。Basic Scan能把读写逻辑、地址译码逻辑外围的故障模型抽出来,但一旦涉及位线短路、存储单元交叉耦合反相器的制造缺陷,扫描链没有任何观测点。工具报unobservable都算客气,有些情况下它直接把你RAM相关逻辑的全部故障都标记成uncontrollable。

第三类是模拟/混合信号接口。这个场景更复杂,但通常的处理方式是在接口处插隔离逻辑,让数字侧能看到一个确定值。Basic Scan能做,只是需要额外DFT设计支持,不是pattern本身能解决的。

1.3 一个反直觉的事实:扫描链越长,测RAM越难

以前有朋友问我:芯片里RAM本身测不到,那我把它周围多插几层扫描寄存器,是不是就能间接提高RAM的测试质量?答案是:能提高,但代价很高,而且有边界。

RAM的读写行为是顺序的。你要验一个地址能不能正确写入,必须先在某个周期把地址和数据送到RAM端口,写使能拉有效,等待写完成,再把读使能拉起来,读出数据,才能判断。这一套动作在Basic Scan的capture窗口里根本做不完——capture脉冲通常就一两个周期,RAM还没来得及把数据写进去,捕获就结束了。扫描链插得再多,capture窗口也撑不住整个写-读序列。

所以对付RAM,要么上Memory BIST,靠片上状态机自己跑March算法;要么用RAM Sequential模式,让pattern在多个时钟周期里完成写-读序列。后者不需要额外硬件,但对工具约束和pattern长度控制的要求高得多。这个我会在第三章展开。

2. Clock PO模式:当内部时钟必须被“看见”并“接管”

2.1 Clock PO在ATPG工具里到底是什么意思

很多人第一次看到Clock PO这个词,以为就是把时钟引脚当作普通输出看一眼。这个理解方向对,但不够深。

在ATPG工具的术语里,Clock PO的意思是:时钟信号不仅作为扫描链和捕获时钟存在,还要作为一个可观测的主输出被pattern显式地检查和比对。换句话说,工具会在生成的pattern里为这个时钟信号单独记录期望值,ATE在跑pattern的时候,会像检查data_out一样检查这个时钟节点。

为什么需要这么做?因为可观测性是覆盖率的前提。一个内部时钟信号如果既不控制任何扫描单元,又不被主输出采样,那它对ATPG来说就是盲区。盲区意味着潜在缺陷可能在测试中漏掉。把时钟配成PO之后,工具就有了“眼睛”去看这个时钟是否按预期翻转、是否在预期时刻出现了正确的边沿。

在TetraMAX和Tessent里,把内部时钟设为PO的常见做法包含两个层面:一是网表级别,把PLL输出或者分频器输出引到某个测试专用主输出引脚上,或者通过MUX接到已有的观察引脚;二是在约束文件里,用set_dft_signal / add_clock这样的命令声明该时钟的观察属性。具体命令语法各版本有差异,但思路一致:让工具知道这个节点既当钟用,也当信号采。

2.2 测试时钟直通方案:从PLL输出直接引到测试引脚

实际项目里用Clock PO,最常见的一个场景是:测试的时候不想依赖内部PLL,直接把外部测试时钟引进去。芯片进入test mode后,ICG和时钟MUX把PLL路径断掉,功能时钟全部由外部测试时钟引脚接管,这样时序上完全可控,pattern在ATE上也稳定。

这个过程中有一层MUX逻辑是必须被测试的——test mode选择信号、MUX的输入输出。如果不做任何处理,这个MUX的select端通常可以由扫描单元控制,但时钟MUX的输出如果直接驱动整个时钟树,那这个输出节点本身的值变化,在Basic Scan的capture窗口里是“看不见”的。解决方案就是把这根时钟线在测试模式下接成可观测的Clock PO:要么引到专门测试引脚,要么在MUX输出处加一个观测寄存器。

我这里有一个真实踩过的坑。某个项目的PLL在低速测试模式下输出本身就是不稳定的——PLL的锁定需要时间,如果pattern一开始就期望它输出规整时钟,Capture阶段很容易采到毛刺。后来我们把PLL输出配成Clock PO,并且在pattern开头预留了锁定等待周期,让ATE多等几个毫秒再开始比对那个PO点上是否有期望时钟翻转,问题才彻底消失。这个等待时间的设置在Basic Scan里完全用不上,但一旦Clock PO上场,就必须考虑。

2.3 复用功能时钟树的方案:约束的内部细节

另一种做法是不切外部测试时钟,让功能时钟树在测试模式下也工作,由PLL正常供钟。这种方案对at-speed test很有价值,因为功能频率下时钟树的真实延迟、skew、以及门控逻辑的时序行为都更接近实际使用。

但复用功能时钟树,对ATPG约束的挑战是:工具必须清楚每个capture沿是从哪一级分频来的。如果你有四路分频时钟,每一路都驱动着不同的扫描链,工具在生成transition pattern时,必须保证launch沿和capture沿来自同一条时钟路径,否则捕出来的响应没有意义。

这个时候Clock PO的作用从“观测”变成了“锚点”。工具会把多条分频时钟的叶子节点分别设成PO,并在pattern里记录它们的翻转相位。我做过的方案里,最稳妥的做法是给每一路分频时钟都加一个独立的Clock PO,并且在约束里明确声明它们的相位关系:同沿翻转还是不同沿翻转。如果不声明,工具默认它们同相,一旦实际相位差半拍,整个TDF pattern在仿真阶段就会暴露出一堆伪失败,排查起来非常痛苦。

2.4 实测中Clock PO常被忽略的时序坑

第一个坑是毛刺捕获。时钟信号在翻转过程中会有短暂的中间电平或振荡,如果ATE采样点刚好落在毛刺上,pattern比对就会失败。这种失败不是真故障,是采样时机问题。解法有两条:一是调整ATE上的采样沿,把采样点靠近期望电平稳定区域;二是对Clock PO做mask窗口,只在特定周期观察,其他周期不比对。

第二个坑是时钟树的RC延迟导致路径不匹配。同一个时钟源经过两级缓冲到达PO节点的时间,和到达触发器时钟端的时间可能差几百皮秒。对于慢速shift没问题,at-speed capture时这个差异会让工具误判时钟沿。这不是pattern生成错误,而是约束里的时序信息不够精确。把SDF反标做完整,或者在工具里设置时钟树延迟的保守值,能缓解。

第三个坑藏在仿真里。很多RTL仿真环境的时钟是ideal的,RC延时为零,Clock PO的期望值在仿真中很容易比对通过,但到了ATE上因为真实延迟就挂掉。所以一旦启用Clock PO,我建议在仿真阶段就加一些人为的时钟偏斜约束,而不是全默认ideal。别问我为什么推荐这么做——你要是见过一次仿真全绿、ATE全红的场面,你也会这么干。

3. RAM Sequential模式:动手构造写-读序列来测存储器

3.1 为什么RAM绕不开Basic Scan的盲区

RAM的基本存储单元是交叉耦合反相器加访问管,它的制造缺陷模式很特殊:字线开路、位线短路、单元下拉管驱动能力不足、访问管泄漏过大等。这些缺陷在逻辑测试里会表现为一个个具体的stuck-at或transition点,但问题是你根本控制不了存储单元内部节点。

更麻烦的是,RAM在未初始化时输出是X态。Basic Scan的capture周期如果落在RAM读路径上,扫描链捕获回来的可能是X,这个X会在整个扫描链上传播,导致大量其他本可以正常捕获的故障也被标记成未知。这也是为什么很多ATPG报告里,一旦RAM出现在设计中,即使面积占比很低,coverage数字也会很难看。

所以RAM要么用BIST,要么用RAM Sequential。BIST需要额外硬件(状态机、比较器、BIST接口),大RAM上划算;小RAM或者寄存器堆上,很多前端团队不愿意为此多花面积,这时候RAM Sequential是现实的选择。

3.2 RAM Sequential的激励序列设计:从写0/读0到地址扫描

RAM Sequential模式的基本思路并不复杂:通过扫描链把地址、写入数据、写使能、读使能全部加载好,然后产生一个写周期,把值写进RAM;再把地址、读使能加载好,产生一个读周期,读出数据,和期望值比对。

听起来简单,但真正生成pattern时,要考虑的序列比想象中多:

  • 最基本的是写0读0、写1读1,这能覆盖存储单元的stuck-at fault和位线的stuck-at fault。
  • 为了覆盖位线短路,需要棋盘格数据背景(比如0x55和0xAA交替),这样相邻位线的期望电平相反,短路才可能被暴露。
  • 为了覆盖地址译码逻辑,需要对地址做遍历组合,常见的有递增地址、递减地址、walking 0/1、以及格雷码跳变。地址跳变幅度越大,对译码逻辑的翻转覆盖越好。
  • 为了覆盖数据线上的transition fault——也就是某根线从0变1或从1变0的过程太慢——需要连续写两个互补值,然后马上读出来,这就是“写0写1读”的三步序列。

这里有一个关键点:RAM Sequential的pattern数量不是由逻辑故障决定的,而是由地址深度决定的。一个4K深的RAM,如果每个地址都要走一遍比较完整的写-读序列,那么单是这一个RAM就可能导致几千条pattern。实际项目中必须权衡:全地址遍历可能让pattern量爆炸,而只抽测部分地址又可能漏掉某些译码故障。我见过比较保守又合理的做法是,对小容量RAM(比如深度小于2K)做全地址遍历,大容量RAM只做边界地址加随机抽样地址,把完整的March测试交给BIST去跑。

3.3 工具里的memory model与pattern生成机制

在TetraMAX和Tessent里,RAM Sequential模式的生成依赖memory model。工具需要知道RAM的端口时序、时钟边沿、读写控制信号的关系,才能规划出合理的激励序列。这个model通常有两种来源:一是标准单元库厂商提供的lib模型附带memory信息;二是在工具里手动定义规则。

手动定义的阶段最容易出问题。比如一个双端口RAM,工具默认的读写时间窗口只有几纳秒,但实际设计中写脉冲可能需要更长时间才能稳定;也可能反过来,RAM的实际建立时间比工具模型里的默认值短,导致pattern过于保守、测试覆盖率下降。这些参数没有统一标准,完全依赖后端时序报告来校准。

我习惯在一个新的RAM型号接入测试流程时,先跑一个“探针pattern”:仅对RAM写一个地址,读回来,用仿真工具看数据是否正确。如果探针通过,再把RAM加入正式ATPG流程;如果探针都过不了,说明memory model的参数配置有问题,这时候强行生成大量pattern只会浪费跑机时间。

3.4 RAM Sequential与MBIST的适用边界对比

RAM Sequential和MBIST是并存关系,不是替代关系。我做了个简单对比:

对比维度RAM SequentialMemory BIST
额外硬件无需要BIST控制器和比较器
面积成本零每个RAM约增加2%~5%面积
测试时间pattern数多,测试时间较长片上自动跑,时间短
故障覆盖重点RAM I/O逻辑、互连、基本阵列SAF存储单元阵列内部缺陷
适用场景小容量RAM、寄存器堆、无BIST设计大容量RAM、需要at-speed March
对ATPG工具依赖依赖memory model准确度不依赖,仿真验证即可

从这个表能看出来,RAM Sequential最大的优势是零硬件开销,尤其是寄存器堆和微小的FIFO,上BIST简直是大炮打蚊子。而RAM Sequential最大的短板是pattern体积和测试时间——所以生产测试中,大RAM用BIST,小RAM用RAM Sequential,两者把覆盖率拼起来,才是效率最高的组合。

4. 一个混合测试方案实例:时钟管理单元加四块SRAM的覆盖率突围

4.1 项目背景和初始覆盖率瓶颈

去年经手的一个老项目翻新版,芯片规模不算大,但内部结构挺典型:一颗通过外部晶振输入、内部PLL产生四路分频时钟的SoC,四块RAM——两块512x32的单端口SRAM,一块256x16的双端口SRAM,还有一块1Kx8的FIFO。没有Memory BIST。

第一轮Basic Scan结果跑出来,stuck-at总覆盖率89.7%,transition coverage只有78.4%。项目TE只给了一句备注“覆盖率不达标,请分析”,后面的活儿全落在我们DFT团队头上。

把ATPG报告里未覆盖故障按模块归拢之后,原因很清楚:

  • 时钟管理单元占了未覆盖故障的22%。PLL分频寄存器的部分输出、ICG使能逻辑、以及时钟MUX的select逻辑,都是扫描可控但不可观测,或者捕获时序上根本来不及。
  • RAM相关逻辑占了未覆盖故障的31%。四块RAM的输入输出逻辑虽然接了扫描链,但捕获窗口内的X态传播太严重,工具在生成时直接放弃了一大片区域。

这两个问题,正好对应Clock PO和RAM Sequential两种模式。

4.2 Clock PO和RAM Sequential的加入方式

我们先处理时钟管理单元。设计里有一个测试模式信号test_mode,拉高之后,PLL输出和四路分频时钟都通过MUX切换到外部测试时钟。我的操作是:

  1. 在RTL里把四路分频时钟的输出节点引到一组测试观察引脚上——这组引脚平时不用,只在测试pattern里被观察。
  2. 在ATPG约束里,把这四个节点分别声明为Clock PO,并且注明四路时钟的相位关系。
  3. 对于ICG单元,不直接把它们全设为PO,而是选择ICG输出端的时钟叶子点做PO——因为ICG使能端的故障会在时钟是否翻转上体现,盯住叶子点就够了。

RAM这边做RAM Sequential。因为容量都不大,我决定对四块RAM全部做全地址遍历。FIFO因为是1K深度,也做全地址。扫描链结构里,RAM的地址、数据、写使能、读使能都接到了扫描单元上,所以加载激励不需要额外硬件,工具自动安排。

约束上有一个细节:RAM的输出在未初始化时是X,为了避免X态污染扫描链,我在RAM输出端加了一个扫描测试专用的bypass逻辑——测试模式下,RAM输出被一个可控的MUX钳到固定值,只有需要读比较的时候,才把RAM的输出真正接到扫描链上。这个bypass逻辑不算大,但对pattern可靠性提升非常明显。

4.3 最终覆盖率、pattern体积和测试时间的实测数据

改完约束重新跑,结果如下:

指标仅Basic Scan增加Clock PO再增加RAM Sequential
Stuck-at覆盖率89.7%93.4%96.8%
Transition覆盖率78.4%84.1%88.7%
Pattern数量3,4123,9876,352
ATE测试时间@5MHz1.21s1.36s1.47s

需要说明的是,这个测试时间是在慢速shift频率下的估算,不是at-speed。但趋势很清楚:加入Clock PO之后,覆盖率提升的性价比极高,pattern只增加了不到600条;RAM Sequential把pattern数量推高了将近60%,但测试时间只增加了约8%——因为RAM这条路径不需要每条pattern都走完整的shift+unload,很多RAM相关的激励周期数比较短,整体上还是划算的。

这次经验让我确认了一件事:遇到覆盖率瓶颈时,先看未覆盖故障都长在哪里,再决定上哪种pattern模式,而不是盲目堆pattern或者调压缩选项。工具压缩开得再高,盲区还是盲区。

5. 选型判断、高发故障与操作清单

5.1 场景化的pattern类型选择表

把三种模式放到一个表里,平时做方案评审时直接对着查:

设计特征推荐pattern模式关键原因
标准扫描逻辑占绝对主导Basic Scan效率最高,pattern体积最小
内部有PLL/分频时钟且需要验证Clock PO让内部时钟可观测、可控
ICG门控时钟大量存在Clock PO + Basic Scan覆盖ICG使能端和时钟叶子
小容量SRAM/寄存器堆,无BISTRAM Sequential零硬件成本覆盖RAM I/O逻辑
大容量RAM建议补Memory BISTRAM Sequential会pattern爆炸
双端口RAMRAM Sequential要校准模型两个端口时序窗口不同
模拟/混合信号接口先插隔离逻辑再做Basic Scan消除X态源头

组合使用的时候,order也很关键。我的习惯是先跑Basic Scan基线,把稳定覆盖率和未覆盖故障分布拿到手;再用Clock PO去清理时钟相关的盲区;最后才把RAM Sequential加进来。顺序反过来的话,RAM带来的X态会污染前面所有的分析。

5.2 高发故障排查:从X态到仿真不匹配

我在多个项目里总结过几类高频问题,几乎每次和RAM Sequential打交道都会碰上:

  • X态从RAM传出来:芯片仿真时RAM没有初始化,直接跑pattern,仿真结果里一片X。解决办法两个方向:一种是在pattern最前面加一段初始化序列,把目标RAM全部写成固定值;另一种是用仿真工具的memory初始化命令,在跑patttern之前在RAM模型里填入期望值。后者省pattern时间,但生产ATE上用不上,只能在验证环境里用。
  • RAM Sequential的pattern在读周期的时序窗口偏窄:工具按库模型给的读写建立保持时间去规划激励,但实际后端的时钟树延迟偏大,导致仿真里能过、板上跑挂。碰到这个情况优先看库模型的memory timing参数是不是被覆盖了,而不是直接调pattern的频率。
  • Clock PO和Basic Scan共享引脚导致冲突:如果一个测试引脚既要当主输入,又要当Clock PO的观察输出,工具会报drive conflict。我的经验是尽量物理分开,实在分不开就用MUX控制方向,不同pattern段里切换。
  • TDF pattern下Clock PO的期望值与仿真不匹配:这个问题通常出在工具对时钟翻转沿的默认理解和实际设计不一致。解决方式是显式约束Clock PO的观测时刻,别让工具自由发挥。

5.3 给DFT工程师的落地清单

最后说几条我自己的习惯,不算标准答案,但对新项目有一定参考价值:

  • 项目一开始就做pattern类型规划,不要等覆盖率报告出来才补。时钟生成模块、RAM模块、门控时钟密度,这些在设计调研阶段就能看到。
  • 所有内部时钟的PO观测点,尽量在RTL阶段就加好测试引脚。版图完成之后再想引出来,走线成本会翻倍。
  • 对RAM Sequential的pattern量要提前估算。估算公式很简单:地址深度 × 数据背景种类 × 读写序列步数,乘以平均故障密度,就是大致的pattern量。如果这个数量超过你测试时间预算的1/3,就要考虑是不是该上BIST了。
  • 每一次新增pattern模式,都要在仿真阶段完整跑一个回退验证,别只在ATE上去赌。多花半天仿真,能省下整个流片后debug的周期。
  • 工具报告里的unobservable不是终点,它是一张地图。把未覆盖点按模块、按器件类型、按故障模型三个维度透视图导出来,很快就能定位到是模式选型的问题,还是网表约束的问题。

做测试这行,很多人容易陷入一个误区:以为覆盖率上不去就是pattern数量不够,于是拼命开压缩、加pattern,结果只是把同一个盲区测了一百遍。其实换个pattern类型,有时候比多跑一千条pattern管用得多。这篇文章提到的Clock PO和RAM Sequential,就是我在实际项目里最常用的两把“备用钥匙”。无论你用的是TetraMAX还是Tessent,只要理解它们各自在解决哪个层面的问题——时钟可观测,还是存储可测试——很多看似刁钻的覆盖率数据,都能对着光看出门道来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询