Tessent Mbist时钟架构与SDC约束实战:三个时钟域与典型违例排查
2026/9/13 11:55:34 网站建设 项目流程

做DFT这些年,Tessent Mbist陆陆续续跟了好几个项目。最早用的时候,我其实有点小看时钟这部分——Mbist不就是把memory的地址线、数据线和控制信号接到控制器上,约束管好BIST_CLK和TCK不就行了?后来项目跑到CTS阶段,时钟树一直balance不上,后端的兄弟把时序报告甩过来,我看着Mbist Controller到Memory那一大片红的路径,才意识到问题没有想象中那么简单。时钟架构没吃透,SDC就写不到点子上,后面时序收敛、pattern仿真、Silicon调试全都要跟着遭殃。这篇笔记算是一个系统性的梳理,把Mbist时钟架构和SDC约束里最容易踩坑的部分整理出来。标题标了-01,这一篇先把时钟域和SDC结构讲透,后面再聊Tessent Mbist的pattern生成和故障覆盖率相关的东西。

1. Mbist身边有三个“时钟世界”在同时运转

Tessent Mbist插入完成后,网表里从来不存在“一个测试时钟”这种简单局面。从约束和实现角度看,至少有三个时钟世界需要在SDC里被完整描述:TCK、BIST_CLK,以及被测Memory的时钟。它们之间是什么关系,直接决定了SDC怎么写。我先把这三个时钟的身份和用途捋一遍。

时钟来源典型频率用途时钟域属性
TCK外部JTAG测试时钟引脚10~50MHz量级TAP状态机、Mbist指令/数据寄存器配置独立异步域
BIST_CLKSoC测试时钟或PLL50~200MHz,取决于工艺与memory规格Mbist Controller内部状态机、地址/数据生成、驱动memory collarMbist信号主时钟域
Memory功能时钟内部PLL或分频器功能设计决定功能模式下memory的读写功能时钟域

1.1 低速TCK:只管配置,不管测试

TCK是IEEE 1149.1标准里TAP状态机的时钟,Tessent Mbist的控制器也是挂在JTAG链上的。它的任务是跑测试之前,把指令和配置数据通过TDI扫进Mbist Controller的指令寄存器和数据寄存器,让控制器知道接下来要测哪些memory、跑哪套算法、需要多长时间。等整个配置流程结束,真正开始执行BIST时,TCK基本就退到一边了,最多通过TAP再去轮询BIST_DONE/BIST_FAIL这些状态位。

TCK驱动的逻辑面积很小,也就是TAP那组状态机和几个移位寄存器,所以CTS对它没有任何压力。麻烦的地方在于,TCK域和BIST_CLK域之间没有同步保证,SDC里必须把这两个时钟声明为异步关系。否则工具会默认它们相位相关,然后去分析那些经过同步器的路径,既报一堆没有意义的违例,又拖慢运行时间。另一个容易漏的是TMS信号,它在TCK上升沿采样,如果要做严格的input delay约束,TMS的路径也要定义到TCK时序下。不过很多项目里TMS直接走false path或者只约束input interface,这点按公司flow定即可。

1.2 BIST_CLK:Mbist真正的主时钟

BIST_CLK才是Mbist执行阶段的主角。Mbist Controller内部的地址生成器、数据生成器、背景序列发生器、计数器、比较状态机,全部由BIST_CLK驱动。一边生成地址和数据,一边往memory的collar灌激励,同时把memory输出的数据抓回来和期望值比较。可以说,整个Mbist算法的每一步节奏都由BIST_CLK决定。

SDC里BIST_CLK是Mbist所有同步路径的time基准。Controller内部寄存器到collar里寄存器的路径要检查setup/hold,Controller输出地址/数据/控制信号到memory address/data pin的路径也要基于BIST_CLK做检查。实际项目里这块路径往往是高扇出重灾区,一条地址线可能同时挂到几十个memory的collar上,工具在做时序优化时很容易在这里形成拥塞。约束阶段至少得让工具正确认识这些路径是同步的,别误标成false path。

