Vivado高速收发器IP配置与联调 - 第2节

一、收发器硬件架构概览

收发器,说白了就是高速串行通信的物理层引擎。我做了这么多年FPGA设计,最深的体会就是:不懂收发器硬件架构,你根本没法搞定高速接口设计。

收发器内部主要分为两大块:PMA层和PCS层。PMA管模拟,PCS管数字。这两层配合起来,才能把并行数据变成高速串行信号发出去,再把收到的串行信号还原回来。

核心要点:收发器 = PMA(物理介质适配层)+ PCS(物理编码子层)

PMA负责模拟信号处理,PCS负责数字逻辑编码

收发器硬件架构总览 PMA层(物理介质适配层) 串行器 (Serializer) 解串器 (Deserializer) 时钟数据恢复 (CDR) 发送/接收缓冲 (TX/RX Buffer) PCS层(物理编码子层) 8B/10B编码器 8B/10B解码器 弹性缓冲 (Elastic Buffer) 通道绑定 (Channel Bonding) 发送 接收 ← 串行数据 (SERDES) 并行数据接口 (FPGA逻辑) →

二、PMA层详解

2.1 PCS/PMA分层思想

为什么要把收发器分成PMA和PCS两层?我个人觉得,这其实是一种模拟与数字分离的设计哲学。PMA处理那些敏感的模拟信号,PCS处理相对稳定的数字逻辑。这样分层以后,你调试的时候也能快速定位问题——是眼图张不开(PMA问题),还是数据对不上(PCS问题)。

我在项目中遇到过好几次这样的情况:链路不稳定,一开始以为是PCS的编解码出了问题,折腾了半天,最后发现是PMA的CDR锁相环参数没配好。嗯,从那以后我养成了一个习惯——先查PMA,再看PCS。

2.2 串行器与解串器(SERDES)

串行器(Serializer)就是把并行数据转成串行数据。比如你FPGA内部是32位宽的数据总线,要发出去就得变成1位的高速串行流。解串器(Deserializer)反过来,把收到的1位串行流还原成并行数据。

这里有个关键参数:串化因子。说白了就是多少位并行数据合成一串。常见的串化因子有8:1、10:1、16:1、20:1等等。

串化因子 并行位宽 典型应用
8:1 8位 千兆以太网
10:1 10位 8B/10B编码后的数据
16:1 16位 PCIe Gen1/2
20:1 20位 64B/66B编码后的数据

小技巧:我建议你在配置串化因子时,一定要和PCS层的编码方式匹配。比如用了8B/10B编码,串化因子就选10:1,这样刚好对齐。

2.3 时钟数据恢复(CDR)

CDR是PMA层最核心的模块,没有之一。它的任务是从接收到的串行数据流中提取出时钟信号,然后用这个时钟去采样数据。

为什么会需要CDR?你想想看,发送端和接收端各自有独立的时钟源,频率不可能完全一样。就算标称都是3.125Gbps,实际偏差可能有个±100ppm。如果没有CDR,接收端用自己的时钟去采样,迟早会采错位。

CDR的工作原理其实不复杂:它内部有一个锁相环(PLL),不断调整相位去跟踪输入数据的边沿。我习惯把CDR的工作状态分成三个阶段:

  1. 频率捕获阶段:CDR先大致锁定到输入数据的频率
  2. 相位跟踪阶段:精细调整相位,找到最佳采样点
  3. 锁定保持阶段:锁定后持续跟踪,抵抗抖动

避坑指南:我曾经在一个项目中,CDR始终锁不住。查了半天,发现是参考时钟的精度不够。Vivado里对参考时钟的ppm有严格要求,一般需要±100ppm以内。如果你用普通的晶振,可能只有±50ppm,但有些便宜的晶振能到±200ppm,那就悬了。

三、PCS层详解

3.1 8B/10B编解码

8B/10B编码,说白了就是把8位数据映射成10位码字。为什么要多出2位?为了保证DC平衡和提供足够的跳变沿。

DC平衡是什么意思?就是发送的码字中0和1的数量尽量相等。这样信号的平均电平稳定,不会出现基线漂移。另外,10位码字中保证有足够的0→1和1→0跳变,方便接收端的CDR提取时钟。

