☰
MBIST测试中GO/DONE信号握手协议与故障定位实战
2026/10/7 17:58:02 网站建设 项目流程

1. MBIST到底是什么,为什么GO/DONE两个信号值得单独拎出来讲

第一次接触MBIST的人,往往会被一堆缩写砸晕:BIST、BISR、TAP、JTAG、Controller、March算法……但真正到了芯片回片调试阶段,你会发现工程师盯得最紧的,其实就两个信号:GO和DONE。一个负责"发令",一个负责"交卷"。把这两个信号吃透,内存故障定位的效率能提升一大截。

MBIST全称Memory Built-In Self-Test,中文叫存储器内建自测试。它的核心思路很朴素:在芯片内部集成一套专门测试SRAM、ROM、DRAM等存储阵列的硬件电路,上电或按需触发后,由这套电路自动完成写入、读取、比较、诊断,最后把结果通过状态信号或寄存器暴露出来。相比把内存测试交给外部ATE设备,MBIST的优势在于频率高、覆盖全、可重复、可片上诊断,尤其是大容量存储阵列,外部测试机根本跑不到那么高的频率。

那GO和DONE为什么重要?因为它们构成了MBIST控制器与外部世界之间最基础的握手协议。GO是启动信号,告诉控制器"可以开始跑了";DONE是完成信号,告诉外部"我跑完了,结果在状态寄存器里"。很多工程师在调试时遇到"测试卡住不动"或者"结果读出来全是0",追根溯源,十有八九是GO/DONE的时序、极性、握手方式没对齐。

这篇文章适合三类人看:一是刚接触DFT的验证工程师,二是需要做芯片bring-up的固件/驱动工程师,三是想理解MBIST诊断流程的测试工程师。我会从信号定义、握手协议、实操流程、故障定位、常见坑几个维度展开,尽量把每个"为什么"讲清楚,让你看完能直接对着波形和寄存器干活。

提示:本文讨论的GO/DONE是MBIST控制器对外暴露的通用状态信号,不同IP厂商可能命名为start/run_done、bist_go/bist_done、mbist_start/mbist_done等,逻辑本质一致,阅读时按你项目里的实际命名对应即可。

2. GO/DONE信号的底层逻辑与握手协议拆解

2.1 GO信号:不只是一个上升沿那么简单

很多人以为GO就是一个简单的脉冲,拉高一下控制器就开始跑。实际项目里,GO的处理方式直接决定了测试的可靠性和可重复性。GO信号通常有三种常见形态:

  • 电平敏感型:GO保持高电平期间控制器持续运行,拉低则中止。这种设计适合需要动态暂停的场景,但容易因为毛刺误触发。
  • 边沿触发型:检测到GO的上升沿后启动一次完整测试,之后GO的状态不再影响运行。这是最常见的做法,抗毛刺能力强。
  • 脉冲握手型:GO发出一个脉冲,控制器回一个ack,双方确认后才开始。这种最稳妥,但时序最复杂。

为什么要在意这些区别?因为边沿触发型如果GO信号上有毛刺,可能触发多次测试,导致DONE信号出现多次翻转,外部状态机误判。我见过一个项目,GO走线太长又没做同步处理,结果每次上电测试都跑两遍,功耗超标,查了两周才发现是毛刺惹的祸。

GO信号还有一个容易被忽略的点:它和时钟域的关系。如果GO来自慢速的APB时钟域,而MBIST控制器跑在高速核心时钟域,中间必须做跨时钟域同步。常见做法是两级触发器打拍,再加边沿检测。如果省掉这一步,GO的建立/保持时间在高速域里可能不满足,控制器采样到亚稳态,表现就是"有时候能跑,有时候跑不起来",这种间歇性故障最难查。

2.2 DONE信号:完成不等于成功

DONE信号最容易被误解的地方,就是把它当成"测试通过"的标志。DONE只表示测试流程结束,不表示测试结果合格。合格与否要看状态寄存器里的pass/fail位,或者看错误地址寄存器有没有内容。

DONE的常见形态也有几种:

  • 电平型:测试完成后DONE拉高并保持,直到下一次GO到来或软件清除。
  • 脉冲型:测试完成后DONE输出一个脉冲,宽度通常是一个或几个时钟周期。
  • 计数型:DONE配合一个完成计数器,表示跑完了多少个pattern或多少个地址。

