发送端均衡:去加重(De-emphasis)与预加重(Pre-emphasis)原理与参数

你有没有想过,为什么PCIe链路一定要搞均衡?

说白了,高速信号在PCB上走几寸,高频分量就衰减得厉害。你想想看,一根20cm的走线,在8GT/s的速率下,损耗可能超过10dB。接收端那边拿到的是一个眼皮都快闭上的眼图,根本没法采样。所以,发送端必须先“动手”——要么把低频压一压,要么把高频抬一抬,让信号到了接收端的时候形态更好一点。这就是发送端均衡的由来。

但有个概念特别容易搞混:去加重(De-emphasis)和预加重(Pre-emphasis)。我刚开始做PCIe调试那几年,也经常把这两个词用反。今天咱们彻底捋清楚。

1. 是“压低频”还是“抬高频”?

先看定义:

  • 去加重(De-emphasis):保持高频幅度不变,降低低频部分的幅度。在时域上就是让连续相同bit的幅度比切换bit的幅度低一截。
  • 预加重(Pre-emphasis):保持低频幅度不变,提升高频部分的幅度。时域上切换bit时往上“凸”一下。

你可能会问:效果上有什么区别?其实它们达到的频域目标是一样的——都相当于一个高通滤波器,补偿信道的低通特性。但PCIe从Gen1开始就选用了去加重方案,原因很简单:提升高频需要更大的发射幅值,功耗和EMI都会增加。去加重只往下压低频,发送器最大输出电平不变,实现起来也更省事。所以后面所有PCIe代际都沿用了去加重的提法,但实际寄存器里写的参数叫“Preset”,它既包含去加重幅度,也包含摆幅信息。

个人习惯:我一般跟团队讲的时候,会直接说“我们讨论的是去加重,但不用纠结名字,记住数字即可——PCIe协议里只定义了发送器需要输出几种预设波形,具体是压低频还是抬高频,那是内部实现的事”。

2. 参数怎么读?—— Preset 与去加重幅度

PCIe Gen3之后,发送端均衡被统一成 Preset 的概念。每个Preset对应一组去加重幅度和摆幅。以Gen3为例,规范定义了8个Preset(0~7),但最常用的就那几个:

Preset 去加重幅度 (dB) 摆幅 (mV, 峰峰值) 典型应用场景
P00.0800 / 1000短距 / 背板
P1-3.5 ± 1800 / 1000中等长度走线
P2-6.0 ± 1.5800 / 1000较长走线
P3-3.5 ± 1400 / 600低功耗 / 短距
P4-6.0 ± 1.5400 / 600低功耗中等长度
P50.0400 / 600极短距 / 芯片间

注意:上表的去加重幅度是 负值,表示低频比高频低了多少分贝。比如P1就是低频幅度比高频低3.5dB。这个数字在协议里可能写成“-3.5 dB de-emphasis”,但你在示波器上测出来的眼图,常常看到低频位的高度明显矮一截。

为什么会这样?我举个实际例子:之前调试一块Gen3的switch板卡,链路长度约25cm,插损大概12dB。一开始用P0(0dB去加重),接收端报CRC错误满天飞。换P2(-6dB)后,眼图瞬间打开,误码率降到1e-12以下。你想想看,仅仅一个去加重预设,差距就这么大。

3. 发送端均衡是怎么做到的?

内部实现其实就是一个三抽头FFE(前馈均衡器)。核心思路:当前bit的幅度由它自己和前后bit的加权和决定。PCIe Gen3/4的发送器一般使用一个主抽头加一个后游标抽头:

  • 主抽头系数 = 1(保持高频幅度)
  • 后游标抽头系数 = c(决定去加重深度)

当当前bit与前一个bit不同时(发生跳变),只输出主抽头幅度;
当它们相同时(连续同值),主抽头减去后游标的贡献,幅度降低。降低的比例就是去加重幅度,单位dB = 20 × log₁₀(1 - c)。

下面是发送端均衡的典型架构——我画了一张框图,帮你把数据流走一遍:

