4、设计可测试性(DFT):测试点设计、边界扫描、内建自测试
各位做系统集成的兄弟,咱们聊聊DFT。说白了,就是你在设计电路板的时候,就得提前想好「这玩意儿将来怎么测」。别等到产线上一堆板子堆在那儿,测试工位卡住了,你才拍大腿——那时候就晚了。
我这些年经手的彩超项目,从16通道到256通道的波束合成板,DFT做得好不好,直接决定了量产爬坡的速度。有些板子设计时没留测试点,产线工人得拿示波器探头在BGA底下戳,那画面……嗯,不提也罢。
4.1 测试点设计:给产线留条活路
测试点设计,核心就一句话:让测试探针能碰到该碰的地方。但实际做起来,坑多得很。
关键原则:
- 覆盖率优先:每个关键节点(电源、时钟、数据总线、控制信号)都要有测试点
- 物理可达:测试点直径建议≥0.8mm,间距≥1.27mm,别让探针打架
- 信号完整性:高速信号(比如LVDS、DDR)的测试点要加在stub上,别直接打断走线
- 分组布局:把同一功能模块的测试点聚在一起,方便飞针测试或针床夹具设计
我记得有一次,一个同事设计的128通道模拟前端板,测试点全放在BGA背面,而且直径只有0.3mm。产线反馈说探针一压就歪,良率直接掉了5%。后来我让他改成0.8mm的方形焊盘,间距拉开到1.5mm,问题才解决。你想想看,产线工人一天要测几百块板子,探针定位不准,那就是灾难。
我的个人习惯:
在原理图阶段,我就给每个测试点加一个「TP_」前缀的net label。这样Layout工程师一看就知道:这是测试点,不能随便挪。另外,我会在PCB上预留一排「地测试点」,方便示波器接地——这招在调试阶段特别管用。
4.2 边界扫描:JTAG不只是用来下载程序的
很多人以为JTAG就是给FPGA烧录用的。其实,JTAG的边界扫描功能,是产测的一把利器。尤其是BGA封装的芯片,引脚藏在肚子底下,肉眼根本看不到虚焊。
边界扫描的原理不复杂:芯片内部有一串移位寄存器,可以「捕获」每个引脚的电平状态。你通过TDI/TDO串行读出这些数据,就能知道每个引脚是否正常连接。
// 一个简单的边界扫描测试流程(伪代码)
1. 通过JTAG加载BSDL文件(边界扫描描述语言)
2. 发送EXTEST指令(外部测试模式)
3. 向所有输出引脚写入已知数据(比如0xAA)
4. 从所有输入引脚读取数据
5. 对比期望值,判断开路/短路
// 实际产线脚本中,我会这样写:
jtag_chain_init("chain1.cfg");
bsdl_load("FPGA_bsdl", "xc7k325t.bsdl");
bsdl_load("ADC_bsdl", "ads52j90.bsdl");
set_pin_state("FPGA", "IO_L1P_T0", 1);
set_pin_state("FPGA", "IO_L1N_T0", 0);
capture_pin_state("ADC", "CLK_P");
capture_pin_state("ADC", "CLK_N");
compare_result("ADC_CLK", expected_0x55);
我曾经在一个64通道的超声前端板上,用边界扫描抓出了3处BGA虚焊。那批板子外观完全正常,上电也能工作,但信噪比就是差。用JTAG一扫描,发现ADC的时钟差分对有一根断了。如果没有边界扫描,这种问题得用热成像仪慢慢找,效率差太多了。
避坑指南:
我曾经吃过一次亏:某款ADC的BSDL文件里,把电源引脚也定义成了可扫描的I/O。结果产线一跑EXTEST,直接把电源对地短路了,烧了3块板子。后来我学乖了——跑边界扫描前,一定要先检查BSDL文件里的「power_pin」和「gnd_pin」定义,该屏蔽的引脚要手动排除。
4.3 内建自测试:让板子自己「体检」
内建自测试,英文叫BIST。说白了,就是让芯片或模块自己跑一段测试程序,然后告诉你「我好不好」。这在彩超系统里特别实用,因为通道数太多了,人工测不过来。
常见的BIST类型有几种:
| BIST类型 | 适用场景 | 我常用的实现方式 |
|---|---|---|
| Memory BIST | DDR、SRAM、FIFO | March C+算法,跑一遍读写校验 |
| Analog BIST | ADC、DAC、LNA | 注入已知信号,比对输出幅值 |
| Digital BIST | FPGA逻辑、SerDes | PRBS伪随机码,环回测试 |
| System BIST | 整机链路 | 发射-接收环回,检测增益和噪声 |
以彩超的模拟前端为例,我会在FPGA里写一个BIST控制器。上电后,它先让发射电路发出一个固定频率的脉冲(比如5MHz,50%占空比),然后通过T/R开关环回到接收通道。ADC采样后,FPGA计算信号的幅度和相位,跟预设值对比。如果偏差超过±3dB,就报错。
// FPGA内部BIST状态机(简化版)
always @(posedge clk) begin
case (bist_state)
IDLE: begin
if (bist_start) bist_state <= TX_PULSE;
end
TX_PULSE: begin
tx_enable <= 1; // 开启发射
tx_freq <= 5_000_000; // 5MHz
tx_cycles <= 10; // 发10个周期
bist_state <= WAIT_ADC;
end
WAIT_ADC: begin
if (adc_done) begin
// 计算RMS值
rms_value <= sqrt(accum_data / sample_count);
if (rms_value > threshold_low && rms_value < threshold_high)
bist_pass <= 1;
else
bist_fail <= 1;
bist_state <= DONE;
end
end
DONE: begin
tx_enable <= 0;
// 输出结果到LED或UART
end
endcase
end
我的建议:
BIST不要只做「通过/不通过」的二元判断。我会把测试结果量化,比如ADC的DNL、INL,或者链路的噪声系数。这样产线不仅能知道板子好坏,还能看出「哪块板子快坏了」——比如噪声系数从3.5dB漂到了4.2dB,虽然还在规格内,但已经是个预警信号了。
4.4 三种DFT方法的协同
实际量产中,这三种方法不是孤立的。我一般这样搭配:
- 上电自检阶段:先跑BIST,快速筛掉「死板」——电源短路、时钟没起振、FPGA配置失败。这个阶段耗时约5秒。
- 连接测试阶段:用边界扫描,检查BGA、连接器、电阻排的焊接质量。耗时约30秒。
- 功能测试阶段:用测试点做信号质量验证——看眼图、测抖动、量幅值。这个阶段最耗时,但DFT做得好,可以大幅减少探针移动次数。
我记得有个项目,刚开始产线测试一片板子要8分钟。后来我重新规划了测试点布局,把BIST和边界扫描整合到一个测试序列里,时间压缩到了3分钟以内。良率也从92%提到了97%。说白了,DFT不是「额外工作」,而是「省时间的投资」。
总结一下我的经验:
- 测试点:宁可多,不可少。多一个测试点,产线少一次飞线。
- 边界扫描:别只当下载口用。它是最便宜的ICT(在线测试)替代方案。
- 内建自测试:让板子自己说话。BIST跑得越快,产线效率越高。
嗯,DFT这部分就先聊到这儿。下一章咱们讲讲生产测试流程的搭建,那又是另一套学问了。