这里有个实操中非常关键的细节:DONE的采样时机。如果DONE是脉冲型,而外部状态机采样太慢,可能直接漏掉。我一般建议在验证阶段就用逻辑分析仪或片上ILA抓DONE,确认脉冲宽度至少覆盖外部采样时钟的2到3个周期。如果不够,要么在RTL里加宽,要么在外部用边沿检测加锁存。

还有一个坑:DONE在复位后的初始状态。有些IP默认DONE为高,表示"空闲即完成",有些默认低。如果外部逻辑假设DONE初始为低,结果IP实际为高,上电后状态机直接跳到"测试完成"分支,读了一堆无效数据。这种问题在集成阶段特别常见,一定要对着IP手册确认复位值。

2.3 GO/DONE握手时序:一张表看清四种组合

把GO的触发方式和DONE的反馈方式组合起来,实际项目里常见四种握手模式。下面这张表是我根据多个项目经验整理的,方便你快速对照自己项目属于哪种:

握手模式GO形态DONE形态适用场景风险点
模式A边沿触发电平保持大多数SoC上电自检DONE未清除导致下次误判
模式B边沿触发单脉冲低功耗快速测试脉冲漏采
模式C电平敏感电平保持需动态暂停的调试GO毛刺误触发
模式D脉冲握手脉冲应答高可靠汽车电子时序复杂,握手超时

理解这张表的意义在于:当你发现测试行为异常时,先确认自己项目用的是哪种模式,再针对性排查。比如模式B下DONE读不到,优先查采样时钟和脉冲宽度;模式A下DONE一直是高,优先查清除逻辑。

2.4 为什么MBIST要用GO/DONE而不是直接读寄存器

有人会问:既然有状态寄存器,为什么不直接轮询寄存器,还要单独搞GO/DONE信号?原因有三个。

第一,速度。MBIST测试可能跑几十毫秒甚至上百毫秒,如果CPU一直轮询寄存器,总线被占死,其他任务没法跑。用DONE做中断或DMA触发,CPU可以先去干别的。

第二,硬件联动。DONE可以直接接到电源管理单元、时钟控制器或复位控制器,实现"测试完成自动切时钟""测试失败自动复位"等硬件级联动,不依赖软件。

第三,调试可见性。GO/DONE是物理信号,可以直接挂示波器、逻辑分析仪,或者片上ILA抓取。寄存器读值只能看到结果,看不到时序关系。定位"为什么没跑起来"这类问题时,信号波形比寄存器值有用得多。

3. 从GO拉高到DONE返回:一次完整MBIST测试的实操流程

3.1 测试前的准备工作:别急着拉GO

很多人一上来就拉GO,结果测试失败,回头查半天发现是准备工作没做。MBIST测试前,至少要做以下几件事:

  1. 确认时钟已稳定:MBIST控制器需要时钟才能跑。如果时钟还没锁定就拉GO,控制器可能进入未知状态。建议在时钟稳定标志置位后再发GO。
  2. 确认复位已释放:复位期间GO无效。有些IP要求复位释放后等待若干周期才能接受GO,这个等待时间手册里一般会写。
  3. 配置测试模式寄存器:比如选择March算法类型、选择测试地址范围、选择是否开启诊断模式。这些配置必须在GO之前完成。
  4. 清除上一次的DONE和状态寄存器:如果DONE是电平保持型,不清除的话,新的GO发出后DONE还是高,外部逻辑分不清是新结果还是旧结果。
  5. 确认内存阵列已上电:有些低功耗设计里,内存阵列独立供电,测试前要确保电源域已开启。

我一般会把这些准备步骤写成一个checklist,每次bring-up对着打勾。看起来繁琐,但能省下大量debug时间。

3.2 GO信号的发出:时序和同步的实际处理

假设你的项目用的是边沿触发型GO,来自APB时钟域,MBIST控制器在核心时钟域。下面是一段典型的同步和边沿检测逻辑,用Verilog示意:

// 跨时钟域同步GO信号 reg go_sync1, go_sync2, go_sync3; always @(posedge clk_core or negedge rst_n) begin if (!rst_n) begin go_sync1 <= 1'b0; go_sync2 <= 1'b0; go_sync3 <= 1'b0; end else begin go_sync1 <= go_apb; go_sync2 <= go_sync1; go_sync3 <= go_sync2; end end // 上升沿检测 wire go_pulse = go_sync2 & ~go_sync3;

