Gen4 均衡系数:定义与规范
讲均衡系数之前,我先说个我自己的经历。刚做 Gen4 项目那会儿,我总觉得系数嘛,随便写个值调一下就行,结果板子死活 link 不上。后来发现,系数的范围、步长、编码方式,规范里掰得清清楚楚,漏一个细节就翻车。这节咱们就把这些硬骨头啃下来。
系数范围——别超出边界
Gen4 标准里,均衡系数分发送端(Tx)和接收端(Rx)。我这里重点讲 Tx 去加重系数,因为它在训练中来回协商,最容易出问题。
- 最小系数:通常对应最大去加重,例如 -12 dB 衰减。换算成数字域,是
-127 LSB(1 LSB = 0.094 dB 左右)。 - 最大系数:无去加重,即 0 dB,对应
0 LSB。有时候也允许一点点预加重,但 Gen4 里很少用到正方向。 - 实际可取范围:
-127 ~ 0,单位 LSB。注意,有些芯片内部支持+127,但标准交互时只发负值。
步长——非均匀还是均匀?
Gen4 均衡系数的步长可不是随便定的。很多人以为和 ADC 一样,每 1 LSB 对应固定 dB 步长。其实不然。
| 系数分段 | LSB 步长(dB) | 典型应用场景 |
|---|---|---|
| -6 dB 以内(轻度去加重) | 0.5 dB / LSB | 短通道、低损耗链路 |
| -6 dB ~ -12 dB(中重度去加重) | 1.0 dB / LSB | 长通道、高损耗背板 |
| -12 dB 以下(极少使用) | 2.0 dB / LSB | 极端损耗链路 |
为什么要这么设计?我琢磨过,核心原因是 人耳感知(不对,是链路均衡)对近端误差更敏感。轻度去加重时,零点几个 dB 的偏差就可能导致眼图闭合;重度去加重时,信号眼本来就小,允许更大误差。步长非均匀,是性价比最高的编码方式。
编码方式——二进制补码 + 偏移映射
Gen4 均衡系数在寄存器里用 8 位有符号二进制补码 表示,但实际物理值要经过一段映射表。直接补码的坑在于,0x80(-128)按协议是保留值,千万别发。
关键编码规则:
- 有效范围:
-127(0x81)到0(0x00),以及+1(0x01)到+127(0x7F)——虽然 Tx 很少用正值。 - 寄存器写入时,直接放补码;读取时也是补码,但实际链路协商会用 Preset 索引 来间接推导系数,而不是直接读补码值。
- 编码表格在 PCIe Base Spec 的表 4-X 里(具体号记不清了),我建议手边常备那份表。
配合一个实际例子。比如你想设置去加重 3.5 dB,对应物理值约 -37 LSB(计算:3.5 ÷ 0.094 ≈ 37.2)。补码就是 0xDB。嗯,这里要注意,如果芯片内部的 LSB 精度和协议不一致,还得乘个缩放因子。我一般直接查 Preset,省心。
寄存器字段布局
Gen4 把所有均衡相关的系数收在 PCIe Extended Capability – Equalization Control 里。每个 Lane 单独有一个 Tx 系数寄存器,格式如下:
Bit 位 | 名称 | 描述
7 | Sign | 1: 负数(补码符号位)
6:1 | Magnitude[5:0] | 幅度值(6 bit)
0 | Reserved | 必须置 0
更常见的做法是把 8 位整体看作补码。但上面这种拆分方式,在调试时很有用——我可以用 bit mask 单独看符号位有没有搞错。记得有一次同事写了个 bug,符号位和幅度反了,结果 –1 变成了 –63,眼图直接塌了。
实战避坑:系数协商的边界
训练过程中,端到端会交换系数 Preset 值(0~10),而不是直接传系数补码。我建议你做链路层设计时,一定要把 Preset 和实际系数的映射表固化成一个数组,别现场算。为什么?
- 性能:每个 Preset 对应的系数是固定的,计算一次就行。
- 一致性:避免浮点误差——我亲眼见过两个芯片商的算出来的系数差了 1 LSB,然后不停切换 Preset,死循环了。
- 合规:Gen4 标准要求 Preset 具体系数必须匹配规范中的数值表,不允许自己设计。
一张图看懂均衡系数规范
下面这个 SVG 框架图,把系数范围、步长非均匀、编码方式、寄存器布局串在一起。画的时候我特意把“我踩过的坑”也标上去了——也算是给各位提个醒。
小结一下
均衡系数不是什么玄学,就是一本规范账:范围不能越界、步长靠分段表格、编码用补码。但每一个细节都可能成为你调试时的拦路虎。我建议你把这节讲的三个要点——范围、步长、编码——当成 checklist,每次写代码前过一遍。嗯,这样基本就能避免我在开头说的那种“死活 link 不上”的尴尬了。