第三章:扫描链设计——扫描链插入、压缩技术、EDT原理

各位同学,今天我们来聊聊扫描链设计。说实话,这是DFT里最基础也最核心的一块。我刚开始做芯片测试那会儿,觉得扫描链不就是把寄存器串起来嘛,有什么难的?结果第一次流片回来,测试覆盖率惨不忍睹,老板差点让我去产线拧螺丝。从那以后,我再也不敢小看扫描链设计了。

3.1 扫描链插入——把普通寄存器变成测试利器

扫描链的本质是什么?说白了,就是把芯片里所有的时序单元(寄存器)串成一条或几条链子。正常工作时,这些寄存器各司其职;测试模式下,它们就变成了一个巨大的移位寄存器,用来灌入测试向量和读出响应。

我个人习惯把扫描链插入分成三步走:

  1. 扫描替换:把普通D触发器换成带扫描功能的扫描触发器
  2. 链连接:按照设计规则把这些扫描触发器串起来
  3. 端口分配:分配扫描输入、扫描输出、扫描使能等端口

关键点:扫描链插入不是简单的串一串就完事。你想想看,如果随便串,时序可能崩掉,面积可能爆炸。我见过一个项目,工程师图省事把所有寄存器串成一条链,结果链长超过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的工作流程

  1. ATE(自动测试设备)发送压缩后的测试数据
  2. 芯片内部的解压缩器(Decompressor)将数据展开
  3. 展开后的数据灌入扫描链
  4. 响应数据从扫描链输出
  5. 压缩器(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——自动测试向量生成,那才是真正烧脑的部分。