1.3 Memory时钟:功能时钟和BIST时钟的交接点

被测memory在功能模式下跑功能时钟,在Mbist模式下必须切换到BIST_CLK。这个切换一般靠DFT时钟Mux完成,Mux的输出直接驱动memory的clock pin。Collar部位可能还会再嵌套一级门控逻辑,用Controller产生的clock enable来控制memory时钟的开闭。

就是这里,SDC约束真正的难点浮出水面:两个时钟物理上都连着同一个clock pin,但它们不会同时有效。工具必须知道当前看哪条路径,否则CTS会在memory clock pin上做出完全错误的balance策略——它可能试图把功能时钟和BIST_CLK两个输入都平衡到零延迟,这在物理上根本不现实。后面在H2 2里我会细讲这种时钟切换在SDC里怎么处理。

三个时钟世界的概念捋清楚之后,Mbist的SDC约束就不再是一堆孤立命令了,而是围绕“哪些路径真的同步、哪些路径天然异步、哪些时钟物理互斥”这三个问题去组织。

2. 从时钟拓扑到SDC落点:核心约束冲突在哪里

时钟架构画出来是一张拓扑图,但SDC里每个约束最终都要对应到具体的端口、引脚和路径类别。这一节我把我理解里的核心冲突点展开讲。

2.1 数据路径的两种类型:跨时钟路径和同源同步路径

Mbist相关的数据路径可以粗暴分成两类。第一类是TCK域与BIST_CLK域之间的跨时钟路径,比如TAP写入的配置寄存器,在Mbist被触发启动时被内部逻辑采样。这类路径在设计里通常有同步器或握手逻辑保护,SDC里把它们声明为异步即可,不需要认真做时序收敛,也收敛不住。第二类是BIST_CLK域内部的同步路径,从Mbist Controller的寄存器出发,经过组合逻辑,到达memory collar里的寄存器或者memory本身。这类路径在Mbist模式下同源,必须让工具完整做setup和hold检查。

很多人刚接触Mbist约束时,容易把Controller到memory的路径当成普通异步路径处理,随手set_false_path,结果就是Silicon上一跑Mbist就挂。反过来说,也不能把这些路径全部交给工具不管。地址线、数据线、控制线的扇出系数非常大,如果不给足够的时序余量,PR工具根本不知道要在中间插入多少buffer来修复setup,最后可能用面积换时序,把整块布局挤得乱七八糟。

2.2 时钟Mux的三种处理套路

Memory时钟在做功能时钟和BIST_CLK切换时,SDC处理手法大致有三条路,实际项目里经常混合使用。

第一种是set_case_analysis,也是我最常用的方式。在测试模式约束文件里固定mbist_en为1,工具分析时只会沿着BIST_CLK这条通路看,功能时钟那条通路被完全disabled。反过来做功能约束时固定mbist_en为0,只看功能时钟。这种方法的优点是简单、运行快,缺点是需要保证case_analysis设置和实际测试激励一致,否则分析的结果和Silicon行为对不上。

第二种是set_clock_groups -physically_exclusive。把功能时钟和BIST_CLK划成物理互斥的两个组,工具知道这两个时钟不会同时活动,不去分析它们之间的路径。这种做法在综合和PR阶段非常常见,尤其是存在大量时钟切换点时,比逐个set_case_analysis要干净。但要注意“physically_exclusive”和“logically_exclusive”是有区别的。如果两个时钟只是逻辑上不会同时有效,物理上却可能因为Mux延时产生glitch,那就用logically_exclusive。Clock Mux输出端这两个时钟源通常是物理互斥的,因为Mux同一时刻只能选中一个输入。