8B/10B编码表分为两类:

  • 数据码(D码):对应256种8位数据组合
  • 控制码(K码):用于帧定界、空闲填充等特殊用途

常用的K码有这些:

K码名称 8位值 10位码字 用途
K28.5 0xBC 0011111010 或 1100000101 逗号序列,用于字节对齐
K28.1 0x3C 0011111001 或 1100000110 空闲字符
K28.7 0xFC 0011111000 或 1100000111 测试模式

关键点:K28.5的10位码字中包含了连续的5个1或5个0,这种特殊的模式叫"逗号序列"。接收端通过检测逗号序列来实现字节对齐。说白了,就是告诉接收端"从这里开始,每10位是一个码字"。

3.2 弹性缓冲

弹性缓冲(Elastic Buffer)解决的是时钟域同步问题。接收端从CDR恢复出来的时钟,和FPGA内部的主时钟不是同一个时钟域。这两个时钟之间可能有频率偏差,也有相位偏差。

弹性缓冲本质上就是一个异步FIFO。写入时钟是CDR恢复时钟,读出时钟是FPGA内部时钟。通过这个FIFO,把数据从一个时钟域安全地搬到另一个时钟域。

我记得有一次调试,发现弹性缓冲老是溢出。后来一查,是CDR恢复时钟的频率偏差超出了弹性缓冲的容忍范围。Vivado里弹性缓冲的深度一般是4~8个码字,如果频率偏差太大,缓冲就会溢出或下溢。

经验之谈:我建议你在设计时预留一些弹性缓冲的余量。如果协议允许,可以适当增加缓冲深度。另外,一定要监控弹性缓冲的满/空标志,一旦出现异常,及时复位重新同步。

3.3 通道绑定

通道绑定(Channel Bonding)是啥?说白了,就是把多个收发器通道捆绑在一起,作为一个更宽的通道来使用。比如4个10Gbps的通道绑定成一个40Gbps的通道。

通道绑定的难点在于去偏斜。每个通道的PCB走线长度不同,过孔数量不同,导致数据到达的时间有差异。这个时间差就叫"通道间偏斜"。

Vivado的收发器提供了两种通道绑定方式:

  • 基于PMA的绑定:在PMA层对齐多个通道的时钟相位
  • 基于PCS的绑定:在PCS层通过检测绑定序列来对齐数据

实际项目中,我一般推荐使用PCS层的通道绑定。为什么呢?因为PMA层的绑定对PCB设计要求太高,稍微有点走线长度不匹配就绑不上。而PCS层的绑定可以通过弹性缓冲来补偿偏斜,容错性更好。

避坑指南:我曾经在一个40Gbps的项目中,4个通道死活绑不上。折腾了两天,最后发现是其中一条通道的PCB走线长了300mil。300mil在低频时不算啥,但在10Gbps速率下,对应的时延差已经超过了通道绑定的容忍范围。后来改了PCB,问题就解决了。

四、PMA与PCS的协同工作

PMA和PCS不是各自为战的。它们之间通过接口总线交换数据。常见的接口位宽有8位、10位、16位、20位等,具体取决于串化因子和编码方式。

数据流向是这样的:

  1. 发送方向:FPGA逻辑 → PCS编码 → PMA串行化 → 串行输出
  2. 接收方向:串行输入 → PMA解串 → CDR恢复时钟 → PCS解码 → FPGA逻辑

这里有个容易忽略的点:PMA和PCS之间的接口时钟频率。比如10Gbps的速率,如果接口位宽是20位,那么接口时钟就是10Gbps / 20 = 500MHz。这个时钟频率决定了FPGA逻辑侧的工作频率。

我个人习惯在设计初期就把这些时钟频率算清楚,然后评估FPGA逻辑能不能跑到这个频率。如果跑不到,就得考虑增加接口位宽来降低时钟频率。

总结一下:收发器硬件架构的核心就是PMA+PCS两层。PMA搞定模拟信号和时钟恢复,PCS搞定编码和同步。两层配合好了,高速串行通信才能稳定可靠。

可可精品资料库