2. SerDes工作原理:并行到串行转换、串行到并行转换、时钟数据恢复(CDR)基本原理
好,咱们今天聊聊SerDes最核心的那点事儿。说白了,SerDes就是个“翻译官”——把一堆并行数据,压缩成一根线上跑的串行数据;到了对端,再把它还原回去。听起来简单吧?但这里面的门道,我当年可是踩过不少坑。
2.1 并行到串行转换:把“宽马路”变成“单车道”
想象一下,你面前有8条车道(8位并行数据),每条车道上一辆车(一个bit)。现在要你把这些车全部挤到一条单车道上,按顺序一辆一辆开过去。这就是并行转串行。
在FPGA里,我们通常用移位寄存器来实现。比如一个8位的并行数据 D[7:0],我把它加载进移位寄存器,然后每个时钟周期从高位(或低位)往外推一位。
// 一个简单的8:1串行器示例
module serializer (
input wire clk, // 高速串行时钟
input wire rst_n,
input wire [7:0] data_in, // 并行输入
input wire load, // 加载信号
output reg serial_out // 串行输出
);
reg [7:0] shift_reg;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
shift_reg <= 8'b0;
else if (load)
shift_reg <= data_in; // 加载并行数据
else
shift_reg <= {shift_reg[6:0], 1'b0}; // 左移,高位先出
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
serial_out <= 1'b0;
else
serial_out <= shift_reg[7]; // 输出最高位
end
endmodule
个人经验: 我在项目中遇到过一个问题——加载信号和时钟的时序没对齐,导致第一个bit就错了。后来我习惯在加载路径上加一级寄存器打拍,确保setup/hold时间满足。你想想看,高速下哪怕0.1ns的偏差,数据就全乱了。
这里有个关键点:串行时钟频率 = 并行时钟频率 × 并行位宽。比如你的并行时钟是100MHz,8位并行,那串行时钟就得跑到800MHz。嗯,这个频率在FPGA的SerDes硬核里是标配,但如果你用逻辑资源自己搭,800MHz的时钟树可不好伺候。
2.2 串行到并行转换:把“单车道”还原成“宽马路”
反过来,接收端要把一根线上串行过来的bit流,重新组装成并行数据。这活儿看着简单,但有个大前提——你得知道每个字节的边界在哪里。
举个例子,发送端连续发了8个bit:1 0 1 1 0 0 1 0。接收端如果从第1个bit开始收,得到的是 10110010;但如果从第2个bit开始收,得到的就是 01100101。完全不一样!
所以,串行转并行必须解决“字节对齐”问题。常用的方法有:
- 逗号检测(Comma Detection):在数据流中插入一个特殊的“逗号字符”(比如K28.5),接收端一旦检测到这个字符,就知道字节边界到了。
- 通道绑定(Channel Bonding):多通道SerDes里,每个通道独立对齐后,再通过额外的对齐字符把多个通道对齐。
硬件实现上,串行转并行就是一个移位寄存器加一个计数器。每来一个串行时钟,数据移入一位;计数器计满8个bit后,把移位寄存器的值锁存到并行输出寄存器。
注意: 我曾经犯过一个低级错误——串行时钟和并行时钟是异步的,结果并行输出出现了亚稳态。后来我老老实实加了一个异步FIFO做跨时钟域处理。记住:任何跨时钟域的信号,都不要直接采样。
2.3 时钟数据恢复(CDR):没有时钟,一切都是白搭
这是SerDes里最核心、也最考验功力的部分。为什么需要CDR?因为高速串行信号里,发送端不会单独给你发一个时钟。你想想看,如果每根数据线都配一根时钟线,那还叫什么“串行”?
所以,接收端必须从数据流里把时钟“挖”出来。这就是CDR干的事。
2.3.1 CDR的基本原理
CDR的核心思想很简单:数据信号本身就有跳变沿,这些跳变沿里就藏着时钟信息。比如一个0101交替的信号,每个bit都有一个上升沿或下降沿。CDR就是利用这些边沿,去调整本地的一个压控振荡器(VCO),让它和发送端的时钟同频同相。
典型的CDR结构包含三个部分:
- 鉴相器(PD):比较数据边沿和本地时钟边沿的相位差。
- 环路滤波器(LF):把相位差信号平滑成控制电压。
- 压控振荡器(VCO):根据控制电压调整输出时钟的频率和相位。
这三者形成一个负反馈环路。说白了,就是不断“追”数据的边沿,直到锁定。
关键指标:
- 锁定时间:从开始到CDR稳定输出时钟需要多久。我见过有的芯片要几百微秒,有的只要几微秒。
- 抖动容限:CDR能容忍多大的输入抖动而不失锁。这个指标在高速设计中特别重要。
- 频率捕获范围:CDR能锁定的输入数据频率范围。一般要求能覆盖±100ppm以上。
2.3.2 常见的CDR架构
实际工程中,CDR主要有两种实现方式:
| 架构类型 | 优点 | 缺点 | 典型应用 |
|---|---|---|---|
| 基于PLL的CDR | 结构成熟,抖动性能好 | 锁定时间长,对长连0敏感 | PCIe、SATA、USB3.0 |
| 基于过采样的CDR | 锁定快,无需VCO | 功耗高,需要多相时钟 | LVDS、低速SerDes |
| 基于相位插值的CDR | 锁定快,面积小 | 相位噪声较大 | Xilinx GTH/GTY |
我个人最常用的是基于相位插值的CDR,因为Xilinx的SerDes硬核里内置了这个功能。你只需要配置好参考时钟和环路带宽,剩下的交给硬件。
2.3.3 数据编码对CDR的影响
这里有个坑——如果数据流里出现连续多个相同的bit(比如00000000),CDR就找不到跳变沿了。没有跳变沿,VCO就会“自由跑”,频率慢慢漂移。等后面数据变了,CDR可能已经失锁了。
所以,SerDes系统必须对原始数据进行编码,保证数据流中有足够的跳变沿。最常见的编码方式有:
- 8B/10B编码:每8位数据编码成10位,保证最多连续5个相同的bit。PCIe、SATA都用这个。
- 64B/66B编码:每64位数据编码成66位,效率更高。10G以太网用这个。
- 扰码(Scrambling):用伪随机序列对数据进行异或,让数据看起来更随机。SAS、SATA也用。
避坑指南: 我曾经在一个项目里用了64B/66B编码,但没注意CDR的环路带宽设置。结果数据流中偶尔出现长连0时,CDR就失锁了。后来我把环路带宽从1MHz调到5MHz,问题就解决了。记住:环路带宽越宽,锁定越快,但对抖动的抑制越差。这是个trade-off。
2.4 知识体系总览
下面这张图,我把本章的核心逻辑串起来了。你可以看到,从并行到串行,再到CDR恢复时钟和并行数据,整个链路是闭环的。
嗯,这张图基本把本章的内容串起来了。从左到右是数据流,从下到上是时钟恢复路径。你仔细看看,CDR其实是个“闭环”——它从串行数据里恢复出时钟,再用这个时钟去采样数据,然后输出并行结果。
好了,这一章的内容就到这里。SerDes的原理听起来抽象,但说白了就是“并转串、串转并、再挖个时钟出来”。下一章我们会深入Vivado,看看怎么用IP核把这些原理变成能跑起来的硬件。
本章小结:
- 并行转串行:用移位寄存器,注意加载时序
- 串行转并行:需要字节对齐,常用逗号检测
- CDR:从数据边沿恢复时钟,PLL/过采样/相位插值三种架构
- 数据编码:保证跳变沿密度,避免CDR失锁
可可精品资料库