4. 判决反馈均衡器基本原理:前馈与反馈结构消除ISI

要做高速串行链路,你一定绕不开码间干扰(ISI)。信号经过信道后,前一个符号的尾巴拖到了后一个符号身上,眼图就闭上了。DFE(判决反馈均衡器)是解决这个问题的利器。我个人习惯把它理解成一套“知错能改”的系统——先靠前馈滤波器把大致的干扰压下去,再利用已经判决出来的符号信息,把残留的ISI消除掉。

4.1 整体结构:两条腿走路

DFE由两个核心部分组成:前馈滤波器(FFF) 和 反馈滤波器(FBF)。你想想看,FFF在前端,处理接收到的连续信号;FBF在后端,利用已判决的符号来重建并减去当前符号的干扰。两者配合,才能干净地恢复出发送数据。

我在项目中遇到过一种情况:只看FFF的抽头系数,眼图已经能睁开一点,但抖动很大。加上FBF之后,眼图一下就稳定了。说白了,FFF负责对付前向的ISI(比如信道衰减引起的拖尾),FBF负责对付后向的ISI(比如反射回来的回波)。

DFE 结构框图(FFF + FBF 协同消除 ISI) 输入 r(t) 前馈滤波器 FFF + 判决器 Slicer 输出 Â[n] 反馈滤波器 FBF 反馈路径 工作流程:接收信号 r(t) 经 FFF 滤波 → 减去 FBF 重建的 ISI → 判决得到 Â[n] 判决结果 Â[n] 送入 FBF 产生反馈量,用于抵消后续符号的 ISI

4.2 前馈滤波器(FFF)

FFF一般是一个横向FIR滤波器,工作在符号速率或更高倍采样率上。它的抽头系数通过自适应算法(比如LMS)来更新。它的目标很简单:把信道冲激响应的前向拖尾压缩掉。

嗯,这里要注意:FFF的抽头数量不能太少,否则残留下的前向ISI会直接落到判决器头上,导致误码。但也不能太多,否则噪声会被放大。我曾经调试过一个28Gbps的背板链路,信道损耗在奈奎斯特频率处有20dB。我一开始只用了4个FFF抽头,眼图还是闭的。加到8个抽头之后,信号才勉强能看。说白了你得根据信道响应来选。

4.3 反馈滤波器(FBF)

FBF的结构跟FFF类似,但输入不是连续的模拟信号,而是已经判决得到的数字符号序列。它利用这些已知符号来重建当前符号受到的后向ISI,然后在加法器处减去。因为判决符号是二进制的(或者PAM-4的四电平),所以FBF的计算没有噪声放大问题——你想想看,减掉一个干净的数字量,不会引入噪声。

我在项目里见过一个坑:FBF的抽头数量设置太少,导致后向ISI没被完全抵消,眼图的上眼皮和下眼皮不对称。解决办法是增加FBF的抽头数,直到眼图的张开对称为止。

4.4 FFF与FBF的分工对比

对比项 前馈滤波器 FFF 反馈滤波器 FBF
输入信号 模拟/连续采样信号 已判决的数字符号
作用对象 前向 ISI(因果部分) 后向 ISI(非因果部分)
噪声放大 有,抽头多则噪声增大 无,数字运算不放大噪声
抽头更新 依赖自适应算法(LMS等) 同样依赖自适应算法
典型调试点 抽头数、步长、参考电平 抽头数、符号延迟对齐、饱和保护

4.5 消除ISI的原理:一步一步推导

假设信道冲激响应用 h(t) 表示。接收信号 r(t) = s(t) * h(t) + n(t)。经过采样后,我们得到离散信号 r[n] = a[n]·h[0] + Σ_{k≠0} a[n-k]·h[k] + v[n]。其中 a[n] 是发送符号,h[0] 是主抽头,后面那个求和就是ISI。

FFF的作用就是将乘上h[k]的那些项尽量均衡掉一部分,得到 y[n] = wT·r[n], 其中 w 是FFF的抽头向量。然后减法器输出 e[n] = y[n] - feedback[n]。feedback[n] 来自FBF:feedback[n] = Σ_{i=1}^{M} b[i]·Â[n-i],这里的 Â[n-i] 就是过去已判决的符号。

为什么这样能消除后向ISI?因为 Â[n-i] 高度接近真实的 a[n-i](在无判决错误时),反馈量就精确重建了后向ISI。判决器输入 e[n] 中剩下的ISI仅仅取决于FFF的残留和判决误差。

我印象很深的是,有一次我的FBF的判决符号延时没对齐,反馈量总是晚了一个符号周期,结果不但没消ISI,反而叠加了新的干扰。调试时看误码率曲线像个馒头一样。所以对齐很重要。

小技巧: 在硬件调试时,先把FFF的抽头调到最优(可以用盲均衡或训练序列),再开启FBF自适应。这样的收敛速度比两者同时启动快很多。我常常在FPGA验证阶段用两步法。

4.6 一个简单的自适应示例(LMS更新)

下面是FFF和FBF的系数更新伪代码。其实跟普通LMS没区别,只是误差信号 e[n] 要减去反馈量。

// 参数假设
N_fff = 8;   // FFF 抽头数
N_fbf = 4;   // FBF 抽头数
mu = 0.01;   // 步长

// 初始化
w_fff = zeros(N_fff,1);
b_fbf = zeros(N_fbf,1);

for each symbol index n:
    // FFF 输出
    y_fff = w_fff' * r[n : n-N_fff+1];
    // FBF 输出
    y_fbf = b_fbf' * a_hat[n-1 : n-N_fbf];
    // 误差
    e = y_fff - y_fbf;
    // 判决
    a_hat[n] = slicer(e);
    // 更新 FFF
    w_fff = w_fff + mu * e * r[n : n-N_fff+1];
    // 更新 FBF
    b_fbf = b_fbf + mu * e * a_hat[n-1 : n-N_fbf];
end
注意: 如果FBF更新时使用的 Â[n-1] 是错的(即误判决),会导致误差传播。这种情况在信噪比很低时尤其明显。我曾经在一次12Gbps背板测试中,因为信号太差,FBF的反馈量被错误判决污染,整个环路发散。解决方案是加入一个误码率监控,当BER过高时暂时冻结FBF的自适应,只让FFF工作。

4.7 从眼图角度理解

你打开示波器看眼图,如果只有FFF均衡,眼图可能还是有点“毛刺”或者眼高不够——那是后向ISI在捣乱。加上FBF之后,眼图的张开度会瞬间提升,尤其是眼睛的上下沿会变得非常干净。我习惯用眼图模板测试,通过/不通过。有一次加FBF之前眼高只有200mV,加了之后直接跳到320mV,误码率从10⁻⁵降到了10⁻¹²以下。

不过要注意,FBF对时钟恢复是有依赖的。如果时钟相位不准,判决点不在最佳采样点,那么判决符号本身就不可靠,FBF也就没用了。所以调试DFE的时候,我通常先保证时钟恢复环路锁定,再调FFF,最后调FBF。


总结一下:FFF + FBF 就像一对搭档,一个在前线压制前向ISI,一个在后防线清除后向ISI。两者缺一不可。你只要记住,FFF处理模拟信号,FBF处理数字信号,减法器是它们握手的地方。这样调试的时候思路就清晰了。