这段代码的关键点:三级触发器。前两级做同步,第三级做边沿检测。为什么是三级不是两级?因为两级同步后信号已经稳定,但要做边沿检测还需要一个延迟版本,所以实际用了三级。如果只用两级,边沿检测会缺少参考点。

发出GO的软件侧操作通常是写一个寄存器位:

// 假设MBIST控制寄存器地址为0x4000_1000 // bit0为GO位,写1触发 #define MBIST_CTRL_REG (*(volatile uint32_t *)0x40001000) #define MBIST_GO_BIT (1 << 0) void mbist_start(void) { MBIST_CTRL_REG |= MBIST_GO_BIT; }

注意这里用的是|=而不是直接赋值,避免误清除其他配置位。有些IP要求GO位自动清除,写完就归零;有些要求软件手动清除。这个必须看手册,搞错了会导致重复触发或无法触发。

3.3 等待DONE:轮询、中断还是DMA

DONE的等待方式直接影响系统效率。三种方式各有适用场景:

  • 轮询:最简单,适合bring-up阶段和裸机环境。缺点是占CPU。轮询时要注意加超时,否则测试卡死时CPU也跟着卡死。
  • 中断:DONE接到中断控制器,测试完成后触发中断。适合有OS的环境。要注意中断清除和DONE清除的顺序,先清哪个后清哪个手册一般有要求。
  • DMA/硬件联动:DONE直接触发DMA搬运结果,或者触发电源管理切换。适合低功耗场景。

轮询的典型代码:

#define MBIST_STATUS_REG (*(volatile uint32_t *)0x40001004) #define MBIST_DONE_BIT (1 << 0) #define MBIST_TIMEOUT (1000000) int mbist_wait_done(void) { uint32_t timeout = MBIST_TIMEOUT; while (!(MBIST_STATUS_REG & MBIST_DONE_BIT)) { if (--timeout == 0) { return -1; // 超时 } } return 0; }

超时值怎么定?我的经验是:按最坏情况测试时间的3到5倍来设。比如手册说最长测试时间10ms,时钟100MHz,那大概100万个周期,超时设300万到500万比较稳妥。设太小会误报超时,设太大卡死时等太久。

3.4 读取结果:DONE之后做什么

DONE置位后,别急着下结论。正确的读取顺序是:

  1. 读全局状态寄存器:看pass/fail位。pass表示所有被测内存都通过,fail表示至少有一个失败。
  2. 如果fail,读失败地址寄存器:一般会记录第一个失败的地址、失败的数据位、失败的pattern类型。
  3. 如果支持诊断模式,读诊断RAM:有些MBIST控制器会把所有失败地址存到一块小RAM里,可以批量读出分析。
  4. 清除DONE和状态寄存器:为下一次测试做准备。

这里有个实操心得:先读失败地址,再清状态。有些IP在清除状态的同时会把失败地址也清掉,顺序反了就丢数据了。我踩过这个坑,后来养成习惯,读结果和清状态分成两个函数,中间加日志。

3.5 一次完整测试的时序全景

把上面的步骤串起来,一次完整的MBIST测试时序大致如下:

阶段操作关键信号注意事项
准备时钟稳定、复位释放、配置寄存器clk, rst_n等待手册规定的准备周期
清除清DONE、清状态done=0确认清除生效再继续
启动写GO位go上升沿确认跨时钟域同步
运行等待DONEdone设超时,防卡死
读取读状态、读失败地址寄存器读先读地址后清状态
收尾清DONE、清状态done=0为下次测试准备

这张表建议打印出来贴在工位上,bring-up阶段对着走,能避免大部分低级错误。

4. 用GO/DONE快速定位内存故障:实战排查思路

4.1 GO发出后DONE一直不来:五步排查法

这是最常见的故障现象。GO拉高了,等半天DONE不动。按下面五步走,基本能定位到根因:

第一步:确认GO真的到了控制器。用ILA或示波器抓控制器输入端的GO信号。如果软件写了寄存器但控制器端没看到,问题在跨时钟域同步或寄存器映射。