第三种是在Mux输出端定义generated clock,把Mux两个输入时钟和输出时钟的关系显式写出来,模拟真实的Mux行为。这种描述最细致,工具能同时看到两条时钟通路,但约束代码量明显增加,而且对网表的完整性和综合工具支持程度要求更高。如果网表里还有boundary logic没有rename干净,很容易在这里翻车。

2.3 并行Memory组的时钟使能逻辑

Tessent Mbist支持把多个memory划分成不同的并行组,同一组共用一个时钟使能信号,组内各memory的读写同步进行。并行组的数量越多,测试时间越短,但瞬时翻转功耗也越高。从时钟角度看,每个memory clock pin上的门控逻辑都必须满足时序。Controller会把clock enable信号发给每个collar,这个enable信号在collar内部和BIST_CLK做门控组合。如果enable的setup/hold违例,ICG输出会出现毛刺,整组memory的数据比较全部作废。

SDC层面要注意的是,所有并行组的clock enable路径都必须落在BIST_CLK域里。工具需要完整检查这些enable信号到ICG的setup/hold。有些流程里,后端会把这些ICG当成普通时钟门控单元处理,默认加clock gating check,这没有问题。但如果你在约束里给相关路径误加了false path,那就等于放过了所有ICG检查,Silicon上必炸。

3. Mbist SDC约束参考模板与逐行解释

理论讲再多,不如直接给一份能落地的模板。下面这份SDC是我在项目里常用的Mbist约束骨架,端口名基于常见命名,具体以Tessent插入后生成的网表为准。

# ============================================= # Mbist SDC约束参考模板 # 适用于Tessent Mbist插入完成后的网表 # ============================================= # 1) 主时钟定义 create_clock -name tck -period 100.0 [get_ports tck] create_clock -name bist_clk -period 20.0 [get_ports bist_clk] create_clock -name func_clk -period 10.0 [get_pins u_pll/clk_out] # 2) 测试模式信号固定 set_case_analysis 1 [get_ports mbist_en] set_case_analysis 0 [get_ports scan_enable] set_case_analysis 0 [get_ports bist_rst_n] set_case_analysis 1 [get_ports tck_enable] # 3) 时钟域关系 set_clock_groups -asynchronous \ -group {tck} \ -group {bist_clk} set_clock_groups -physically_exclusive \ -group {func_clk} \ -group {bist_clk}

3.1 时钟定义:给三个时钟一个合法身份

第一步先把BIST_CLK、TCK、功能时钟全部定义成主时钟。BIST_CLK和TCK通常直接从chip端口进来,用create_clock挂在port上。功能时钟一般从PLL输出pin上抓,这时要用get_pins抓PLL内部的clk_out,不要挂在PLL的input端口上,否则会产生很多不必要的generated clock传播。

period怎么定?TCK按照JTAG实际工作频率留一点余量,比如实际跑10MHz,约束给100ns。BIST_CLK的周期要和待测memory的规格对齐,但不是简单照搬功能时钟频率。Mbist测试要遍历大量pattern,动态功耗比功能模式高很多,频率拉太高会导致电压降过大。我自己习惯把BIST_CLK约束到功能时钟频率的一半到三分之一,除非memory规格明确说可以跑满速,并且电源仿真验证过。

3.2 模式信号控制:set_case_analysis决定工具看哪条路

模板里第二段是测试模式信号固定。mbist_en为1,表示当前视角是Mbist测试模式,工具自动沿着BIST_CLK路径分析。scan_enable为0,表示在Mbist模式下不关心扫描移位路径。tck_enable为1,表示TCK时钟通路在测试期间有效。这些信号的有效电平完全取决于设计命名和逻辑极性,套模板时务必对着RTL或者Tessent生成的网表确认。

这种写法有个好处,就是同一份网表可以在不同模式约束下分别做综合分析。mbist_en为0、scan_enable为1的时候,工具处理的是扫描测试模式视角。PR阶段多模式分析会同时读入好几个约束文件,每个约束文件对应一种工作模式。Mbist约束文件只是其中之一,case_analysis设置不干净,多模式分析时工具就会产生冲突,报出一堆UNCONSTRAINED_PATH或者时钟冲突。

