3. 确定性抖动(DJ)的分类
聊完抖动的总体分类,咱们得把镜头拉近,专门看看确定性抖动(DJ)。这东西说白了就是那些“有规律、可预测”的抖动。它不像随机抖动那样靠概率分布说话,它的来源特别清楚,你多半都能找到元凶。
我做了这么多年信号完整性,处理的DJ案例比RJ多得多。为什么?因为这玩意儿能治!找到根源,往往一个电容、一段走线就能解决。DJ按行为特征,主要分三类:周期抖动(PJ)、数据相关抖动(DDJ)和占空比失真(DCD)。咱们一个个掰开讲。
核心概念: DJ是有界的、可重复的抖动分量。它的峰值(Peak-to-Peak)不会随着测量次数无限增长,这和RJ完全相反。所以你测量DJ时,看到的极限值就是它的真实边界。
3.1 周期抖动(PJ)
PJ,顾名思义,就是抖动在时间上呈现周期性。你把它放到频谱仪上看,会在特定的频率点上看到一个明显的尖峰。我个人习惯是先看电源噪声,开关频率往往是PJ的第一大源头。
实战技巧: 拿到一个PJ波形,先算它的周期。如果周期跟你板上的DC-DC开关频率一致,八九不离十就是电源耦合过来的。我碰到过最夸张的一次,PJ周期正好等于USB 2.0的帧周期,查了半天发现是USB连接器屏蔽没做好。
PJ的典型来源有哪些?
- 开关电源纹波: 频率通常在几百kHz到几MHz。这个在射频和高速数字电路里特别常见。
- 串扰: 邻近信号线的电磁耦合。如果那个干扰信号是周期性的,比如时钟线,那么被干扰的线上就会出现同频的PJ。
- 锁相环(PLL)的参考杂散: 频率合成器生成的杂散信号,会直接给输出时钟“化妆”,抹上周期性的抖动。
- 机械振动: 在精密测量场景下,风扇、甚至人的脚步声都能产生低频PJ。这个我以前不太信,直到亲眼看到实验室数据...
测量PJ有个关键点:带宽。如果你用示波器测PJ,带宽不够,那些高频PJ分量会被滤掉。你看到的反而只是一个平滑的“假信号”。
表里是我总结的PJ分类和排查优先级:
| PJ 来源 | 典型频率范围 | 排查优先级 |
|---|---|---|
| 开关电源 | 100 kHz ~ 10 MHz | 高(1st pass) |
| 时钟串扰 | 25 MHz ~ 1 GHz | 高(Layout 检查) |
| PLL 杂散 | 数 MHz ~ 数百 MHz | 中(Spectrum 分析) |
| 机械振动 | < 1 kHz | 低(需排除法) |
3.2 数据相关抖动(DDJ)
DDJ,这个名字很直白:它跟数据本身有关。你发送不同的比特序列,抖动大小就不一样。常见的情景是,你发一串长“0”然后突然来一个“1”时,这个跳变沿的位置会偏离理想位置。为什么?因为信道有带宽限制。
DDJ在两个场景里特别棘手:一是高速串行总线(比如PCIe、USB、SATA)的预加重设计;另一个是记忆信道(有反射、有多个抽头的信道)。
DDJ又两个关键分量,咱们必须分开处理:
3.2.1 码间干扰(ISI)
ISI是最常见的DDJ分量。传输信道不是理想导体,有损耗、有反射。前一个信号的尾巴还没收完,后一个信号就来了——这就像两个人同时说话,互相干扰,边沿位置就漂了。
我记得有一次调试DDR4总线,跑PRBS7码型,眼图半睁半闭。换上PRBS31后,眼完全闭上了。这就是ISI在作怪。为什么?PRBS31里连续相同比特(CIT)更长,信道记忆效应更强,抖动自然更大。
避坑指南: 我曾经用PRBS7测试,所有指标都通过。但换到实际应用码型(比如80b/10b编码)后,系统频繁丢包。原因就是PRBS7的长度不够,没有覆盖到信道的记忆深度。所以DDJ验证,我建议至少跑PRBS15以上。
3.2.2 脉冲宽度失真(PWD)
PWD跟数据上升沿和下降沿的不对称有关。如果上升沿慢、下降沿快,那么一个“0-1-0”脉冲的宽度和“1-0-1”的脉冲宽度就不一样了。注意,这里不是电平高低的问题,是斜率不一样。
这个分量在低功耗设计里尤其明显。我曾经用过一款28nm的FPGA,它内部驱动强度可配置。当设成“弱驱动”时,PWD一下子窜上来几十皮秒。嗯,这是个很容易被忽略的问题。
DDJ的分解,核心思想就是条件平均。你按照不同的数据比特模式(Pattern)把抖动标记分组,然后各组分别取平均。ISI分量取的是当前比特前后比特组合的平均;PWD取的是单个比特的前后沿差异。
// 一段伪代码:DDJ 分解核心逻辑
// 假设我们已经拿到了一长串跳变沿的时间误差 TIE[]
// 以及对应的数据流 bits[]
for each transition edge at time t:
pattern = get_surrounding_bits(bits[], t, pre_bits=2, post_bits=2)
// pattern 如 "001", "101", "010" 等
DDJ_ISI[pattern] += TIE[t]
count[pattern]++
for each pattern:
DDJ_ISI[pattern] /= count[pattern]
// 分离 ISI:提取不同 pattern 的 TTE 均值
// 剩下的残差 = TIE - DDJ_ISI,包含 PJ、DCD 和 RJ
你想想看,这个思路并不复杂。但实际工程里,码型数量太大(比如5比特前后文就有2^5=32种),需要大量的数据点才能统计稳定。所以,我一般推荐用长伪随机码(PRBS)配合硬件累加器来做。
3.3 占空比失真(DCD)
DCD,这个最简单,但也最容易掉坑。它的表现很单一:时钟或数据信号的高电平宽度和低电平宽度不相等。结果就是,上升沿和下降沿的零点位置都发生了偏移——一个往右偏,一个往左偏。
DCD的来源基本上就两个:
- 接收端阈值电压偏移: 接收器的判决电平不是理想的Vdd/2,而是偏高或偏低了。这会导致“1”比“0”看起来更宽(或更窄)。
- 发射端驱动不平衡: 上升沿和下降沿的驱动强度不一样。PMOS和NMOS的尺寸不匹配就会有这个问题。
关键特征: DCD不会影响信号的周期,它只影响占空比。所以你测周期是准的,但1和0的宽度是错的。这在DDR系统中特别致命,因为DDR对DQ-DQS的时序关系非常敏感。
分离DCD的方法还挺巧妙。你先把TIE序列按符号(正或负)分成两组。因为DCD会让上升沿偏一个方向,下降沿偏另一个方向。然后你取这两组的均值,它们模值的差就是DCD的大小。
手算例子: 假设上升沿的TIE平均是+5 ps,下降沿的TIE平均是-3 ps。那么DCD分量 = (|5| + |-3|) / 2 = 4 ps。简单吧?但注意,这个假设了PJ和ISI已经被提前分离了,否则算出来的是“假DCD”。
实际项目里,我通常用“双直方图法”来验证DCD。即分别绘制上升沿和下降沿的TIE直方图,如果它们有明显的偏移,而且偏移量之差是常数,那就实锤了DCD。这个方法的好处是,即使有PJ存在,直方图的形状会变花,但两个直方图的相对偏移不会变。
最后,我给大家列个总结表,方便对比这三类抖动的“性格差异”:
| 抖动类型 | 来源 | 特征 | 频谱表现 | 典型对策 |
|---|---|---|---|---|
| PJ | 电源、耦合、干扰 | 周期性,有固定频率 | 离散尖峰 | 去耦、屏蔽、Layout优化 |
| DDJ(ISI) | 信道带宽、反射、损耗 | 与码型记忆相关 | 码率整数倍宽带噪声 | 均衡器(CTLE/DFE) |
| DDJ(PWD) | 沿斜率不对称 | 高/低脉冲宽度不等 | 主要是低频成分 | 调整驱动级尺寸 |
| DCD | 阈值偏、驱动平衡差 | 上升/下降沿偏移方向相反 | 偶次谐波加强 | 校准阈值、优化驱动 |