第二步:确认时钟在跑。抓控制器的时钟输入。如果时钟停了,控制器当然不动。常见原因是时钟门控没打开,或者时钟配置寄存器没配对。

第三步:确认复位已释放。抓复位信号。如果复位一直有效,控制器处于复位态,不响应GO。

第四步:确认配置合法。有些IP在配置非法时会拒绝启动,比如测试地址范围超出实际内存大小。读配置寄存器回读,确认写入生效。

第五步:确认没有卡在某个pattern。如果控制器支持暂停,可能卡在某个特定pattern上。读当前地址寄存器,看卡在哪个地址,再分析那个地址对应的内存单元。

我遇到过一次,五步走完发现是第二步——时钟门控没开。因为那个时钟域默认关闭,软件忘了开。这种问题看寄存器看不出来,必须抓时钟信号。

4.2 DONE来了但结果全是fail:区分真故障和假故障

DONE正常返回,但状态寄存器报fail。这时候要区分是内存真的坏了,还是测试配置有问题。常见的假故障原因:

  • 测试地址范围配错:比如实际内存只有64KB,配置成了128KB,超出部分读出来全是随机值,当然fail。
  • 时钟频率超出规格:MBIST测试频率有上限,超频跑会导致时序违例,读出错数据。
  • 电源电压不足:低电压下内存单元可能读写不稳定,尤其是SRAM。
  • 初始化未完成:有些内存需要先初始化才能测试,跳过初始化直接测会fail。
  • pattern类型不匹配:不同故障类型需要不同March算法,用错算法可能漏测或误测。

区分方法:先跑一个已知良好的小内存块。如果小内存块pass,大内存块fail,大概率是配置或电源问题;如果小内存块也fail,可能是控制器本身或时钟问题。

4.3 DONE信号抖动或多次翻转:时序问题定位

DONE抖动通常有三个原因:

  1. GO毛刺导致多次触发:前面提过,边沿触发型GO对毛刺敏感。抓GO波形,看有没有窄脉冲。
  2. DONE跨时钟域未同步:DONE从核心时钟域到APB时钟域,如果没同步,采样到亚稳态,表现为抖动。
  3. DONE清除逻辑竞争:软件清DONE和硬件置DONE同时发生,产生竞争。

排查方法:抓GO和DONE的原始波形,看抖动是否与GO相关。如果相关,查GO毛刺;如果不相关,查DONE同步。

4.4 常见问题速查表

下面这张表是我根据多个项目经验整理的MBIST GO/DONE常见问题速查表,建议收藏:

现象可能原因排查方法解决措施
GO后DONE不来时钟未开抓时钟信号打开时钟门控
GO后DONE不来复位未释放抓复位信号释放复位
GO后DONE不来配置非法回读配置寄存器修正配置
DONE来了但fail地址范围错核对内存大小修正范围
DONE来了但fail电源不足测电源电压提高电压或降频
DONE抖动GO毛刺抓GO波形加滤波或同步
DONE抖动跨时钟域未同步查同步逻辑加两级触发器
DONE读不到脉冲太窄抓DONE波形加宽脉冲或锁存
DONE一直高未清除查清除逻辑加清除操作
测试跑两遍GO重复触发抓GO边沿加边沿检测

4.5 独家避坑技巧:三个手册上不会写的经验

技巧一:GO之前先读一次状态寄存器。这一步的目的是确认上一次测试的状态已清除。如果读出来DONE还是高,说明清除没生效,这时候发GO会出问题。养成"发GO前先读状态"的习惯,能避免很多间歇性故障。

技巧二:DONE的采样用边沿检测加锁存,不要直接用电平。即使DONE是电平保持型,也建议在外部做一次边沿检测并锁存,这样软件读到的永远是"曾经完成过"的标志,不会因为DONE被意外清除而丢失完成事件。

技巧三:超时时间按测试时间的两倍设,但超时后不要立即复位。超时后先读当前地址寄存器和状态寄存器,看看卡在哪里,这些信息对定位问题非常宝贵。直接复位会丢失现场。

5. MBIST测试的进阶话题与扩展方向

5.1 多内存实例的GO/DONE管理

实际SoC里往往有多个内存实例,每个实例可能对应一个MBIST控制器,或者多个实例共享一个控制器。GO/DONE的管理方式直接影响测试时间。

