
做DFT这行的人几乎都绕不过MBIST这个话题。每次拿到一颗新芯片的测试方案看到那一长串存储器的测试条目我脑子里冒出来的第一个词就是MBISTMemory Built-In Self-Test存储器内建自测试。这篇是Part 1我想把MBIST的测试原理从头到尾掰开揉碎讲清楚它到底解决什么问题、内部怎么运作、March算法是怎么回事、量产测试现场又该怎么用。适合刚入行的DFT工程师、芯片设计验证的同学以及所有想搞清楚“存储器测试为什么不是直接拿ATE去测”的人。先把结论放在前面MBIST的本质是让芯片自己产生测试向量、自己执行读写、自己比对结果外部只需要一个启动信号。理解了这句话后面所有细节都能顺理成章串起来。1. 为什么现在的芯片都离不开MBIST1.1 存储器在SoC里到底有多难测随便翻开一颗SoC的版图你第一眼看到的往往不是CPU核心也不是各种接口控制器而是一大片一大片的SRAM阵列。这个现象在业界很普遍存储器通常要占芯片总面积的50%以上某些AI加速芯片或者网络处理器里缓存和SRAM加起来甚至能到70%-80%。面积大意味着什么意味着工艺缺陷的概率也大。光刻的微小偏差、氧化层的针孔、金属连线的颗粒污染都有可能落在存储阵列里形成实实在在的坏点。麻烦的不只是面积。一颗SoC里往往有几十个甚至上百个独立的存储器实例容量从几KB到几MB不等分散在芯片各处。如果靠外部ATE自动测试设备直接驱动你需要把每个memory的地址线、数据线、控制线都引到芯片引脚上——这几乎是不可能完成的任务。即便用MUX把多个memory分时复用同一组测试引脚那些从测试引脚绕到存储器端口的连线也会造成巨大的延时导致测试频率拉不上去甚至影响功能时序。可以说物理结构决定了嵌入式存储器没法走“外部直连”的测试路线。1.2 MBIST的核心思路让芯片自己给自己体检MBIST的思路非常直白既然外部资源够不到存储器那就在芯片内部放一个小型的“测试机器人”让它自己生成地址、数据和读写控制信号把测试序列跑起来然后自动比对读回的数据。整个过程不需要外部ATE逐个时钟去驱动外部只要给一个启动信号等测试跑完读一个Pass/Fail结果就行。打个不恰当的比方这就像让一个学生自己出题、自己答卷、自己批改最后上报一个总分。这个设计解决了好几个实际问题。第一测试向量不需要从外部灌进来片内产生的数据可以在几个时钟周期内并行驱动整个存储器阵列测试速度极快。第二测试逻辑紧挨着存储器放置走线短、时序好控制可以使用芯片内部的高频时钟来测能够覆盖timing类的故障而这是低速外部测试做不到的。第三诊断信息可以存在片内寄存器里通过JTAG串行读出让产线知道故障到底发生在哪个地址、哪个bit。1.3 为什么不能全靠扫描测试很多人会问芯片不是有扫描测试Scan Test吗为什么不直接拿扫描链去测存储器这个问题我当年也疑惑过。扫描测试的核心思路是把寄存器串成链用外部ATE把测试向量串行搬进搬出。放到标准逻辑上这招很好使但放到大容量SRAM上就尴尬了如果把存储器的每一个bit都当成扫描链上的一个节点测试数据量会爆炸式增长——一个几Mb的SRAM测试向量集可能要用到几十上百MBATE的存储器和测试时间都顶不住。而且扫描测试受限于扫描链的移位频率一般只能跑到几十到一两百MHz存储器在正常工作频率下可能跑1GHz以上很多动态故障在低速测试下根本看不出来。MBIST则没有这个问题它直接并行驱动地址和数据内部状态机按功能时钟或者接近功能时钟的频率跑测试速度天然快一个数量级。所以业界的标准做法很明确标准逻辑靠扫描测试存储器靠MBIST两条腿走路。对比项扫描测试ScanMBIST测试对象标准数字逻辑存储器、寄存器堆向量产生位置外部ATE芯片内部BIST控制器测试频率受限于ATE和扫描链移位频率可用内部高频时钟测试时间数据量巨大测试时间长线性复杂度通常毫秒级故障定位靠扫描链逐拍分析靠诊断寄存器记录Fail地址2. MBIST测试原理从架构到算法的完整拆解2.1 MBIST系统里谁在指挥谁干活一个典型的MBIST系统拆开看由四块组成BIST控制器BIST Controller、被测存储器Memory Under Test、响应分析器Response Analyzer和测试接口通常是JTAG/TAP。BIST控制器是整个系统的核心里面有一个有限状态机相当于大脑。它按照预先定义好的测试序列一步步向存储器发出地址、数据、写使能、读使能信号。存储器执行完一笔操作后把读出的数据送回响应分析器。响应分析器有两种常见形态。第一种是比较器Comparator控制器在同一时刻也知道期望读到什么值直接把实际读出的数据和期望值逐bit比对任何一位不一致立刻记录Fail地址和Fail数据。这种方式的优势是定位精确诊断信息非常丰富产线拿到Fail地址就知道该修哪里缺点是期望数据生成和比较逻辑会占用不少面积。第二种是特征寄存器MISR多输入特征寄存器把整个测试过程中读到的所有数据压成一个签名Signature最后只比较一次签名。MISR的优势是省面积、连线简单适合对诊断粒度要求不高的场景缺点是如果最后的签名不匹配你不知道是哪个地址先出错排查起来要多费一番功夫。整套流程的状态流转大概是这样的复位后控制器停在IDLE状态收到RUN指令后进入INIT阶段先把所有单元写一遍初始值然后进入EXECUTE阶段开始跑正式测试序列。一旦所有March元素执行完毕状态机跳到DONE状态同时拉高BIST_DONE信号。如果有任何一个比较点失败BIST_FAIL信号也会被拉起来诊断寄存器里保存的Fail信息就可以通过TAP口逐位移出来。2.2 March算法手把手拆解March C-十个动作说完了架构来说说MBIST的灵魂——March算法。March这个词在存储器测试里有专门含义指的是一组按地址升序或降序排列的读写操作序列每一轮都会对存储器里的每一个单元执行完全相同的动作。它的时间复杂度是O(N)也就是测试时间跟存储器容量成正比。这个线性复杂度是March算法能成为工业标准的最大原因几MB的SRAM跑一遍也就是毫秒级的事。要理解March先得看懂March元素的写法。一个March元素长这样⇑(w0; r0; w1)意思是按地址从小到大⇑表示升序⇓表示降序对每个单元依次执行写0、读0、写1三个动作。括号里的r0表示期望读到0如果实际读出来是1比较器当场报Fail。业界用得最广的是March C-算法完整序列写成这样⇑(w0); ⇑(r0, w1); ⇑(r1, w0); ⇓(r0, w1); ⇓(r1, w0); ⇓(r0)翻译成人话就是六组动作第一组从低地址到高地址全部写0第二组再从低到高对每个单元先读0再写1第三组从低到高对每个单元先读1再写0第四组掉头从高到低读0写1第五组从高到低读1写0第六组最后从高到低再读一遍0。加起来每个单元经历10次操作所以March C-的复杂度通常写作10NN是存储单元总数。我举个只有4个地址的小例子起始所有单元是随机值。第一轮⇑(w0)把地址0到3全部写成0现在存储阵列是“0000”。第二轮⇑(r0, w1)从地址0开始先读期望读到0——如果读出1说明这个单元存在固定为1的故障立即Fail读出来是0就写1进去。接着处理地址1、2、3第二轮结束时阵列变成“1111”。第三轮⇑(r1, w0)再从地址0往高走每个单元先读1、再写0结束时阵列又回到“0000”。第四轮和第五轮换个方向从高往低再过两遍最后第六轮从高往低读0收尾。任何一个单元只要能写不能读、能读不能写、跳变跳不过去都会被这套序列逮个正着。实际项目中March C、March LR这些更复杂的算法也经常出现。March C在C-的基础上增加了一些读写组合对耦合故障的覆盖更完整March LR则是专门为了覆盖更多类型的耦合故障设计的操作数更多故障覆盖率也更高。工具生成测试算法时会根据存储器的类型、容量和覆盖率要求自动选择最合适的一套但作为工程师看懂March C-永远是基本功。2.3 故障模型与算法覆盖MBIST到底在抓什么错聊完算法再说说算法背后的“敌人”——存储器故障模型。常见的存储器故障可以归成几大类。固定故障SAF是最基础的某个存储单元永远停在0或者1怎么都写不进去转换故障TF是写0到1或1到0的跳变失败单元能存值但跳不过去耦合故障CF是某个单元的操作会污染相邻单元导致隔壁单元的读写结果出错地址译码故障AF是地址线译码异常你要访问A地址打开的却是B单元还有邻域敏感故障NPSF周围一圈单元的组合状态会限制中心单元正常翻转。不同的March算法对不同故障类型的覆盖能力差别很大。做一个对照表看得最清楚故障模型典型行为March C-覆盖情况SAF固定故障单元固定为0或1写入无效能覆盖TF转换故障0→1或1→0跳变失败能覆盖CF耦合故障写/读操作污染相邻单元部分覆盖CFin等类型需增强AF地址译码故障地址译码错乱访问到错误单元能覆盖NPSF邻域敏感故障邻居组合状态影响中心单元不能完整覆盖需专用算法为什么March C-能覆盖SAF和TF对CF却只能部分覆盖原因在于测试序列的刺激方式。比如检测SAF只要写0再读0、写1再读1任何读回的错值都会暴露问题检测TF需要连续写0再写1保证单元发生一次真实的跳变。而耦合故障需要特定的背景数据配合才能激发出来——你想知道地址3的单元会不会被地址2的单元干扰就必须让地址2处于特定值、地址3又同时执行操作。March C-里的背景数据在多个方向上做了翻转所以能覆盖一部分简单耦合但更复杂的耦合关系还需要March LR这类算法去深挖。3. MBIST测试流程实操从插入到量产3.1 Tessent MBIST插入设计的具体步骤原理归原理真正落地还得靠EDA工具。目前业界用得最多的MBIST实现工具是Siemens EDA的Tessent MBIST早年叫Mentor的MBISTArchitect另外Synopsys的DFT MAX也有类似能力。以Tessent MBIST为例插入流程大致分几步先把设计读进工具让工具扫描出所有存储器单元然后指定哪些memory需要测试、用哪种算法、控制器怎么共享工具自动生成BIST控制器的RTL代码并连好控制器与存储器之间的地址、数据、控制信号最后把这段RTL并进顶层设计连上TAP接口跑综合和仿真验证。工具生成的那坨BIST控制器RTL里面包含的东西其实前面都讲过地址计数器负责产生升序或降序地址数据生成器负责产生0或1的背景数据控制状态机负责按March序列切换读写操作后面还挂着诊断寄存器组记录第一次Fail的地址和期望数据。你不需要手写这些逻辑但你必须能看懂它的波形否则仿真一报错就只能干瞪眼。插入阶段还有一个很关键的决策点叫控制器共享方式。每个memory独用一个控制器好处是故障定位简单出问题直接锁定到某个特定memory缺点是面积大因为每个控制器都自带状态机和比较逻辑。反过来多个memory共享一个控制器通过分时调度来测试面积能省不少但诊断粒度变粗了需要在故障数据里带上存储器编号才能定位。我经手的项目里大多数做法是“分组共享”把同类型、同电压域、同功耗特性的memory分到一组每组一个控制器在面积和诊断能力之间取一个可接受的平衡。3.2 量产现场如何启动MBIST并判读结果设计做完MBIST最终要拿到ATE机台上跑。量产测试触发MBIST的方式有几种常见路径通过JTAG/TAP口发RUNBIST类的指令、直接拉专用测试引脚、或者放在Boot ROM里上电自动触发。不管用哪种方式外部看到的时序都差不多先把复位释放等待时钟稳定——如果MBIST用的是PLL出来的高频时钟还要等PLL锁定然后发启动命令最后轮询BIST_DONE信号。DONE拉起来以后如果FAIL信号是低电平说明这次测试Pass如果FAIL是高电平说明至少有一个存储器存在故障。Fail了之后怎么办读诊断数据。带诊断功能的控制器会把第一次失败的地址、期望数据、实际读出的数据、以及算法步骤号都存在诊断寄存器里。这个地址信息非常值钱它直接告诉你是哪一行哪一列出了问题。配合修复方案比如冗余行/列替换和eFuse熔丝产线上就能做BISR内建自修复把有故障的地址统一替换到备用单元上复测通过后烧写熔丝把替换信息固化下来。很多车规芯片和存储类芯片的最终良率就是靠“测试-修复-复测”这个循环一点点抠出来的。另外要注意仿真阶段通过MBIST仿真得到的结果最终要转换成量产用的测试向量格式常见的有WGL和STIL。这一步通常在工具里自动完成生成的文件会描述每个时钟周期TAP口上的电平变化。如果这一步处理不好仿真Pass了但ATE上跑不起来也是常见的事后面我会专门说排查方法。3.3 插入MBIST的面积、时序与功耗代价MBIST不是免费的午餐它有自己的面积、时序和功耗代价。面积方面一个共享控制器通常占地几千到几万等效门对动辄几千万门的SoC来说并不夸张但如果每个memory都配独立控制器累计起来就很可观了。项目里面积预算紧的时候控制器共享往往是最先被拿来做权衡的地方。时序方面控制器到存储器之间的地址、数据、控制线会增加额外负载尤其在高频场景下这条测试路径可能成为timing的瓶颈。实际项目里的一般做法是把MBIST测试时钟设为主时钟的分频比如工作频率1GHz就用500MHz来测。这样既能覆盖大部分时序故障又不会把布局布线逼到死角。功耗也要重视测试时所有memory同时读写瞬间功耗可能比正常工作还高严重的时候会掉压。解决办法是把memory分几批来测一批一批轮着来或者测试时临时降频。还有一个容易忽略的问题MBIST控制器和存储器之间的时钟域关系。控制器通常工作在TAP域或专门的BIST时钟域存储器正常工作在功能时钟域两个域之间要做同步处理否则跨时钟域的握手信号很容易出现亚稳态问题。你可以把控制器和存储器理解成一个讲普通话、一个讲方言中间必须配个翻译这个翻译就是CDC同步逻辑。很多MBIST跑飞、结果不稳定的case最后查来查去都是出在这一块。4. 踩坑记录MBIST实战中的常见问题与排查技巧4.1 功能正常但MBIST一直Fail怎么查这个现象我至少遇到过三次。功能仿真完全正常说明存储器本身的逻辑没有大问题MBIST持续Fail原因大多出在测试路径上。第一件事是降低MBIST时钟频率看Fail是否消失。如果降频后Pass了基本可以断定是时序余量不足存储器在高速下读出的数据在采样点已经变化属于“测出来的故障”不是“真实存在的故障”。这时候要么给存储器加时序约束要么调整BIST时钟。降频之后仍然Fail就要去核对期望数据的生成逻辑。比较器期望数据映射搞反是最常见的低级错误算法里写的是r0期望读到0但控制器内部期望寄存器的连线被工具接到了常1上读出来明明是0比对却失败。这种问题靠看波形一眼就能发现诊断寄存器里记录的期望数据是1、实际数据是0对照一下就知道谁错了。4.2 BIST控制器不动作DONE信号等不到发完RUN指令DONE信号迟迟不拉起来MBIST控制器完全不动作九成是时钟和复位的问题。我的排查顺序一般是先确认TAP命令是否真的写进去读一下控制器的ID寄存器能读到说明访问通路OK然后检查BIST时钟有没有翻转很多场景下PLL没锁定导致BIST时钟直接停摆最后看复位释放顺序如果存储器的复位先撤了、控制器的复位还没撤控制器在INIT阶段写进去的数据就会被存储器复位清掉两个状态机各玩各的测试自然卡死。遇到过的情况里把复位做成同源同序、统一由顶层控制释放基本都能解决。4.3 面积和诊断能力怎么平衡曾经有个项目为了让诊断地址精确到bit给每个memory都配了独立的MISR和诊断寄存器结果面积预算直接爆掉。后来改成把同类型、同电压域的memory共享一个控制器诊断数据里只保留第一次Fail的地址和memory编号面积省了四成产线定位故障的能力并没有明显下降。这条经验我反复使用先定诊断粒度再定控制器共享方式。先让工具用默认配置生成一轮看看面积报告再根据实际需要调整共享策略往往比一上来就追求最精细的诊断更高效。4.4 常见问题速查表症状可能原因检查顺序RUN后无DONETAP通路异常 / 时钟未起 / 复位不同步读ID→查时钟→查复位固定Fail期望数据接反 / 频率过高 / 存储器真损坏降频验证→核对算法→读诊断地址Fail地址始终在同行列存储阵列局部缺陷 / 地址译码问题换一个memory再测→确认物理坏点诊断签名不稳定跨时钟域握手问题 / MISR采样不稳检查CDC同步→降低BIST时钟良率正常但测试时间超标算法选太复杂 / 控制器串行测试太多评估降级算法→增加共享控制器并行测试修复后复测仍FaileFuse烧写地址错误 / 冗余资源不足核对修复映射→检查冗余行列数量这套速查表是我自己在项目里一点点积累出来的每次遇到MBIST问题先按表格顺序排除一遍大部分情况都能快速定位。特别是“降频验证”这一招成本最低、出结果最快强烈建议排在排查动作的前列。最后说一点个人体会。很多刚入行的同事一听到MBIST第一反应是去翻工具手册、背命令这没有错但我总觉得在跑任何一条Tessent命令之前先把March算法、故障模型、控制器状态机这几块原理吃透更重要。因为工具生成的脚本、报告、波形里满屏都是“MarchCminus”“SAF”“BIST_FSM”这些词不懂原理就只能对着波形瞎猜懂了原理一眼就能看出哪一步该写0却写了1、哪个状态该跳却没跳。这也是我这篇Part 1坚持从原理讲起的原因。下一篇我打算写Tessent MBIST脚本从入门到跑通把这些原理对应到逐条命令上。