这颗芯片第一次从测试机下来的时候ATPG的pattern怎么跑都挂在同一个向量上speed test更难看shmoo图红了一大片。一开始所有人都在怀疑是不是DFT插入的时候把哪条路径的约束做松了负责时序的同事翻了三天的timing report也没看出毛病。最后我拿示波器探头戳在下游PLL的参考时钟引脚上才反应过来一个特别低级的逻辑问题级联PLL的下游那一级被我做的OCC时钟控制给“饿死”了。简单说就是我把上游PLL在测试模式下旁路掉下游PLL没有了参考时钟直接失锁测试时钟链自然就断了。DFTC做OCC时钟控制本身是SoC芯片里at-speed测试很成熟的一条路径但级联PLL这个场景特别容易踩坑。级联结构在每个SoC里几乎都有比如外部晶振进主PLL主PLL的输出再喂给音频PLL、SerDes的恢复时钟PLL、或者USB PHY做参考时钟——外部晶振不够用、PCB上不想多放晶振、又或者需要跟片上时钟严格同源的时候这种“PLL串PLL”的设计非常常见。问题就出在OCC逻辑要管的是测试模式的capture时钟而测试模式下我们习惯性会把“用不到”的PLL全部旁路掉。这一句“用不到”里就埋着“饿死”的雷。1. 一颗芯片死在测试模式级联PLL“饿死”的现象与代价先说清楚“饿死”到底指什么。PLL本质上是一个闭环反馈系统它需要一个参考时钟作为输入鉴相器才能正常工作。级联PLL的下游这一级参考输入不是来自晶振而是来自上游PLL的输出。上游PLL一旦在测试模式下被旁路、被关掉、或者输出被切换到其他时钟路径下游PLL的参考输入就等于断了。PLL失锁之后输出频率会漂移或者干脆停在某个不稳定的状态这个时候不管OCC逻辑本身做得有多对从它出来的测试时钟都是有问题的。我在那个项目里遇到的现象很典型。Scan pattern全部能过因为scan shift本来就用的是慢速测试时钟低频下PLL状态根本不影响但一到at-speed的capture阶段就挂。挂在哪个向量上也不是固定的有时候同一个pattern这次跑过下次又跑不过完全看PLL失锁之后输出频率漂到了哪个位置。这种“时好时坏”的表现在封测厂那边会特别难排查测试工程师的第一反应往往是觉得pattern有race或者DFT约束有violation没人会想到是参考时钟链断了。这事的代价远不止调两天pattern。那颗芯片因为speed test过不了只能靠redundant pattern和低速功能测试来弥补at-speed覆盖率的缺口直接导致测试质量下降。后面为了验证确实是PLL饿死的问题我们把PCB上那颗芯片拆下来重新bonding了测试点又花了三周时间。算下来前后接近一个半月两个FAE、一个DFT工程师、一个验证工程师的人力全搭在这个问题里。回过头看这类问题其实在设计阶段完全可以避免关键是搞清楚一点OCC的参考时钟不是“你想用哪个PLL就用哪个PLL”而是“这个PLL能不能在这个时刻稳定地给出参考时钟”。级联结构下这个“能不能”是和上游所有PLL的状态绑在一起的。2. 为什么不能把OCC简单看成“时钟选择器”它在at-speed测试里的真实角色很多刚接触DFT的工程师会把OCC理解成一个多路选择器功能模式切功能时钟测试模式切测试时钟capture的时候控制一下脉冲数就完了。如果只是这样想就很容易在级联PLL的配置上出错。OCC的全称是On-Chip Clock Controller它的核心任务是在at-speed测试的capture阶段产生精确数量的、频率可控的时钟脉冲同时保证launch和capture之间的时序关系是确定的。它不是随便切一下时钟而是要把“功能路径上的时钟行为”在测试模式下复现出来。DFTCDesign For Test Compiler是工具流程OCC是它插入的硬件逻辑结构两者是“工具”和“产物”的关系。一个典型的OCC逻辑包含这样几个部分时钟选择mux用来在功能时钟、测试慢时钟、以及PLL输出之间切换脉冲计数器用来控制capture阶段产生几个时钟沿使能控制逻辑用scan_enable、shift_enable这类信号来区分shift阶段和capture阶段还有PLL lock信号的处理逻辑用来保证在PLL稳定之前不会发出capture脉冲。这里最容易被忽视的就是最后一点PLL lock信号的处理。OCC在设计上是“等PLL锁定了再发脉冲”的但“等”多久、在什么条件下“等”取决于DFTC插入时的配置。在单PLL场景下这很简单反正那个PLL只管自己等它lock了就行。但在级联PLL场景下问题变成了你等的这个PLL下游PLL它自己都没“吃饱”——它的参考时钟来自上游PLL而你在测试模式下恰好把上游PLL的一部分功能给关了或旁路了。OCC等一个永远等不到的lock信号capture自然就废了。打个不精确但很好懂的比方OCC就像一个厨房里的传菜员它要知道菜好了没有lock信号才能上菜。单PLL场景里菜是单独一个灶台做的传菜员盯着这个灶台就行。级联场景里下游这个灶台的火是靠上游那个灶台供气的你把上游的煤气阀门关了下游的菜永远做不熟传菜员再怎么等也没有用。所以级联PLL场景下DFTC插入OCC的视野必须是全局的。你不能只看“OCC的参考时钟选了哪个PLL”而要沿着这个PLL的参考时钟链一路往上游看确认整条链上每一个环节在测试模式下都能维持稳定。3. 级联PLL饿死的三个根因旁路开关、lock窗口和仿真模型的“假象”把级联PLL饿死这个问题拆到根上通常逃不出三个原因旁路逻辑放错了位置、lock等待窗口不够、仿真模型掩盖了问题。我一个个说。3.1 旁路开关的一刀切测试模式把所有PLL都bypass很多芯片设计里都会有一根全局的test_mode或dft_bypass信号进了PLL之后会把PLL强制到旁路模式也就是让时钟绕过PLL的倍频环路直接把参考时钟透传出去。这样做的初衷是方便某些低速测试省得PLL锁定的时间拖慢测试节奏。但问题也出在这根全局信号上。在级联结构里上游PLL的旁路信号实际上同时控制了下游PLL的“口粮”。你把上游PLL旁路了它的输出还会存在但已经不是正常的、干净的被锁定的时钟了下游PLL拿这个乱跳的信号当参考鉴相器根本锁不住输出就变成一团糟。在我们那个芯片里设计上为了稳妥把测试模式下的所有PLL都接到了同一个bypass控制上。功能模式一切正常一到测试模式上游主PLL被旁路下游音频PLL瞬间断粮。DFTC插入的OCC逻辑本身没有任何问题但因为它“信任”了设计给的PLL状态就跟着一起出问题。这个根因的解法其实不难级联结构里作为“参考源”的上游PLL在测试模式下不能被旁路要让它保持正常的锁定输出状态。如果确实需要旁路要么在旁路逻辑上对不同的PLL做区分要么让下游PLL在测试模式下改用独立的慢时钟源不要依赖上游PLL。3.2 lock信号的等待窗口PLL重新锁定也要时间第二个坑和PLL lock信号的时序有关它更隐蔽。即使你没有旁路上游PLL上游PLL输出正常下游PLL也可能因为测试过程中信号扰动、电源噪声等种种原因而短暂失锁需要重新锁定。PLL的锁定时间典型值在几十微秒到几百微秒量级具体看环路带宽和分频比。OCC逻辑在capture之前是要等lock信号的但DFTC插入时的等待逻辑通常是不管PLL是“一直锁定”还是“刚重新锁定”的它只看lock信号有没有拉起来。有些设计里的lock计数窗口比较短PLL还没完全锁定lock标志已经拉起来了有些PLL在临界锁定状态lock信号会抖动这时候OCC以为PLL好了实际上频率还没稳住capture打出来的波形自然是错的。我在后来的项目里总结了一条经验DFTC配置OCC的时候lock信号的来源和时序一定要让PLL供应商的模型里带出来的lock behavior对上。如果PLL的lock输出在锁定初期有毛刺OCC的等待逻辑就得加过滤或者干脆用lock_count多等几拍。这个在单PLL场景下可能不致命但级联场景下下游PLL的锁定时间还要叠加上游PLL的扰动窗口很容易不够。3.3 仿真模型的“假象”PLL模型在参考丢失时到底输出什么第三根因是最坑的因为它会让前面所有问题在设计验证阶段“看起来不存在”。很多PLL的行为级模型在参考时钟丢失或者混乱的时候输出的是一个X态或者未知态。在仿真里X态会直接传播到OCC逻辑导致capture使能一直拉不起来仿真直接报错。这种情况下验证工程师会发现“测试模式跑不通”但定位方向很容易走偏以为是自己控制逻辑写错了。更麻烦的是有些模型在参考丢失时保持上一时刻的输出频率看起来波形完全正常仿真里ATPG pattern能跑过但实际芯片里PLL早就失锁了。这就是“仿真通过、实测全挂”的经典剧本。我见过的项目里这个问题往往要等芯片回来才能暴露代价极大。所以做级联PLL场景的DFT验证时必须主动去检查仿真模型在参考时钟异常的情况下是什么行为如果模型过于理想就得人为注入故障来验证OCC的fail-safe行为或者至少在仿真环境下强制检查参考时钟链上每个节点的合法性。这一点DFTC本身不会替你做需要flow里额外加check。4. 定位饿死问题的完整排查链路从“pattern跑挂”到“揪出参考时钟链断点”如果你已经在芯片上看到了类似症状这里有一条我自己用过的排查路径每一步做了什么事、怎么判断都写清楚可以照着一步步走。4.1 第一步判断是生成问题还是硬件问题用仿真复现遇到at-speed pattern挂第一件事是区分问题的性质。先把同一个pattern在仿真环境里重新跑一遍用SDF反标时序看看仿真里能不能复现。如果仿真里也挂那大多是逻辑功能或约束问题如果仿真里全过而实测挂基本上可以默认怀疑测试时钟路径的硬件行为有异常——PLL链路是首要嫌疑。这一步的关键技巧是仿真通过不代表硬件没问题因为行为模型可能掩盖了真实PLL的非理想行为。所以额外要做一件事就是检查仿真里用的PLL模型是不是“理想得太离谱”如果是直接跳到第三步不要纠结仿真结果。4.2 第二步示波器实测看PLL输出频率和lock信号芯片贴到测试板上之后如果怀疑PLL链路直接量波形不要看pattern。把示波器探头戳在下游PLL的输出时钟引脚上触发条件设成测试模式的入口沿然后抓整个at-speed测试窗口内的时钟波形。正常情况应该看到一个频率稳定、占空比稳定的时钟。如果看到的波形是乱的、频率在漂移的、或者长时间停在某个电位上基本可以判定PLL工作状态异常。再拿第二根探头去量下游PLL的lock信号配合时钟波形一起看——如果lock信号在capture阶段之前根本没有拉高或者拉高之后又掉下来那问题就锁定在PLL锁定环节。4.3 第三步顺着参考时钟链往上查找到断点确认PLL有问题后不要急着改DFTC配置要逆着参考时钟链往上查。下游PLL的参考时钟是哪来的如果是来自上游PLL继续查上游PLL在测试模式下是什么状态。把测试模式下的控制信号波形拉出来看bypass信号有没有被置位、上游PLL的输出是否正常、中间有没有mux切到了别的路径。这一步是定位饿死的决定性环节。我当时就是在这里看到上游主PLL的bypass信号在测试模式下一路拉高同时下游PLL的参考时钟引脚上波形稀烂一下就明白了。4.4 第四步实验性修改验证根因找到断点之后不要急着流片先用一个实验性修改来验证判断。最简单的办法是在测试模式下强行让上游PLL保持正常的非旁路状态再跑一遍ATPG pattern。如果之前挂的pattern现在能过那根因基本石锤。如果上游PLL没法在测试模式下保持退一步的方案是把下游PLL的参考时钟在测试模式下切到一个独立的、可用的时钟源上比如直接把晶振时钟引过来这样下游PLL也有饭吃OCC也能正常工作。这个方法在很多项目里是最终的workaround虽然会增加一点时钟切换逻辑但能保住at-speed测试覆盖率。5. 级联PLL场景下DFTC配置的几个关键雷区从时钟边界到同步处理确认了饿死的原理之后再回到DFTC配置本身有一些具体的地方是特别容易踩雷的这里一条条过。5.1 时钟分组和OCC参考时钟的选择DFTC在插入OCC的时候需要为每个时钟域指定OCC的参考时钟。在级联PLL的场景里指定参考时钟的时候一定要把PLL之间的依赖关系考虑进去。比如下游PLL_OCC的参考时钟选了PLL_B那PLL_B的参考时钟PLL_A必须在整个测试窗口内稳定。操作上我会在DFTC的时钟规范里把PLL_A的时钟定义成“测试期间必须保持的时钟”不让工具在优化的时候把它优化成test clock。同时把PLL_B的锁定条件依赖的时钟路径全部设成false path或者case analysis避免工具在STA的时候误报。这些约束看起来很小但少一个都可能导致工具在优化时动到你不希望动的逻辑。5.2 全局bypass信号的层级分配很多设计的dft_bypass信号在顶层统一拉线到所有PLL这在功能上很简单但DFTC视角下这个信号会变成一个很大的约束扇出。如果某些PLL不能bypass就得通过DFT信号约束把它们的bypass关系打断。推荐的做法是在顶层定义清楚“可旁路PLL”和“不可旁路PLL”的清单然后给不可旁路的PLL单独做约束确保它们的bypass状态在测试模式下不被全局信号覆盖。这个清单最好能直接挂在DFT plan文档里方便后面人接手时不会改错。5.3 lock信号的异步处理和跨时钟域PLL的lock信号来自PLL的模拟部分和数字逻辑的时钟是异步的。DFTC插入的OCC逻辑里lock信号如果直接进到数字时序逻辑会有亚稳态风险。虽然OCC本身的时序容错性还好但最好的实践是给lock信号加两级同步器并且让同步器的时钟和OCC的控制时钟保持一致。级联PLL场景下下游PLL的lock信号还隐含了上游PLL的稳定性信息所以在约束上要把lock信号的到达时间相对于OCC的capture时钟沿留出足够裕量。我在一个项目里见到过因为lock信号同步器时钟选错导致capture阶段锁存到错误的lock值进而少发一个脉冲的情况排查起来极其痛苦。5.4 多PLL同时启动的功耗和串扰问题级联结构里还有一个容易被忽略的问题如果测试模式下所有PLL都要保持开启尤其是有好几个PLL串在一起的时候模拟部分的功耗会比单PLL场景大不少。IR drop一大PLL的抖动特性会变差可能从“稳定锁定”变成“锁定但抖动超标”最终还是会体现为at-speed测试失败。这个层面的问题DFTC管不了需要在芯片的电源规划阶段就给测试模式留出足够的余量。我建议在做PLL链路的功耗仿真时专门跑一个“全PLL开启at-speed capture”的模式看一下电源网络上最大的压降点在哪里。如果压降超标调整电源mesh或者加去耦电容都比事后在测试上补强要便宜得多。6. Hierarchy Flow的落地建议从子模块到顶层的时钟链统一规划前面聊的很多还是单芯片级别的问题一旦上了Hierarchy Flow也就是层次化设计流程饿死的风险还会再高一截因为每个子模块的DFTC是分开跑的工具很难看到完整的全局时钟链。这里给几条实际操作建议。6.1 子模块DFTC插入前先做时钟依赖分析Hierarchy Flow下子模块做DFT的时候往往是blackbox掉其他模块的你在这个子模块里看到PLL_B但PLL_B的参考时钟来自顶层你是看不到的。所以在子模块跑DFTC之前必须先做一轮时钟依赖分析把每个OCC参考时钟的源头一路追到真正的参考源晶振或者上游PLL然后把这条链路单独列出来标注出“测试期间必须保持稳定”的节点。这个分析结果要写进子模块的DFT约束文件里并且在插入OCC之后人工确认一遍。6.2 顶层接口信号规划让“必须保持”的PLL不受测试模式干扰层级化设计的接口规划里最容易出的问题是子模块里PLL的bypass信号被顶层测试控制信号接管了而顶层设计师并不知道这个PLL是另一个模块的参考。所以接口文档里必须明确列出哪些PLL是“本模块需要”的哪些PLL是“其他模块需要”的。对于后者你的模块在测试模式下绝对不能动它。这个列表在Hierarchy Flow里比在flat flow里重要得多因为你面对的可能是多个团队开发的模块互相之间根本不了解对方时钟链路的细节。6.3 顶层OCC和子模块OCC的协同避免两层都等lock还有一个很实际的问题如果顶层也插了OCC子模块也插了OCC两级OCC的lock等待逻辑可能互相冲突。顶层OCC在等顶层级联PLL的lock子模块OCC在等子模块PLL的lock两级的等待时间如果叠加在一起测试pattern的时序预算就非常紧张。我的建议是遇到级联PLL尽量不要做两级OCC都等待的配置。要么让顶层的OCC统一控制capture子模块的OCC只做时钟选择不复用lock等待要么反过来子模块控制顶层只透传。总之lock等待逻辑要收敛在一个层级不要两级同时参与否则时序很难收。6.4 Signoff前的一张自查清单最后分享一张我每次做类似项目signoff前都会过一遍的清单。不复杂但每一项都是真金白银换来的教训所有OCC的参考时钟逐条追到最终参考源确认测试期间整条链路都保持稳定关闭所有不必要的PLL旁路特别是级联链路里的上游PLL确认PLL lock信号的同步器时钟选择正确且等待窗口足够覆盖PLL重锁时间仿真验证里加入参考时钟断链的负向测试用例确认OCC能正确fail或进入安全状态顶层和子模块之间明确lock等待逻辑的归属层级不重复等待电源仿真覆盖“测试模式全PLL开启”场景确认IR drop不超标和PLL供应商确认模型在参考丢失时的行为不该理想的地方不要理想这套清单看起来繁琐但每次跑完都能拦下至少一两个问题有些问题如果流片之后才发现可能就是几十万美金的代价。做DFT的很多时候干的就是这种“在设计阶段多花一小时省下流片后一个月”的活儿。最后再多说一句个人体会DFTC始终是一个工具它可以按你的约束完美插入OCC逻辑但它不知道你的PLL之间谁是谁的“饭票”。级联PLL的时钟链在测试模式下能不能活本质上取决于做DFT的人有没有把芯片的真实时钟依赖关系Mapping到工具的约束里。这块思路理清了DFTC只是执行理不清它就带你在坑里兜圈子。