3.3 时钟组关系:把异步和互斥讲清楚

模板里第三段是时钟组关系。TCK和BIST_CLK之间是异步关系,因为JTAG配置过程与BIST执行过程之间没有固定的相位关系,中间有同步器隔着,也可能在时间上完全错开。set_clock_groups -asynchronous直接告诉工具不要分析这两个域之间的路径。

功能时钟和BIST_CLK之间用physically_exclusive。原因是它们通过同一个Mux输出到memory clock pin,物理上不可能同时出现。这里特别提醒,不要把这个关系误写成asynchronous。存储器功能时钟和BIST_CLK虽然是不同源,但它们最终会汇聚到同一个时钟Mux的输出点,在做memory接口路径分析时,工具需要把它们当成互斥时钟而不是异步时钟,否则约束意图就变了。

4. 从违例报告反推问题:三种典型Mbist时序灾难

约束写完了,时序报告里还是会出问题。下面这几种违例我在不同项目里都遇过,排查思路和修复方向比较有代表性。

4.1 Controller到Collar的路径大面积违规

典型现象:setup violation集中在Mbist Controller输出到memory collar输入这一片,而且WNS差得离谱,不是几百ps的小违例,可能是几个ns。打开report_timing看路径,大多是控制器内部寄存器经过高扇出组合逻辑到达collar的地址/数据引脚。

排查链路一般是这样的:先看时钟skew。如果BIST_CLK在Controller端和memory端skew很大,第一时间怀疑CTS策略有没有把Mbist时钟树单独处理好。再看路径组合逻辑级数和cell驱动强度。地址线扇出大,工具在修复setup时可能已经插了很多buffer,但插buffer本身又增加了cell delay,形成恶性循环。

修复方向通常有三个:一是优化CTS,把Mbist时钟树单独balance,减少skew对setup的消耗;二是在RTL或网表阶段对高扇出信号做reg复制或者手动插入buffer tree,降低单一驱动点的负载;三是如果确认测试频率有冗余,适当放宽BIST_CLK周期,先让时序收敛再考虑提速。

4.2 ICG单元的hold违规为什么难修

第二种典型问题是collar内部ICG单元的hold violation。和普通寄存器路径不同,ICG单元同时有clock输入和enable输入,hold检查要求enable信号在clock沿之后继续保持一段时间不变化。如果BIST_CLK到ICG的clock pin和enable pin路径延时差太多,hold就很难满足。

这类违例难修是因为它往往出现在门控逻辑上,后端工具不太容易自动插buffer修复,因为修复位置选择不当会影响时钟gating check。实际项目中我见过因为ICG hold违例导致Mbist偶发失败的情况,Silicon上不是每次都挂,但良率下来一排查,就是这处在临界状态。

修复上优先考虑在collar内的ICG前面加lockup latch,或者调整时钟树让ICG的clock到得晚一点。如果设计规范允许,也可以在ICG enable路径上加multicycle path约束,但我不建议轻易用,因为multicycle path的本质是放宽检查条件,一旦Silicon上时序裕量不够,故障会以很低概率出现,很难复现。

4.3 复位释放问题:Mbist一启动就FAIL

第三种情况最让人头疼:PR时序报告干干净净,仿真也没问题,结果Silicon上一跑Mbist,BIST_FAIL信号直接拉高,从头到尾没有一次pass。很多人第一时间怀疑memory坏了,其实很多时候是复位释放没处理好。

Mbist Controller在工作前需要bist_rst_n完成释放,这个释放动作必须和BIST_CLK沿有确定的时序关系。如果复位释放电路只是简单把外部reset反相后接到Controller,释放时刻可能离BIST_CLK的有效沿太近,导致Controller里部分寄存器采样到不确定值,状态机直接乱掉,测试自然全fail。