常见方案有两种:

  • 串行测试:一个实例测完再测下一个。GO/DONE逐个握手。优点是简单,缺点是测试时间长。
  • 并行测试:所有实例同时启动,等所有DONE都返回。优点是快,缺点是需要更多逻辑来汇总DONE,且功耗峰值高。

我一般建议:小内存串行,大内存并行。小内存测试时间短,串行省逻辑;大内存测试时间长,并行省时间。具体阈值看项目需求,一般单个实例测试超过1ms就考虑并行。

并行测试的DONE汇总逻辑:

// 假设有4个MBIST实例 wire [3:0] done_vec; wire all_done = &done_vec; // 所有实例都完成 wire any_done = |done_vec; // 任一实例完成

用all_done触发下一步,用any_done做进度指示。

5.2 GO/DONE在低功耗测试中的特殊处理

低功耗设计里,MBIST测试往往和电源域、时钟域紧密耦合。几个特殊处理:

  • 测试期间保持电源稳定:MBIST测试时内存阵列功耗较高,如果电源管理单元误切电源,测试中断。建议测试期间锁定电源域。
  • 测试完成后自动切时钟:DONE可以触发时钟控制器,把MBIST时钟切回正常时钟,省电。
  • 分区域测试:大内存分多个区域,逐个上电测试,降低峰值功耗。每个区域有自己的GO/DONE。

这些处理需要在系统层面协调,不是MBIST控制器单独能搞定的。建议在架构阶段就把GO/DONE的联动关系定义清楚。

5.3 从GO/DONE看MBIST的可测试性设计

GO/DONE的设计质量,其实反映了整个MBIST的可测试性水平。好的设计应该做到:

  • GO/DONE可观测:能挂ILA,能引到pad
  • GO/DONE可控制:软件能发GO,能清DONE
  • GO/DONE有状态:不只是脉冲,还有状态寄存器记录历史
  • GO/DONE有保护:超时、毛刺过滤、跨时钟域同步

如果你在review别人的MBIST设计,先看GO/DONE这四点做到没有,基本能判断这个设计的成熟度。

5.4 调试工具的选择:ILA、逻辑分析仪还是示波器

抓GO/DONE波形,三种工具各有优劣:

  • ILA(集成逻辑分析仪):片上,不占引脚,能抓深层信号,但需要FPGA原型或支持ILA的芯片。适合RTL验证和FPGA原型阶段。
  • 逻辑分析仪:外部,需要引引脚,能抓多路信号,适合芯片bring-up阶段。
  • 示波器:看模拟特性,比如毛刺、建立保持时间,适合信号完整性分析。

我的建议:RTL阶段用ILA,bring-up阶段用逻辑分析仪,怀疑信号完整性时用示波器。三者配合,基本能覆盖所有调试场景。

6. 写在最后:几个我踩过的坑和真实体会

MBIST的GO/DONE看起来简单,但真正在项目里跑通、跑稳,需要关注的细节非常多。我印象最深的一次,是一个项目上电自检偶尔失败,概率大概百分之一。查了一周,最后发现是GO信号的走线太长,和一条高频时钟线平行走了一段,耦合了毛刺。解决方案是在GO上加了一个小的RC滤波,同时在RTL里加了毛刺过滤。这种问题,看代码看不出来,看寄存器也看不出来,必须抓波形。

还有一次,DONE信号在低温下偶尔读不到。常温测试一切正常,低温就出问题。最后定位是DONE的驱动能力不足,低温下驱动变弱,外部采样失败。解决方案是在DONE上加了一级缓冲。这个案例告诉我,MBIST测试不仅要看逻辑,还要看电气特性,尤其是极端工况下。

最后一个体会:GO/DONE的调试,80%的问题出在时序和同步上,20%出在配置上。所以每次遇到问题,先抓波形看时序,再看配置寄存器。这个顺序能帮你快速缩小范围。

如果你正在做MBIST相关的项目,建议把GO/DONE的握手协议画成一张时序图,贴在工位上。每次调试对着图走,比翻手册快得多。这个内容后续还可以扩展到BISR(内建自修复)的GO/DONE联动,以及MBIST和扫描测试的协同调度,有机会再展开聊。

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

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

立即咨询