ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于SelectIO IP核的FPGA LVDS差分信号配置详解

基于SelectIO IP核的FPGA LVDS差分信号配置详解 做FPGA这些年LVDS是我打交道最多的差分信号没有之一。板子刚贴片回来的那个下午我把示波器探头夹在LVDS测试点上看着屏幕上应该出现却始终没出现的波形心里那根弦又绷紧了——做硬件调试的人都知道LVDS这东西看着只有两根线但它在Vivado平台上的配置链路从SelectIO IP核参数到XDC引脚约束再从内部时钟路由到PCB等长一环扣一环任何一步出岔子结果就是示波器上干干净净或者眼图烂成一团糊。这篇文章我打算把基于Xilinx SelectIO IP核的LVDS差分信号配置整个走一遍。从LVDS电气原理开始到Vivado里的具体操作再到引脚约束、时钟设计、板级调试最后捎带聊聊MIPI转LVDS和RS485这些差分近亲。适合刚接手LVDS接口项目、被SelectIO IP核一堆选项绕晕、或者正在为“Implement Design变红”发愁的朋友参考。我会把参数背后的道理和踩坑经历都写出来不是光给步骤。1. 3.5mA电流与100Ω电阻LVDS的电气原理决定了后面所有配置1.1 差分对里没有“高电平”V_OD和共模电压才是关键先纠正一个特别常见的误解很多人拿万用表去量LVDS的P线或N线对地电压发现一个1.2V一个1.2V就以为信号没起来。其实LVDS从来就不是“一根线对地是多少伏”的问题它所有信息都编码在两根线的电压差上。LVDS发射端本质上是一个恒流源典型电流是3.5mA。电流从P线流出经过接收端的100Ω终端电阻再从N线回来。欧姆定律一算3.5mA × 100Ω 350mV这就是接收端看到的差分电压摆幅。当逻辑“1”时P线比N线高350mV逻辑“0”时反过来N线比P线高350mV。这个差值在标准里叫V_ODOutput Differential Voltage正常范围大约在250mV到450mV之间。那高值和低值到底是多少如果你查LVDS的直流参数表会看到类似这样的对应关系参数典型值说明V_OD差分输出高电平350mVP线电压减去N线电压V_OD差分输出低电平-350mVN线电压减去P线电压V_CM共模电压1.2V两根线电压的平均值V_OH / V_OL约1.375V / 约1.025V单根线对地电压范围注意表格里最后一行——单根线对地电压始终在1V到1.4V这个区间晃荡看起来就像“没信号”。所以调试LVDS必须用差分探头或者用示波器的A-B数学通道用两根普通探头分别接P和N再相减。如果你只有一根探头看到的就是一条1.2V附近的直线什么都判断不了。理解了V_OD和共模电压后面很多配置选项就自然通了。为什么Xilinx的引脚约束要选IOSTANDARD LVDS_25而不是LVDS本质就是电气标准不同LVDS_25的共模电压和供电要求与LVDS有差异选错直接违反器件电气规范。1.2 HR Bank还是HP Bank选错银行后面的活儿全白干7系列FPGA的IO Bank分两类HPHigh Performance和HRHigh Range。HP Bank优化了高速接口性能VCCO电压典型支持1.8VLVDS这种低摆幅标准在HP Bank上性能最好HR Bank支持更宽的VCCO范围1.2V到3.3V方便兼容各种单端电平但高速差分性能不如HP。实际项目中很多人在这里栽跟头。我记得有个项目板子上一路LVDS时钟从ADC来速率1.2Gbps结果被工程师随手分配到了HR Bank跑起来就是不稳定时好时坏。后来把引脚挪到HP Bank问题消失。这不是玄学是HR Bank的I/O驱动器和封装寄生参数对这么高速率的差分信号实在不友好。在Vivado里做引脚分配时建议先用芯片封装的引脚图把人机交互界面的Bank类型标注看清楚。如果你的设计对速率要求不高比如LVDS屏的像素时钟只有几十MHzHR Bank用LVDS_25也不是不行很多开发板就是这么干的。关键是要知道自己用的Bank是哪种再决定IOSTANDARD选项。这个决定要在原理图阶段就做不要等到PCB画完了才在Vivado里纠结。2. SelectIO IP核配置从创建实例到信号正确落地的完整过程2.1 先算数据率再谈配置并行宽度、串行因子和时钟的关系打开Vivado在IP Catalog里搜索SelectIO会看到SelectIO Interface IP核。很多人一上来就点点点完全没想清楚自己要什么。我建议先停下来拿笔算一下数据率。举个最常见的场景ADC输出5路LVDS数据每路串行速率是800Mbps加一路随路时钟400MHz。FPGA内部逻辑跑不了800MHz所以必须做串并转换把串行高速数据变成并行低速数据。Serialization Factor串行因子就是干这个的。如果设成8那么并行侧的时钟就是 800Mbps ÷ 8 100MHz并行数据宽度8bit。这个关系必须提前算清楚否则IP核生成的时钟频率跟你预期对不上后面全乱。再举一个LVDS屏的例子屏幕分辨率1920×108060Hz估算像素时钟约148.5MHz每个像素RGB各8bit数据通道用了4组LVDS差分线每组要承载约37.125MHz × 8 297Mbps串行因子设7并行时钟42.4MHz左右。不同的屏规格书会给不同的映射方式先画一张表差分通道编号、数据映射、随路时钟频率、串并因子。画完再开IP核效率高得多。2.2 IP核界面里每个关键选项的取舍逻辑在Vivado里新建SelectIO IP核实例后主要配置页面有几个关键项我的建议如下Interface DirectionReceiver、Transmitter还是Bidirectional这个不用犹豫按项目需求选。ADC采集就是Receiver驱动LVDS屏就是Transmitter。I/O StandardLVDS还是LVDS_25。前面说过看Bank的电平和器件要求。7系列里LVDS通常用于HP BankVCCO 1.8VLVDS_25用于VCCO 2.5V的Bank。如果你不确定打开器件引脚规划界面选中引脚后动态查看VCCO。Differential Termination也就是DIFF_TERM。这个选项问的是要不要把100Ω终端电阻做在FPGA芯片内部。对接收端来说强烈建议使能。LVDS规范要求接收端必须有100Ω终端电阻如果不使能内部端接你就得在原理图上的P和N之间自己放一个电阻放的位置不对还会引入stub。Xilinx内部端接已经是成熟方案我在多个项目里实测没问题。需要注意的是有些Bank/标准组合不允许内部端接IP核会直接变灰或者报错这时候就要检查原理图。Data Width / Serialization Factor上面已经算过按照并行宽度设。这里还有一个Clock Strategy或者类似的选项简单说就是决定用BUFIO还是BUFG来处理时钟选“Use BUFIO”通常性能更好后面第4章详细讲。IDELAY/ODELAY如果数据线和时钟线之间出现了走线长度差导致采样窗口偏移就需要用IDELAY做微调。我的经验是PCB等长做得好同一组差分线误差控制在±5mil以内大部分时候可以不开IDELAY。但如果你的板子layout已经很极限或者连接器、线缆引入的延时偏差大老老实实把IDELAY组件使能进去后面调试会轻松很多。注意SelectIO IP核的IDELAY是固定延时还是可动态调整要看具体版本支持动态调整一般需要额外控制接口。2.3 生成了IP之后接口信号该怎么连IP核生成后很多人盯着那一堆端口发呆。其实接收方向最核心的就三组// 接收侧典型端口示例具体以生成的IP为准 input wire lvds_rx_p, // 差分P端 input wire lvds_rx_n, // 差分N端 output wire rx_clk, // 并行侧时钟 output wire [7:0] rx_data // 并行侧数据如果你只接了lvds_rx_p、lvds_rx_n然后把rx_data直接接到用户逻辑再把rx_clk接给某个always块做触发时钟大概率会看到数据错位。为什么因为rx_clk与rx_data之间的相位关系是有讲究的IP核内部已经帮你做了ISERDES和时钟对齐但并行数据输出的时序窗口需要你按照IP核手册里的时序图来接。比如有些IP核用了BitSlip机制rx_data的bit顺序需要在帧同步后调整。我的建议是直接看IP核生成的example design跑一下仿真用ILA抓一下rx_clk上升沿时rx_data的跳变状态心里就有数了。不要凭猜。很多工程师抱怨“IP核输出的数据是乱的”结果最后是没看数据手册里bit顺序的说明。另外如果项目里只是简单路过一个差分信号不想用整个IP核也可以用原语直接拼。接收侧用IBUFDS ISERDESE2发送侧用OBUFDS OSERDESE2。SelectIO IP核本质上就是把这些原语封装好加点时钟管理和参数界面。用原语更轻量但要自己管理BUFIO、BUFG和地方适合熟练工用IP核适合绝大多数项目也方便维护。我的习惯是3路以内差分通道用手写原语通道多了上IP核否则工程代码里SERDES复制的到处都是可读性太差。3. 引脚约束和DRC排查工程从这里开始变红3.1 一份能过约束的XDC写法与端口命名规范LVDS的引脚约束核心就是给差分对的P端和N端分别指定封装引脚并且指定IOSTANDARD。一个典型的XDC片段长这样# 差分接收端口 set_property PACKAGE_PIN AE6 [get_ports lvds_rx_p] set_property PACKAGE_PIN AE5 [get_ports lvds_rx_n] set_property IOSTANDARD LVDS_25 [get_ports lvds_rx_p] set_property IOSTANDARD LVDS_25 [get_ports lvds_rx_n] set_property DIFF_TERM TRUE [get_ports lvds_rx_p] set_property DIFF_TERM TRUE [get_ports lvds_rx_n]这里有个容易被忽略但特别重要的点端口命名。如果你的顶层端口名字带_p和_n后缀比如lvds_rx_p和lvds_rx_nVivado通常能自动识别为差分对约束时可以只写P端N端自动配套。但保险起见我习惯于把P和N都写全避免因为命名不规范导致Vivado把p口和n口当成两个独立的单端引脚那样DRC一定会报错。另一个坑不要把P和N弄反。LVDS接收端如果P/N接反了收到的数据会全部反相看起来就是全0或全1。排查方法很暴力——用示波器A-B看差分波形如果反转了直接把XDC里两个PACKAGE_PIN对调重新布局布线五分钟搞定。在设置IOSTANDARD之前一定要确认FPGA Bank的VCCO电压域。比如你选LVDS_25但这个Bank的VCCO实际是1.8VVivado在Implementation阶段会报IO标准与Bank电压不匹配的错误。这类错误一般都能在Message窗口里直接看到但前提是你编译了。很多人连编译都没跑就直接上板自然什么都发现不了。3.2 从RTSTAT-2到Implement变红排查DRC问题的完整思路很多朋友遇到“Implement Design变红”就慌其实大部分时候问题不在于逻辑代码而在于约束和资源分配。打开Vivado窗口里的Reports找DRC报告重点关注类型带Timing或URBANUnrouted/Unconstrained开头的条目。像RTSTAT-2这类DRC报错通常出在时钟约束状态上。常见的情况有三种第一种XDC里写了create_clock但这条时钟信号实际没有从合法引脚进入FPGA或者时钟生成器的某个BUFG没有正确连接。Vivado检查时发现约束指定了时钟但内部找不到对应的时钟节点就会报出时序约束失效的DRC错误。解决方法是打开Schematic追踪这条时钟路径看从IBUFDS到MMCM/PLL再到BUFG中间有没有断线。第二种多个约束同时作用在一个时钟域上产生了冲突的时钟定义。这种情况在多人协作的工程里特别常见有人加了一条set_input_delay另一个人又用不同的参考时钟定义了一遍Vivado就只能报DRC。建议把约束文件精简时钟相关约束放在同一个XDC里并且用set_clock_groups明确不同时钟域之间的关系。第三种与LVDS相关的管脚约束有遗漏。比如只约束了P端没约束N端或者IOSTANDARD不一致。这种错误Vivado有时不会在综合阶段报而是等到布局布线发现I/O电平和Bank配置有冲突整个工程就红了。排查DRC整条链路我的习惯是先看DRC Summary按严重程度排序从Error开始。双击报错条目Vivado会自动跳到相关的XDC文件或Schematic位置。确认是约束缺失、约束冲突还是IP的时钟网络没接对。不要只改一行就重新跑要看这个DRC是否和之前报错之间存在因果关系——经常修了AB就自动消失了。4. 时钟是LVDS的灵魂随路时钟到底该怎么安排4.1 为什么不能用BUFG把随路时钟直接送全局LVDS接收通常带一路随路时钟DDR Clock或者SDR Clock它和数据一样从引脚进来经过IBUFDS变成单端时钟。这时候很多初学者习惯性地加一个BUFG把它送上全局时钟网络然后所有逻辑都用这个时钟。看起来没问题实际高速项目中这就是隐患的开端。为什么因为LVDS数据是源同步的数据信号和随路时钟在PCB上是并行走线到达FPGA引脚的时间偏差小但进入FPGA内部之后如果数据走ISERDES、时钟却绕了一大圈BUFG再回来时钟和数据的到达时间关系就飘了。BUFG适合送全局低频时钟或跨时钟域信号不适合直接作为高速差分接口的IO时钟。正确的做法是在接收侧使用BUFIO。BUFIO是I/O Bank专用的时钟缓冲器它直接连接IO逻辑比如ISERDES延迟极低保证时钟和数据的相位关系在进入IO资源时保持一致。Xilinx在7系列里专门为源同步接口设计了这套结构不用白不用。4.2 BUFIO、BUFR、BUFG的协同一个完整的接收时钟示例一个典型的LVDS接收时钟方案是随路时钟从引脚进入先过IBUFDS变成单端这个时钟同时送入BUFIOBUFIO输出直接驱动ISERDES的CLK用来做高速串行数据采样同时送入BUFRBUFR内部可以对这个时钟做分频例如÷4或÷8输出并行侧时钟驱动后续FPGA逻辑如果并行数据要跨Bank或进入时钟域交叉逻辑再接BUFG把并行时钟送到全局网络。这样做的好处是高速串行部分的采样时钟路径最短并行部分再用BUFG铺开各司其职。IP核内部如果选了合适的Clock Strategy它自己会生成这套结构你只需要在顶层把rx_clk的BUFG版本给用户逻辑用rx_clk_div给到并行数据寄存器。发送侧和接收侧对称并行数据在FPGA逻辑侧以并行时钟写入OSERDES串行侧用BUFIO驱动的bit clock把数据从OSERDES移出最后经过OBUFDS送出差分电平。工程上做LVDS发送时最常犯的错就是bit clock没有走BUFIO导致OSERDES输出时序不满足眼图中间有毛刺。4.3 跨Bank和IO时钟约束的实际处理如果你的LVDS引脚分布在多个Bank每个Bank有自己的BUFIO/BUFR资源跨Bank的并行数据合并时一定经过BUFG统一做时钟域同步否则两边并行时钟可能来自不同的BUFR相位差不定逻辑上就会出现随机错误。时序约束上至少要有这么几条# 随路时钟进入频率400MHz create_clock -name lvds_clk -period 2.5 [get_ports lvds_clk_p] # 并行侧时钟通常由PLL/MMCM产生或者由BUFR分频得到不需要额外create # 但需要设置输入延时窗口 set_input_delay -clock lvds_clk -max 0.8 [get_ports lvds_data_p*] set_input_delay -clock lvds_clk -min -0.2 [get_ports lvds_data_p*]这里的set_input_delay数值要根据芯片数据手册里ADC输出数据和随路时钟的相位关系来确定。我见过很多工程直接把这两个数写成0时序报告自然一片红。写约束之前花十分钟读ADC或屏体驱动芯片的时序参数算出setup/hold窗口再填进去比瞎试快得多。5. 板级调试与信号完整性眼图张不开时怎么办5.1 示波器正确测量LVDS的姿势板子调不通第一件事是量信号。量LVDS有几个硬性要求尽量用差分探头。如果实验室没有用两根同型号同长度的无源探头通道1接P通道2接N然后示波器数学通道选A-B。注意两根探头的地线要用最短的接地弹簧不要用带长地线夹的探头否则地线回路引入的噪声比信号本身还大测出来的波形惨不忍睹——这不是板子信号差是测量方法错了。判断LVDS正常与否看两个一个是V_OD是否在250mV~450mV范围。如果只有100mV甚至更低先查终端电阻是不是没接上或者内部端接有没有使能。再查驱动端电流源是否正常工作很多LVDS驱动芯片的使能引脚悬空会导致输出电流为0。另一个是共模电压是否稳定在1.2V左右。如果共模明显漂移可能信号源和接收端没有共地或者电源纹波过大。5.2 一次眼图降速排查的真实复盘之前做过一个项目FPGA接收来自ADC的LVDS信号串行速率2Gbps。上板后功能完全不对用示波器看眼图结果发现眼睛完全闭合中间一团黑影。第一反应是怀疑SelectIO IP核配置错了反复检查IOSTANDARD和端接确认没问题。接着看时序报告setup/hold有一点违例但不多。然后开始降速验证把ADC采样率降一半串行速率降到1Gbps眼图依然闭合再降到500Mbps勉强能看出眼睛形状降到100Mbps眼图终于漂亮了。这个结果说明问题不在逻辑时序而在物理链路。拿放大镜检查PCB发现LVDS差分对在靠近连接器的地方为了绕等长连续打孔换层而且有一段stub特别长——那就是罪魁祸首。高速差分信号经过阻抗不连续点反射叠加眼图直接压扁。后来改了走线把stub削掉2Gbps眼图重新张开。这件事给我的教训是当你降速之后功能恢复大概率是信号完整性不是逻辑问题。反过来如果降速了功能依然不对那优先查约束和数据对齐比如IDELAY设置、BitSlip状态、时钟相位是否反了。调试LVDS还有一种快速手段在Vivado里用ILAIntegrated Logic Analyzer抓FPGA内部并行数据。ILA抓不到引脚上的差分模拟信号但能看SERDES之后的数据pattern。如果ILA里的数据反复出现固定错位比如总是额外移了1bit那不是物理层问题是SERDES对齐或时钟分频没弄对。5.3 上电时序和端接电阻的隐藏坑LVDS调试时有个很少被人提的坑电源共模。FPGA的LVDS bank和发送端的芯片如果供电参考不一致共模电压可能超出接收端允许范围导致接收端判断逻辑失衡。检查时用示波器直流耦合量P和N的平均值两个数应该差不多如果有明显偏差重点检查参考地和反馈电容。另外端接电阻不是越多越好。Xilinx内部有DIFF_TERM时外部如果又并了一个100Ω终端电阻等效端接就变成50Ω差分信号形状直接畸变。所以同一个LVDS接收端内部端接和外部端接只能选一个。这个在原理图评审时就要写清楚别等贴片回来再改。6. 从FPGA到嵌入式平台LVDS在MIPI转接和RS485等场景中的迁移6.1 Linux平台上MIPI转LVDS的典型用法我们做FPGA的经常要跟嵌入式Linux平台联调。这几年RK3566、i.MX8这类处理器很常见它们原生接口多数是MIPI DSI但工控类显示屏又大量使用LVDS接口。解决方案就是加一颗MIPI转LVDS的桥接芯片。这种方案里Linux工程师关注的是设备树里MIPI DSI的时序配置、桥接芯片的初始化寄存器、LVDS屏的像素时钟等。对FPGA工程师来说需要理解的是“差分信号最终格式”是类似的数据差分对、时钟差分对、P/N极性必须匹配。桥接芯片数据手册里的LVDS映射表和你FPGA里SelectIO IP核发送的数据映射原理完全一致只是换了个平台底层都是把并行RGB数据按某种规则串行化到几组差分对上。如果你在FPGA侧调过LVDS看这类桥接芯片的规格书会非常轻松。6.2 差分信号是一大类别把RS485和LVDS混为一谈RS485也是差分信号新手很容易搞混。但RS485和LVDS本质差别挺大LVDS是低压摆幅、高速短距、点对点RS485是较大压差典型±1.5V到±5V之间、速率相对较低、支持多点总线拓扑能挂几十个节点。逻辑上都是看差分对的相对电压但电气参数和适用场景完全不同。如果你的总线设计里同时出现RS485和LVDS一定要分开规划别共用一组线或者混用收发器芯片。FPGA的SelectIO不支持RS485这种大摆幅差分信号一般需要外接RS485收发芯片FPGA侧只需要输出标准的单端UART或自定义逻辑信号。从这些场景能看出差分信号的本质万变不离其宗永远关心“两线之间的电压差”而不是“单线对地电压”。理解了这一句从FPGA的LVDS调到嵌入式平台的MIPI转LVDS再去看RS485思路都是通的。最后再分享一个小习惯每次烧写比特流之前我会花三分钟在Vivado的I/O Planning视图里核对所有差分引脚的P/N分配和IOSTANDARD再检查一遍XDC里DIFF_TERM是否都使能了。这个习惯救了我很多次。LVDS项目出问题90%不在逻辑代码而在引脚约束、时钟路径和PCB物理层。先怀疑这些再回去查逻辑调试效率能高一截。
返回列表