正确的做法是给Mbist Controller加异步复位同步释放电路,让复位信号在BIST_CLK域内经过两级触发器同步后再释放。SDC层面不要对这条路径随便设false path,应该让工具检查recovery和removal。如果工具默认没查,可以用set_recovery_checkset_removal_check显式打开,确保复位释放沿和BIST_CLK之间有足够的时序裕量。

下面这个表格是我整理的常见Mbist时序问题排查速查表,方便对照:

现象大概率原因排查方向修复手段
Controller到Collar setup违例时钟skew过大、扇出过高report_clock_timing看skew;report_timing看组合逻辑级数单独balance Mbist时钟树;reg复制;降BIST_CLK频率
ICG hold违例enable路径与clock路径延时差过大report_timing -through ICG的enable pin加lockup latch;调整时钟树相位;谨慎放宽约束
Silicon上Mbist全FAIL复位释放不规范、跨域路径被误标false path检查复位同步器;检查约束里是否有误设的set_false_path加异步复位同步释放;纠正约束文件

5. 被项目反复“毒打”后留下的几条经验

最后聊几条纯经验的东西。这些内容在Tessent官方文档里不一定找得到,但每个经历过Mbist项目的人应该都懂。

5.1 频率别总想着往上顶

Mbist测试的核心价值是尽量短时间把memory覆盖完,所以有人习惯把BIST_CLK顶到和功能时钟一样高,觉得测得更快更充分。这个想法有问题。Mbist执行时Controller、collar、memory三个部分同时翻转,动态功耗远高于普通功能模式。我在一个项目里把BIST时钟从50MHz提到80MHz,功耗仿真直接超了预算,低压测试时Mbist各种偶发fail。后来老老实实回到66MHz,一次通过。选频率要结合功耗分析和memory的AC spec,别让测试本身成为压垮电源的最后一根稻草。

5.2 CTS阶段单独处理Mbist时钟树

如果PR工具允许,尽量在CTS时把Mbist相关的时钟树设成独立的balance group。默认情况下,工具会把BIST_CLK和功能时钟放在一起做全局优化,结果就是memory clock pin上的compromise。单独balance之后,Controller到memory的skew通常会好很多。不要觉得这是后端的事,DFT工程师完全可以在SDC里通过set_clock_tree_options或者set_clock_groups把自己的意图表达清楚,后端同事会更感谢你。

5.3 每次约束改动都要做时序回归

Mbist约束文件不是写完就完事的。RTL迭代、Tessent重新插入collar、Memory IP更换版本,这些都会导致总线命名变化或路径层级变化,很容易让SDC里的get_pins和get_ports失效。我在一个项目里就遇到过Tessent升级后,mbist_en端口名字从mbist_en变成了mbist_enable,旧约束文件里的set_case_analysis静默失效,工具压根没me到这两个信号,多模式检查也没报错,最后在PR颜色分析时才发现功能路径和测试路径撞在一起了。

所以每次改完约束,至少要做两件事:第一,用report_clock -skew确认三个时钟域都还存在且关系正确;第二,抽几条典型Mbist路径检查约束是否真的作用到了预期pin上。跑一遍report_analysis_metrics或者report_qor看Mbist路径的WNS/TNS有没有突变。这个习惯养成之后,省掉的debug时间远超写约束本身花的时间。

这一篇先记录到这里。回头看我自己的过程,Mbist的时钟问题没有特别神秘,只要把TCK、BIST_CLK、Memory时钟三个域想清楚,SDC里该声明的异步声明掉、该设的case_analysis设好、该检查的ICG和复位路径检查到位,时序收敛是水到渠成的事。下一篇我打算接着写Tessent Mbist完成插入后,怎么跑pattern生成和覆盖率分析,顺便聊聊BIST接口信号在Silicon上怎么量。如果你也在项目里被Mbist时钟树折磨过,欢迎在评论区聊聊各自的踩坑经历。

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

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

立即咨询