尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

FPGA实战:XAPP585 7:1 LVDS接收与Serdes SDR串并转换详解

FPGA实战:XAPP585 7:1 LVDS接收与Serdes SDR串并转换详解 搞了十来年FPGA接口设计XAPP585这份应用笔记我前前后后翻过不下几十遍Lattice、Altera、Xilinx各大平台做7:1 LVDS接收绕不开的就是这份文档里讲的Serdes SDR模式1_to_7串并转换思路。这里的SDR是Single Data Rate单数据速率跟做软件无线电的Pluto SDR那个SDR完全是两码事追射频的同学别走错门。一句话说清楚本文要讲的事在一个普通IO引脚上把高速串行数据流按7个bit一组切出来还原成并行总线这就是XAPP585的核心命题。适合刚接手LVDS/DSI/摄像头串行接口、对SelectIO资源还不太熟的FPGA工程师阅读也适合老工程师复习一下底层硬件的对齐逻辑。1. XAPP585在解决什么问题7:1串行链路的接收困局1.1 显示和采集接口里常见的7:1链路很多TFT LCD屏、LVDS相机接口、FPD-Link传输甚至部分ADC/DAC的高速引脚用的都是同一种套路并行数据源侧把7根线收成1根线用比像素时钟高7倍的比特时钟沿数据线上把bit打出去接收端再“一根线还原成7根”。这种“7:1”结构的最大好处是减少物理连线比如传统RGB888屏光数据线就要20多根7:1之后差分对就几根线束成本和PCB面积显著下降。那为什么偏偏是7不是8历史原因挺有意思早期面板接口的并行总线常见是18bit、24bit RGB按3组7:1拆分正好形成3对差分线加1对时钟线传起来很规整。而像某些DSI接口支持的分组也有类似逻辑。7:1在视频接口里的地位基本等同于8b/10b在Serdes链路里的地位——约定俗成绕不开。1.2 为什么不能只用移位寄存器凑合看到“串并转换”很多人的第一反应写个移位寄存器模块里拿一个计数器采到7个bit塞进一个7bit寄存器然后并行输出。这个方案在50MHz以下可能还能跑一旦bit速率到几百兆问题全部显露。第一是路径延迟不可控。普通slice里的触发器和IOB里的引脚之间有布线延迟时钟树与数据路径的skew会随着布局布线变化你无法保证在高速下每个bit周期都满足建立保持时间。第二是时序收敛困难。移位寄存器在PR后报出violation时你只能到处加流水级越加越乱。第三是资源浪费。一个7bit移位位计数并行锁存在逻辑资源紧张的工程里纯属浪费。而XAPP585的思路完全不同把串并转换逻辑放进IOB内部的专用硬件Serdes资源里。这里的寄存器物理上紧贴引脚走线延迟极小采样窗口由FPGA厂商在硅片上做了匹配用户只负责提供正确的时钟和配置剩下的由硬件保证。2. 先分清两种SerdesIOB里的Serdes与GT收发器不是一回事2.1 SelectIO Serdes与GT Serdes的分工热词里有一条“GT Serdes物理层”跟XAPP585里讲的东西容易混。GT Serdes是Xilinx高速收发器硬核GTP/GTX/GTH/GTY那一族跑PCIe、万兆以太网、CPRI这类协议支持几十Gbps内部有PMAPCS还有CDR、均衡、加解扰这些PCS功能。SelectIO Serdes则是FPGA普通IO里的串并转换逻辑速率最多几百Mbps到1Gbps量级只负责基础的串并变换和位滑动没有CDR一般要依赖外部送来的随路时钟。对比项SelectIO SerdesGT Serdes所在位置普通IO Bank专用高速收发器引脚典型速率数百Mbps1Gbps~几十Gbps时钟恢复需外部随路时钟或PLL内置CDR可恢复时钟数据结构通常是裸数据位对齐支持8b/10b、64b/66b等编码配置难度较低重点是相位对齐较高涉及很多PMA参数XAPP585写的是前者属于SelectIO资源里最朴素的用法。如果拿着XAPP585的图去套GT Serdes那肯定要栽跟头。反过来也别指望普通IO能跑GT Serdes的速率物理层就不是一个级别。2.2 Spartan-3E的Serdes能干什么SDR模式红利在Spartan-3E那个年代IOB内嵌的Serdes支持两种工作模式DDR模式可以做到1:8SDR模式可以做到1:7。从7:1的视频链路来看SDR 1_to_7完美匹配不用再去拼凑多级逻辑。所谓SDR就是只在采样时钟的上升沿或下降沿采样数据每个时钟周期采1个bit7个bit刚好组成一个并行字。DDR则是上下沿都采一个周期采2个bit适合偶数分频的8:1链路。对于7:1信号SDR模式的采样时钟频率必须等于数据速率。假设像素时钟50MHz7:1后数据速率为350Mbps那你需要一个350MHz采样时钟。这个频率对Spartan-3E的IOB和全局时钟网络来说并不算高真正难的是保证采样点落在每个bit的眼图中央。3. 时钟架构DCM是1_to_7能不能收稳的命门3.1 1:7模式下需要哪几个时钟1_to_7串并转换器内部其实需要两个不同频率的时钟协同工作一个高速采样时钟叫bit clock用来逐个采样串行数据一个低速并行时钟叫word clock用来同步“7bit拼好之后”的输出。二者频率关系严格是7倍。外部输入的是什么时钟取决于信号源设计。常见有两种一种是源端只给并行像素时钟接收端自己用DCM/PLL把像素时钟7倍频得到bit clock另一种是源端直接给bit clock比如35MHz并行字时钟同时给245MHz采样时钟。两种方案XAPP585场景里都存在。更强的做法是只给像素时钟由DCM同时产生bit clock和word clock并且由DCM的LOCKED信号统一复位Serdes保证倍频稳定后才开始采样。3.2 相位选择采样点为什么要落在眼图中央串行数据在PCB上传输、经过IBUFDS进入FPGA后数据边沿和采样时钟之间一定存在一个不确定的相位偏移。如果采样时钟正好落在数据跳变的边沿附近触发器的建立/保持时间很容易不满足采出来的bit就可能是悬空态或者前一个bit、后一个bit。理想采样点永远是bit窗口的中心也就是眼图最开阔的位置。所以DCM不能只是简单倍频还要支持移相。Spartan-3E的DCM提供固定相移和可变相移两种调整手段XAPP585里推荐的做法是先通过静态移相粗调再在开机初始化阶段配合已知pattern扫描相位找到稳定区域后固定下来。7系列FPGA更灵活可以用IDELAYE2做动态延迟甚至加入扫描状态机自动训练眼图。3.3 用DCM做7分频和相移的具体思路假设外部输入时钟是像素时钟PIX_CLK50MHz需要bit clock350MHzword clock50MHz。DCM/DFS的配置大致可以这样CLKIN接PIX_CLK先通过CLKFB反馈保证输出同步CLK0输出50MHz word clockCLKX7输出350MHz bit clockCLK0还可以接DCM内部的CLKDV如果版本支持非整数分频或直接使用CLK0通过PHASE_SHIFT属性设置采样相位比如步长按周期/256先设一个中间值再实测微调用LOCKED输出作为Serdes模块的复位信号。注意bit clock和word clock必须走全局时钟树而串行数据引脚要走IOB直通路径不要绕到片内逻辑再返回否则延迟没法控制。数据引脚和时钟引脚的距离、Bank的VREF/端接都会成为相位偏移的一部分。4. 1_to_7转换机制7个连续采样如何拼成一个字4.1 输入路径从差分对到采样寄存器以LVDS输入为例信号从PCB进入FPGA后先经过IBUFDS_DIFF等差分输入原语把差分电平转成单端逻辑电平。之后直接进入IOB内部的Serdes采样模块。在Spartan-3E上这一步一般通过CORE Generator生成的serdes_1_to_7软核或者说宏来完成底层展开就是IOB里那组专用寄存器链。如果你用Spartan-6对应原语叫ISERDES27系列叫ISERDESE2本质一样。采样寄存器链的工作方式很简单每个bit clock上升沿把引脚上的当前电平移入第一位同时把原有数据向后移一位。连续7个bit clock上升沿后这7个bit刚好凑成一个完整并行字由word clock锁存到输出寄存器输出宽度为7bit的并行数据总线。4.2 并行数据格式和位顺序很多工程师在这里踩第一个坑串行发送端发的“第1个bit”到底是并行字的MSB还是LSB不同协议定义不一样有的先发高位有的先发低位。XAPP585里的Serdes宏通常会提供一个可选位顺序参数或者在输出端允许你做一个简单的bit重排。实际操作里我建议把“第一位是先发MSB还是LSB”这个信息单独作为一个常量写注释别想当然。曾经有人图省事以为所有屏都是先发高位结果出来图像左右错位排查了半天。4.3 SDR与DDR模式的取舍SDR 1_to_7模式的优势是采样逻辑简单只在一个边沿采样对时钟占空比要求没那么极端而且奇数分频天然避开了DDR必须处理上下沿对齐的麻烦。DDR 1_to_8常见于某些8:1的DSI链路上下沿都采样采样时钟频率只需数据速率的一半但也意味着对占空比失真、时钟歪斜更敏感调试难度更高。从实用角度说1_to_7用SDR是“协议选择”而不是“能力上限”。7:1这种奇数比用DDR做不做不了——上下沿都采的话一个周期是2个bit7不是2的整数倍没法一次性凑出整数并行字。所以SDR在这个场景不是退而求其次而是唯一正确选项。5. 字对齐BitSlip状态机和训练序列7选1的运气游戏5.1 为什么能转出数据但不一定转对假设我们已经稳定采出了7bit并行字如果发送端对“哪一位是第一位”没有约定接收端也无所谓那数据看起来没问题。但为了还原出正确的并行数据接收端必须知道“第1个bit”对应串行流的哪一个位置。上电时Serdes内部计数器从哪个bit开始完全是一个随机值有7种可能只有1种能让并行字和发送端的并行字边界对齐。不做对齐的话7个bit被循环移位图像会出现固定的错位甚至花屏。很多初次接触Serdes的人会不理解“我明明每次都是逢7输出一个word为什么数据不对”就是因为你没有训练对齐。前期手写逻辑的时候计数器归零的时机是随机的7种相位里未必正好是中奖那个。5.2 训练序列和BitSlip状态机解决方法是让链路带上“训练序列”。发送端在数据开头或每隔一段插入一个固定pattern比如7bit的1011010或者16bit的101010接收端用状态机去匹配这个pattern。状态机逻辑大致这样复位后清空并行输出等待数据稳定持续接收并行字每个字与同步pattern比较匹配不成功则触发一次BitSlip把当前并行字循环移位1bit重新比较匹配成功后进入LOCK状态并保持监测LOCK状态下每收到一个字继续做校验连续失败若干次则回到搜索状态。BitSlip在硬件里可能是原语自带的BITSLIP端口也可能只是一只桶形移位寄存器。底层没有该端口的时候可以在并行数据输出后加一个7选1的移位/旋转换器用状态机控制选位效果完全等价。这里有一条经验同步pattern千万别用全0或全1这种规则序列。数据链路空闲时本来就是全0容易假锁建议用类似0x6B、0x5A这类带多个跳变沿的pattern即使发送端没有固定训练序列也可以找帧起始信号比如HSYNC、VSYNC的前导来做。5.3 实际调试中怎么判断对齐成功最直观的做法是在逻辑分析仪ILA里抓并行数据和word clock的对应关系。训练成功后并行word应该有稳定的边界数据值要么等于发送端已知的pattern要么跟图像数据呈连续变化。如果发现并行数据整体循环移了k位那并行的bus里数据看起来是乱的但单bit翻看每个bit时钟下的采样序列又是“连续的、像样的”这往往就是缺对齐逻辑。判断失败还有一种隐蔽情况训练序列短数据随机内容碰巧匹配。工程上建议连续匹配2~3个word才宣布LOCK失锁判据也设成连续多个word不匹配才重新训练避免抖动造成的瞬时失锁。6. 从XAPP585移植到现代FPGA原语换代但原理不变6.1 Spartan-3E Serdes与ISERDESE2的对应如果还在新款FPGA上照抄Spartan-3E的宏大概率编译不过——原语名、端口、配置方式都变了。Spartan-6对应ISERDES27系列对应ISERDESE2UltraScale系列对应ISERDESE3。ISERDESE2更灵活支持1:2、1:4、1:6、1:8等多种模式主从级联后还能支持更宽的1:10、1:14。7:1这种奇数比例模式下需要把ISERDESE2配成1:8模式然后只用前7bit或者根据用户指南里的SDR 1_to_7支持表去配置。新系列里数据输出位宽永远是2的幂1_to_7不是原生直接支持需要自己做截断/循环移位原理与第4、5章的思路一致。原语/方案Capturing模式对齐手段备注Spartan-3E Serdes宏SDR 1:7用户逻辑BitSlip或桶形移位XAPP585主体Spartan-6 ISERDES21:2/1:4/1:8等BITSLIP端口注意主从级联7系列 ISERDESE21:4/1:8等BITSLIP IDELAYE2动态延迟很实用UltraScale ISERDESE31:8简化了时序模型高速性能更好6.2 跨时钟域处理Serdes模块输出的是word clock域的7bit并行数据和word clock本身而你的用户逻辑往往运行在系统时钟域。直接把word clock和sys_clk接在一起是不安全的两者频率、相位都不同。正规做法是在Serdes输出后面接一个异步FIFO写时钟用word clock写使能由word clock域有效标志驱动读时钟用sys_clk读出来的数据再进业务逻辑。FIFO深度一般16或32就够但要注意写使能信号至少要持续一个写时钟高电平周期避免亚稳态。很多人在这里省掉FIFO结果偶发花屏还以为是Serdes采错了。6.3 采样相位校准与量产考虑7系列及之后的FPGA有了IDELAYE2原语可以对输入数据引脚做精细的延迟调节比DCM移相更直接。做法可以做成一个开机自校准状态机从最小延迟开始每个延迟档位采一段已知pattern记录哪些档位“能采对”取中间档作为工作点。这个逻辑在实验室可能看不出差别温度20度电压稳定产线低温或大电流场景下就很重要。如果不想做动态校准至少在上电时把DCM/IDELAY的相位设置为“眼图居中”的经验值并留下软件寄存器手动旁路方便现场调试。7. 实测中排过的雷采样相位、同步复位、差分端接7.1 差分端接不到位眼图直接烂掉LVDS必须端接100Ω差分电阻位置越靠近接收引脚越好。很多早期板子为了省几个电阻把端接放在连接器远端或者干脆没放结果高速数据反射严重眼图畸形Serdes再怎么调相位都调不出稳定采样点。7系列FPGA在IBUFDS上可以开内部DIFF_TERM但Spartan-3E时代没有这个功能必须在PCB上焊。建议画板之前先查对应Bank是否支持片内端接不支持就预留外部电阻位。7.2 复位释放不干净Serdes状态机卡死Serdes模块通常有多个复位信号bit clock域复位、word clock域复位、还有后端业务逻辑复位。如果这些复位不是同步释放模块内部状态可能进入非法组合。最省事的做法是做一个复位桥用两个D触发器级联在每个时钟域内各自同步外部复位信号再把同步后的复位送给对应域。DCM的LOCKED信号也建议作为复位链的一环倍频还没稳定时不要让Serdes开始采样。7.3 假锁定和现场偶发花屏之前说过使用过短的同步pattern会假锁。现场还有一种常见问题是训练时环境温度低相位偏得不多能锁定量产后机房温度升高采样点漂移变大原来“刚好在眼图边缘”的工作点失效图像随机花一下又恢复。这种问题最难复现解决路径基本就是“上电训练相位扫描取中间值”。如果嫌状态机复杂也可以退而求其次在boot阶段固定写死一组相位用外部旋钮/软件配置去调但一定要在生产联调时做高低温摸底。7.4 BitSlip时机和word clock的关系BitSlip指令必须在word clock边界前后稳定再加不要赶在并行数据正在更新的时候发。否则会出现“当前word一半是旧边界、一半是新边界”的混合体导致状态机误判。稳妥做法是把BitSlip握手信号同步到word clock域等一个完整word稳定后再执行移位。8. 结尾一个值得分享的调试技巧上面写得很细最后分享一个我实际项目中救过大命的做法在硬件验证阶段不要直接抓真实图像数据先用FPGA内部产生一个计数器按7:1串行化发出去再回环到自己或另一颗FPGA的Serdes接收端——也就是所谓的loopback自测。回环数据放在固定pattern和递增计数器之间来回切换ILA端抓并行输出能快速确认“串并转换、字对齐、跨时钟FIFO”这三段链路是否都正常。如果自测没问题接真实信号源还是乱那问题大概率在外部端接、相位或训练pattern上。搞明白XAPP585的1_to_7本质就是理解三件事采样时钟相位能取到眼图中央7个bit能按固定边界拼成并行字训练序列能把随机起始点拉到正确位置。这套思路从Spartan-3E一路沿用到今天换个原语、换个端口名核心逻辑依旧扎实。希望这篇拆解能帮你少走一段我当时走过的弯路。
返回列表