第三章:扫描链设计——扫描链插入、压缩技术、EDT原理
各位同学,今天我们来聊聊扫描链设计。说实话,这是DFT里最基础也最核心的一块。我刚开始做芯片测试那会儿,觉得扫描链不就是把寄存器串起来嘛,有什么难的?结果第一次流片回来,测试覆盖率惨不忍睹,老板差点让我去产线拧螺丝。从那以后,我再也不敢小看扫描链设计了。
3.1 扫描链插入——把普通寄存器变成测试利器
扫描链的本质是什么?说白了,就是把芯片里所有的时序单元(寄存器)串成一条或几条链子。正常工作时,这些寄存器各司其职;测试模式下,它们就变成了一个巨大的移位寄存器,用来灌入测试向量和读出响应。
我个人习惯把扫描链插入分成三步走:
- 扫描替换:把普通D触发器换成带扫描功能的扫描触发器
- 链连接:按照设计规则把这些扫描触发器串起来
- 端口分配:分配扫描输入、扫描输出、扫描使能等端口
关键点:扫描链插入不是简单的串一串就完事。你想想看,如果随便串,时序可能崩掉,面积可能爆炸。我见过一个项目,工程师图省事把所有寄存器串成一条链,结果链长超过10万级,测试时间长得离谱,最后不得不重做。
这里给个简单的扫描链插入脚本示例(Synopsys DFT Compiler):
# 设置扫描模式
set_scan_configuration -chain_count 8
set_scan_configuration -clock_mixing no_mix
# 定义扫描端口
create_port -direction in scan_in[0:7]
create_port -direction out scan_out[0:7]
create_port -direction in scan_enable
# 插入扫描链
insert_dft
# 报告扫描链信息
report_scan_path -view existing
嗯,这里要注意:扫描链的数量选择是个权衡。链数越多,测试时间越短,但需要的测试引脚也越多。我一般建议根据芯片的IO引脚余量和测试时间要求来定,通常8到32条链比较常见。
3.2 扫描压缩技术——用更少的向量测更多的故障
为什么要做扫描压缩?你想想看,一颗上亿门的芯片,如果每条链都老老实实灌向量,测试时间可能长达几分钟甚至十几分钟。量产测试时,一颗芯片测几分钟,那成本就上天了。
扫描压缩的核心思想很简单:在芯片内部增加解压缩和压缩逻辑。测试时,外部输入少量压缩后的向量,芯片内部解压后灌入扫描链;响应数据从扫描链出来后再压缩,输出到外部。
我的经验:压缩比通常能做到10:1到50:1。但别贪心,压缩比太高会导致覆盖率下降。我曾经在一个项目中尝试100:1的压缩比,结果覆盖率掉了5个点,最后不得不降回30:1。
常见的压缩技术有几种:
| 压缩技术 | 原理 | 压缩比 | 适用场景 |
|---|---|---|---|
| XOR压缩 | 多条链输出做异或 | 2:1 ~ 8:1 | 小规模芯片 |
| MISR压缩 | 多输入特征寄存器 | 10:1 ~ 30:1 | 中等规模 |
| EDT压缩 | 确定性测试+解压缩 | 20:1 ~ 100:1 | 大规模SoC |
我个人比较推荐EDT方案,原因后面会讲。但如果你做的是小芯片,XOR压缩就够用了,别杀鸡用牛刀。
3.3 EDT原理——嵌入式确定性测试的魔法
EDT,全称Embedded Deterministic Test,是Mentor(现Siemens EDA)推出的一项技术。它的核心思想是:在芯片内部嵌入一个解压缩器,把外部输入的少量测试数据解压成完整的扫描链数据。
为什么会这么有效?因为测试向量其实有大量冗余。你想想看,一条扫描链上几万个寄存器,但真正需要关心的故障点可能只有几百个。EDT就是利用这个特性,只传输那些"有信息量"的数据。
EDT的工作流程:
- ATE(自动测试设备)发送压缩后的测试数据
- 芯片内部的解压缩器(Decompressor)将数据展开
- 展开后的数据灌入扫描链
- 响应数据从扫描链输出
- 压缩器(Compactor)将响应压缩后送回ATE
这里有个关键点:解压缩器必须是确定性的。也就是说,同样的输入必须产生同样的输出。这样才能保证测试的可重复性。EDT用的是线性反馈移位寄存器(LFSR)加上一些组合逻辑来实现确定性解压缩。
// EDT解压缩器简化模型
// 输入:compressed_data[7:0]
// 输出:scan_chain_data[63:0]
module edt_decompressor (
input clk,
input rst_n,
input [7:0] compressed_in,
output [63:0] scan_data_out
);
reg [15:0] lfsr;
wire [63:0] expanded;
// LFSR更新逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
lfsr <= 16'hACE1;
else
lfsr <= {lfsr[14:0], lfsr[15] ^ lfsr[13] ^ lfsr[12] ^ lfsr[10]};
end
// 解压缩:LFSR状态 + 压缩数据 -> 展开数据
assign expanded = {lfsr, compressed_in, 40'h0};
// 输出到扫描链
assign scan_data_out = expanded;
endmodule
避坑指南:我曾经在一个项目中遇到EDT解压缩器出现"线性依赖"问题。简单说就是某些故障模式在解压缩后变成了相同的向量,导致无法区分。解决方法是增加一些非线性逻辑,比如在LFSR输出加一些AND/OR门。这个坑我踩过,你们要记住。
3.4 扫描链设计的实战要点
好了,理论讲完了,我来总结几个实战中必须注意的点:
- 时钟域处理:不同时钟域的寄存器不能串在同一条链上,否则跨时钟域采样会出问题。我一般每个时钟域单独建链。
- 扫描使能信号:这个信号必须干净,不能有毛刺。我习惯在扫描使能上加两级同步器再加一个毛刺滤波器。
- 测试覆盖率目标:量产测试通常要求>95%的 stuck-at 故障覆盖率。如果达不到,先检查是不是有黑盒模块或者异步电路没处理好。
- ATE向量深度:EDT虽然压缩了数据,但ATE的向量深度还是有限制的。我建议在流片前做一次ATE仿真,确保向量能装得下。
我的小技巧:在做扫描链插入之前,先跑一遍DFT规则检查。很多工具都有这个功能,比如Synopsys的DFT_drc。提前发现规则违例,比后面返工省事多了。
最后说一句,扫描链设计不是一锤子买卖。我每次流片回来,都会先跑一遍扫描链测试,确认链本身没问题,再去做ATPG。如果链都坏了,后面的测试全是白费功夫。嗯,今天就到这里,下节课我们讲ATPG——自动测试向量生成,那才是真正烧脑的部分。