1. 抖动概述与基本概念归纳

1.1 什么是抖动?

抖动这东西,说白了就是信号边沿偏离理想位置。你想想看,数字电路里的时钟本应该在0.5ns处跳变,结果它跑到0.52ns才跳——这0.02ns的偏差就是抖动。

我做高速接口项目那会儿,一开始觉得抖动只是“波形差一点”,直到眼图闭上,误码率直接飙到10⁻⁶,才明白这东西不搞清楚,芯片根本跑不起来。个人习惯,每接触新信号标准,第一件事就是查它允许的抖动预算。

1.2 抖动的来源

抖动能从哪冒出来?我归纳了下,常见就这几类:

  • 电源噪声——电源纹波直接调制到时钟边沿。我曾经在DDR3调试时,发现抖动波形正好跟开关频率吻合,一查果然是电源去耦没做好。
  • 串扰——相邻信号线之间的耦合。尤其是长走线并行时,串扰抖动简直防不胜防。
  • 热噪声——半导体器件的散粒噪声、闪烁噪声,属于底噪,永远都在。
  • 码间干扰(ISI)——前一个比特的状态影响当前比特的边沿。速率越高,ISI越明显。
  • 时钟源自身——PLL的抖动、晶振的相位噪声。
检查思路:拿到抖动谱,先看是否存在固定频率尖峰。如果有,多半是电源或串扰;如果是宽频白噪,那就是热噪声主导。

1.3 抖动分类

业内最常用的分法:随机抖动(RJ)和确定性抖动(DJ)。前者无界但服从高斯,后者有界且有规律。

类型 特性 常见来源 分布形状
随机抖动(RJ) 高斯分布,均方根描述 热噪声、散粒噪声 钟形曲线
确定性抖动(DJ) 有界,峰峰值描述 电源噪声、串扰、ISI 双峰、矩形等
其中:周期性抖动(PJ) 单一或多个频率正弦抖动 电源纹波、时钟调制 正弦相位谱
其中:数据相关抖动(DDJ) 码型决定,包括ISI和DCD 信道不匹配、占空比失真 与码型相关

为什么要分这么细?因为不同的抖动,抑制手段完全不同。电力噪声靠滤波,ISI靠均衡,RJ只能靠扩频或冗余时钟。我记得有一次项目里眼图闭合,一开始怀疑是RJ,跑完分解才发现是0.1MHz的PJ主导——换一个LDO就解决了。嗯,分解的意义就在这里。

别搞混了:RJ用均方根(RMS),DJ用峰峰值(Peak-to-Peak),两者单位不一样,不能直接相加。很多新人直接把RMS×2当峰峰值用,结果眼图预算算错,流片回来才发现。

1.4 抖动的测量指标

光知道分类还不够,你得会量。常见指标就这几个:

  • 峰峰值抖动(Jp-p)——采样窗口内边沿位置的最大偏差。简单但受采样数影响,采样越多测到越大。
  • 均方根抖动(JRMS)——对高斯部分有效,稳定且可重复。
  • 眼图开口——眼高、眼宽直接反映数据有效窗口。我习惯把眼宽跟抖动峰峰值放一起看,超过总预算的20%就危险了。
  • 抖动谱(Phase Noise)——频域分析,能看出干扰频率点。
我的建议:量产测试用Jp-p,因为快;研发调试重点看抖动谱,因为定位快。

1.5 抖动分解的意义

你得到一组抖动数据,比如眼图闭合了,但你不知道是随机抖动太大还是确定性抖动干预。抖动分解算法的作用就是从总抖动(TJ)里分离出RJ和DJ,再进一步把DJ拆成PJ、DDJ等。这样你才能对症下药。

拿我经历的SerDes项目来说,总抖动6ps,直觉觉得是RJ太大。但分解后RJ只有1.2psRMS,DJ占了4.5pspp——再一细化,DDJ里面的ISI贡献了3ps。于是加了个CTLE,眼图立马打开。你说不分解行吗?

1.6 本章知识体系

抖动知识框架 抖动 (Jitter) 随机抖动 (RJ) 确定性抖动 (DJ) 周期性抖动 (PJ) 数据相关抖动 (DDJ) 占空比失真 (DCD) 峰峰值 (Jp-p) 均方根 (JRMS) 眼图开口 抖动谱 抖动分解算法 → 从 TJ 中分离 RJ、DJ 及子成分 指导电源滤波 / 均衡器 / 时钟设计 注意:RJ 无界但可用 RMS 统计;DJ 有界且可通过频域定位。分解必须基于足够长的采样数据。

1.7 代码示例:模拟简单抖动

分解之前,先看看抖动长什么样。用Python生成一个带随机抖动的时钟边沿:

import numpy as np
import matplotlib.pyplot as plt

fs = 100e9          # 采样率 100 GSa/s
f_clk = 1e9         # 时钟频率 1 GHz
t_period = 1e-9     # 1 ns
t = np.linspace(0, 10*t_period, 1000)

# 理想时钟沿(上升沿在 t = 0, 1ns, 2ns ...)
ideal_edges = np.arange(0, 10*t_period, t_period)

# 加入高斯抖动(RJ): sigma = 10 ps
jitter = np.random.normal(0, 10e-12, size=len(ideal_edges))
actual_edges = ideal_edges + jitter

# 构建时钟波形(方波)
clock = np.zeros_like(t)
for edge in actual_edges:
    idx = np.searchsorted(t, edge)
    clock[idx:] = 1 - clock[idx:]   # 翻转

# 估算抖动峰峰值、RMS
pp_jitter = np.max(jitter) - np.min(jitter)
rms_jitter = np.std(jitter)

print(f"抖动峰峰值: {pp_jitter*1e12:.1f} ps")
print(f"抖动 RMS : {rms_jitter*1e12:.1f} ps")

跑这段代码,你会看到理想边沿被随机高斯噪声扰动。每次结果不同,但RMS稳定在10 ps左右。

改着玩:如果把噪声换成np.random.normal(0, 5e-12),或者加一个正弦干扰模拟PJ,看看峰峰值怎么变。

记住,这只是一个模拟。真实芯片上的抖动需要考虑带宽、上升沿斜率、噪声谱形状等因素。但概念理解上,你已经知道抖动是什么、怎么量、为什么需要分解了。