1. 从一次流片翻车说起:为什么我要重写这套DFT扫描链模板
三年前接手一个数模混合SoC的DFT集成,芯片回来之后MBIST测试全过,但scan chain的shift测试死活跑不通,覆盖率卡在62%上不去。当时排查了整整两周,最后发现是scan enable信号在SDC约束里被当成普通异步信号处理了,时钟域交叉的地方没有做scan shift的时序例外。那次教训让我意识到,DFT不是后端跑完ATPG就完事的东西,scan chain的插入方式、SDC约束的写法、MBIST和scan的共享逻辑,这三者必须从RTL阶段就统一规划。
这套基于DFT的scanshift sdc模板,就是我在踩了若干次坑之后沉淀下来的一套可复用的工程框架。它解决的核心问题是:如何让scan shift阶段的时序约束、scan chain的物理插入、以及MBIST的共享总线逻辑三者不打架。适合谁看?如果你正在做数字IC的DFT集成,手上有scan chain要插、有SDC要写、有MBIST要接,而且不想在tapeout之后才发现shift mode跑不通,那这篇内容应该能帮你省下至少一轮ECO的时间。
我下面会从整体架构设计讲到具体的SDC约束写法,再到scan chain插入时的物理注意事项,最后把MBIST共享总线的坑单独拎出来说。所有内容都是基于实际项目验证过的,不是教科书上的理论推导。
2. 整体架构设计:scan shift、SDC、MBIST三者怎么协同
2.1 为什么scan shift需要独立的SDC约束文件
很多团队的做法是把functional mode的SDC直接拿过来,加几条set_case_analysis就完事。这种做法在小芯片上可能侥幸能过,但一旦设计里有多个时钟域、有generated clock、有clock gating,shift mode的时序路径和functional mode完全是两回事。
Scan shift阶段的核心特征是:所有scan flop的SE端拉高,数据从scan_in经过组合逻辑的scan mux逐级移位到scan_out。这时候时钟是慢速的shift clock,通常频率只有functional clock的十分之一甚至更低。但问题在于,scan mux插入之后,原本的functional路径被改变了,组合逻辑的延迟特性变了,clock gating的使能逻辑也可能被scan enable控制。
所以我的做法是:为shift mode单独写一份SDC,这份SDC只关心三件事——shift clock的定义、scan enable的时序例外、以及scan chain路径的false path设置。functional mode的SDC保持独立,两者通过set_case_analysis切换。
注意:不要试图用一份SDC覆盖所有mode,set_case_analysis写多了之后,PT的分析结果会变得不可信,而且debug难度指数级上升。
2.2 Scan chain的插入策略:staggered还是compressed
Scan chain的插入方式直接决定了SDC约束的复杂度。常见的两种方案:
- Staggered scan chain:所有chain共享同一个shift clock,但每条chain的scan enable错开几个周期。优点是控制简单,缺点是shift时间随chain数量线性增长。
- Compressed scan:用EDT或者类似的结构把内部chain压缩成少数几条外部通道。优点是shift时间大幅缩短,缺点是SDC约束里需要额外处理decompressor和compressor的时序。
我目前这套模板默认走的是compressed scan的路子,因为现在稍微大一点的SoC,staggered的shift时间根本受不了。但compressed scan带来的问题是:decompressor的输出到内部chain的scan_in之间,时序路径需要单独约束,不能简单当成普通数据路径处理。
2.3 MBIST与scan的共享总线设计
MBIST和scan共享总线的场景很常见,尤其是SRAM比较多的时候。共享总线的核心问题是:MBIST controller和scan chain可能同时驱动同一组总线,如果不做隔离,shift阶段的总线冲突会导致X传播,ATPG的覆盖率直接崩掉。
我的方案是在MBIST controller和scan chain之间加一层bus isolation mux,由test mode信号控制。具体来说:
| Test Mode | 总线控制权 | 说明 |
|---|---|---|
| Functional | 功能逻辑 | 正常工作时 |
| MBIST | MBIST controller | 内存测试时 |
| Scan Shift | Scan chain | 扫描移位时 |
| Scan Capture | 功能逻辑 | 扫描捕获时 |
这个表格看起来简单,但实际实现的时候,test mode信号的译码逻辑必须非常小心,否则会出现glitch导致总线短暂冲突。
3. SDC约束的核心细节:从shift clock到scan enable的完整写法
3.1 Shift clock的定义与约束
Shift clock通常是从functional clock分频或者直接由ATE提供的慢速时钟。在SDC里,我一般这样写:
# 定义shift clock create_clock -name shift_clk -period 100 -waveform {0 50} [get_ports shift_clk_pad] # 如果shift clock是从functional clock分频来的 create_generated_clock -name shift_clk_int \ -source [get_ports func_clk_pad] \ -divide_by 8 \ [get_pins u_clock_div/clk_out]这里的关键点是:shift clock的period要设得足够宽松,通常我设成functional clock的8到16倍。为什么?因为shift阶段不需要考虑性能,只需要保证时序能过。设得太紧,PT会报一堆setup violation,而这些violation在shift mode下根本没有意义。
但也不能设得太松,否则hold violation会漏掉。我的经验值是:shift clock period = functional clock period × 10,这个值在大多数工艺节点下都能兼顾setup和hold的检查。
3.2 Scan enable的时序例外设置
Scan enable是shift mode下最容易被忽略的信号。在functional mode下,SE是0,scan mux选择功能路径;在shift mode下,SE是1,scan mux选择scan路径。问题在于:SE信号本身也需要满足时序要求,尤其是当SE需要穿过多个时钟域的时候。
我的做法是:
# SE在shift mode下是静态信号,设为false path set_false_path -from [get_ports scan_enable_pad] -to [get_pins u_scan_mux/se] # 但如果SE需要跨时钟域同步,则不能简单设false path # 需要根据同步器的结构单独约束 set_max_delay 2.0 -from [get_pins u_se_sync/q] -to [get_pins u_scan_mux/se]这里有个坑:如果SE直接设成false path,PT不会检查SE到scan mux的时序,但实际硅片上如果SE的skew太大,会导致部分flop已经进入shift mode而另一部分还在capture mode,结果就是shift出来的数据全是错的。所以对于跨时钟域的SE,我一般用set_max_delay而不是set_false_path。
3.3 Scan chain路径的false path与multicycle path
Scan chain的shift路径是从一个flop的Q经过scan mux到下一个flop的D。这条路径在shift mode下是真实存在的,但在functional mode下是false path。所以SDC里需要这样写:
# Functional mode下,scan路径是false path set_false_path -from [get_pins u_scan_mux/scan_in] -to [get_pins u_flop/d] # Shift mode下,scan路径是真实路径,但需要multicycle set_multicycle_path 2 -setup -from [get_clocks shift_clk] -to [get_clocks shift_clk] set_multicycle_path 1 -hold -from [get_clocks shift_clk] -to [get_clocks shift_clk]为什么shift路径要设multicycle?因为shift clock的周期已经足够长,设multicycle是为了给PT更多的余量,避免因为OCV或者clock skew导致误报。但hold的multicycle要设成setup-1,这是基本规则。
实操心得:set_multicycle_path的hold值一定要比setup小1,否则hold检查会跑到下一个周期去,导致真正的hold violation被掩盖。
3.4 Clock gating在shift mode下的处理
Clock gating是shift mode下另一个容易出问题的地方。Functional mode下,clock gating根据功能逻辑决定是否关断时钟;shift mode下,所有clock gating必须强制打开,否则scan chain中间断掉,shift数据传不下去。
SDC里的写法:
# Shift mode下强制打开所有clock gating set_case_analysis 1 [get_pins u_clock_gate/en]但这里有个细节:clock gating的enable信号可能来自功能逻辑,如果直接set_case_analysis 1,PT会忽略功能逻辑的约束。所以更好的做法是用set_clock_gating_check:
set_clock_gating_check -setup 0.5 -hold 0.3 [get_clocks shift_clk]这样PT会检查clock gating的setup和hold,而不是简单地把enable拉高。
4. Scan chain插入的实操流程与物理注意事项
4.1 从RTL到netlist的scan插入流程
Scan chain的插入通常在后端综合之后、APR之前进行。我的流程是这样的:
- RTL阶段:在RTL里预留scan mux和scan chain的接口,用
ifdef SCAN或者类似的宏控制。 - 综合阶段:用DFT compiler或者类似工具插入scan chain,生成带scan的netlist。
- SDC生成:根据scan chain的结构,生成shift mode的SDC。
- APR阶段:把scan chain的物理连接做进去,注意scan chain的走线要尽量短,避免跨die。
这里的关键点是:scan chain的插入顺序要和SDC的生成顺序一致。如果先插了scan chain再写SDC,SDC里的get_pins可能找不到对应的pin;如果先写了SDC再插scan chain,SDC里的约束可能不完整。
4.2 Scan chain的物理连接注意事项
Scan chain的物理连接有几个硬性要求:
- Scan chain的走线长度要匹配:同一条chain上的flop,scan_in到scan_out的走线长度差异不能太大,否则shift阶段的skew会导致hold violation。
- Scan chain要避免跨power domain:如果一条chain上的flop分布在不同的power domain,shift阶段如果某个domain断电,整条chain就断了。
- Scan chain的scan_out要接到pad或者compressor:如果是compressed scan,scan_out要接到compressor的输入;如果是staggered scan,scan_out要接到pad。
我踩过的一个坑是:scan chain跨了power domain,结果shift测试时某个domain的电源没上,整条chain的数据全是X。后来改成每个power domain单独一条chain,问题才解决。
4.3 Scan chain的时序验证方法
Scan chain插入之后,必须做时序验证。我的验证流程是:
- PT shift mode分析:用shift mode的SDC跑PT,检查setup和hold。
- Formality验证:用Formality检查scan插入前后的逻辑等价性,确保scan mux没有改变功能逻辑。
- ATPG覆盖率检查:跑ATPG,检查scan chain的覆盖率是否达到预期。
这里有个经验:PT shift mode分析的时候,要把functional mode的SDC和shift mode的SDC分开跑,不要混在一起。混在一起跑的话,PT会同时分析两种mode的路径,结果就是一堆false violation,根本没法debug。
5. MBIST共享总线的坑与解决方案
5.1 MBIST与scan的总线冲突场景
MBIST和scan共享总线的场景下,总线冲突主要发生在两个时刻:
- MBIST测试期间:MBIST controller驱动总线,scan chain处于idle状态。
- Scan shift期间:scan chain驱动总线,MBIST controller处于idle状态。
如果这两个时刻的总线控制权没有正确切换,就会出现总线冲突。冲突的后果是:总线上出现X,X传播到scan chain里,导致shift出来的数据全是错的。
5.2 Bus isolation mux的设计与约束
Bus isolation mux的设计很简单,就是一个2选1的mux,由test mode信号控制。但SDC约束需要特别注意:
# MBIST mode下,总线由MBIST controller驱动 set_case_analysis 1 [get_pins u_bus_mux/sel] # Scan shift mode下,总线由scan chain驱动 set_case_analysis 0 [get_pins u_bus_mux/sel]这里的关键是:test mode信号的译码逻辑必须无glitch。如果译码逻辑有glitch,总线会在两个驱动源之间短暂切换,导致冲突。我的做法是用one-hot编码的test mode信号,并且加一个同步器。
5.3 MBIST与scan的时钟域协调
MBIST和scan可能使用不同的时钟。MBIST通常用functional clock或者专门的MBIST clock,scan用shift clock。如果这两个时钟不同步,总线切换的时候会出现亚稳态。
解决方案是:在总线切换之前,先停掉当前时钟,等总线稳定之后再切换。具体实现是在test mode信号上加一个handshake逻辑,确保时钟停止和总线切换的顺序正确。
注意:MBIST和scan的时钟域协调是DFT集成里最容易出问题的地方,建议在RTL阶段就做好时钟切换的逻辑,不要等到后端再补。
6. 常见问题与排查技巧实录
6.1 Shift测试跑不通的排查思路
Shift测试跑不通是最常见的问题,排查思路如下:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 所有chain都fail | shift clock没接对 | 检查shift clock的pad和SDC定义 |
| 部分chain fail | scan chain断了 | 用chain diagnosis定位断点 |
| 数据全X | 总线冲突或power domain问题 | 检查bus isolation mux和power domain |
| 数据错位 | SE skew太大 | 检查SE的时序约束和物理走线 |
我遇到最多的是数据全X的情况,十有八九是总线冲突或者某个power domain没上电。排查的时候先用chain diagnosis定位到具体的flop,然后检查那个flop的power和总线连接。
6.2 SDC约束的常见错误
SDC约束的常见错误包括:
- set_false_path用错地方:把真实的时序路径设成了false path,导致PT不检查,硅片上出现violation。
- set_multicycle_path的hold值设错:hold值设成了setup值,导致hold violation被掩盖。
- set_case_analysis冲突:同一个信号被设了多个case analysis值,PT的行为不可预测。
我的经验是:SDC写完之后,一定要用PT的report_timing检查关键路径,不要只看summary。summary里的violation数量可能是0,但关键路径的violation可能被false path掩盖了。
6.3 ATPG覆盖率上不去的调试方法
ATPG覆盖率上不去,通常是因为:
- scan chain的X传播:某个flop的输出是X,导致下游的flop无法被测试。
- clock gating没打开:shift mode下clock gating没打开,scan chain中间断了。
- bus conflict:总线冲突导致X传播。
调试方法是:先用ATPG工具生成X-mask,看看哪些flop的输出是X,然后逐个排查X的来源。如果是clock gating的问题,检查SDC里的set_case_analysis;如果是bus conflict,检查bus isolation mux的控制逻辑。
6.4 实操避坑清单
最后整理一份避坑清单,都是我在实际项目里踩过的坑:
- Shift clock的period不要设得太紧,否则PT会报一堆无意义的setup violation。
- SE的跨时钟域路径不要简单设false path,用set_max_delay更安全。
- Scan chain不要跨power domain,每个domain单独一条chain。
- Bus isolation mux的test mode信号要无glitch,用one-hot编码加同步器。
- MBIST和scan的时钟切换要有handshake,不要直接切。
- SDC写完之后要用report_timing检查关键路径,不要只看summary。
- ATPG覆盖率上不去的时候,先查X传播,再查clock gating和bus conflict。
这套模板我在三个项目上用过,从55nm到16nm都有,基本没再出现过shift测试跑不通的情况。当然每个项目的具体细节不一样,SDC的约束值需要根据工艺和时钟频率调整,但整体框架是通用的。如果你正在做DFT集成,希望这些经验能帮你少走点弯路。