发送端均衡(去加重)实现框图 并行数据源 串化器 (Serializer) 3-Tap FFE (去加重控制) TX 驱动器 PCIe 信道 RX 均衡+CDR ■ 主抽头系数固定为1,后游标系数c由Preset决定(0 ≤ c ≤ 0.5) ■ 去加重幅度 = 20·log₁₀(1−c) dB,例如c=0.5 → −6.0dB,c=0.3 → −3.1dB ■ Gen5/6引入更多抽头(5-tap FFE),但基本原理相同

从图上你可以看到:发送数据经过串化器变成高速串流,然后进入FFE均衡器。FFE根据当前bit和前一个bit的关系调整输出电平。我们平时在示波器上看到的“眼图上下差一截”,就是这个FFE干的好事。

4. 实战中的避坑指南

我曾经在一个Gen4 Retimer项目里踩过一个坑——板卡在实验室测试没问题,但一到客户系统里就频繁Link Down。反复抓log,发现接收端协商出来的Preset是P7(保留值,实际没有定义),但我的发送器固件里P7被映射成了P0(不加去加重)。客户信道损耗比实验室大,P0根本打不开眼图。

后来我仔细查了PCIe Base Spec 4.0,才发现Gen4对Preset的处理有严格规定:如果接收端请求的Preset不在发送器支持集里,必须回复“不支持”,然后双方回退到P0。但我的固件没做容错,直接用了默认P0,导致链路不稳定。

避坑指南:
  • 一定要查看芯片datasheet上支持的Preset列表,很多老芯片只支持P0~P4。
  • 在LTSSM进入Configuration之前,发送器必须在训练序列里正确发送Preset能力。我曾经用逻辑分析仪抓出来过——有些PHY默认Preset寄存器是0x00,需要软件主动配置。
  • 如果你在调试时发现眼图不对称(上下眼皮高度不一样),先检查去加重幅度是否和期望值一致。用示波器测量:连续5个+或5个-的电平幅度,减去跳变bit的幅度,算一下dB,跟Preset标称值对一下。

5. 去加重 vs 预加重 —— 一张表说清楚

虽然PCIe只用去加重,但面试和原理探讨时两者的区别是高频考点。我整理了下表:

对比项去加重 (De-emphasis)预加重 (Pre-emphasis)
操作对象压低低频分量抬高高频分量
发送器最大电压不变(压低频)增加(高频需更高的峰值)
功耗相对低相对高
频域形状高通(零极点相同)高通(零极点相同)
PCIe使用是(Gen1~Gen6)否
实现复杂度只需一个后游标需要调整主抽头幅度

6. 如何通过寄存器配置发送端均衡?

如果你做固件开发,一定会遇到写PHY的Preset寄存器。我见过所有的PCIe控制器,基本都在类似这个地址里:

// 以某款常见PCIe控制器为例
#define PCIE_PHY_TX_PRESET_OFFSET  0x1A0

// 配置为 Gen3 Preset P2(去加重-6dB,摆幅800mV)
uint32_t reg_val = 0x02;  // Preset编号
reg_val |= (0x01 << 3);   // 开启去加重使能(某些控制器需要)
reg_val |= (0x00 << 4);   // 摆幅档位选择

// 写入PHY寄存器组
*(volatile uint32_t *)(PHY_BASE + PCIE_PHY_TX_PRESET_OFFSET) = reg_val;

注意:不同厂家的寄存器布局完全不同。有的把Preset编号和摆幅分开两个寄存器。我的建议是——一定先读当前值,再修改对应位,不要直接整个寄存器覆写。我曾经见过同事直接把0x00写进去,把摆幅也清掉了,结果TX完全不输出信号。

7. 一个小总结

发送端均衡说难也不难,核心就是记住三个数字:0dB、-3.5dB、-6dB。对于大多数PCIe链路,从P0开始试,如果眼图闭合就依次往大去加重幅度升级。但也要注意:去加重过头了,接收端可能会因为过强的预加重(实际上是压低频太狠)导致信号过冲,反而劣化时序。我记得有个项目,客服反馈说换用P4(-6dB+低摆幅)反而比P2好,因为板上走线只有8cm,P2的低频压得太低,接收端CTLE又没适配好,最终眼图上下不对称。所以,均衡是发送端和接收端配合的艺术,不是参数越大越好。

下一道题我们会深入接收端均衡(CTLE和DFE),看看另一头是怎么配合的。这里先把发送端的概念焊牢了,后面做链路调试才能快准狠。