ARTICLE DETAIL

资讯详情

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

FPGA引脚与Bank:从I/O Bank到GT高速收发器,原语实战避坑指南

FPGA引脚与Bank:从I/O Bank到GT高速收发器,原语实战避坑指南 最近翻看评论区发现不少读者困在同一个地方拿了块新板子按网上的教程写好了UART_RX、跑通了流水灯一旦想把 LVDS 屏或者高速 ADC 接上去就开始报各种 I/O 相关的错或者干脆怎么配都不出数。这些问题的背后几乎都指向同一组概念I/O Bank、GT Bank以及看起来像天书一样的原语。这一篇就把它们从头捋一遍。这篇内容和之前的 Part 系列一样默认你已经会写基本的 Verilog知道怎么建工程、加约束、跑仿真。本篇要解决的核心问题是三件第一FPGA 引脚为什么不是“随便选根线就能用”第二I/O Bank 里的 HD、HP、HR 到底是什么选型时怎么判断第三GT Bank 和 GTP/GTH/GTY 这套高速收发器家族该怎么理解。最后再把我自己踩过的坑、以及身边同事翻车最多的几个点整理成一份避坑清单。1. 为什么 FPGA 开发绕不开 Bank一个引脚背后牵一发动全身1.1 “Bank” 到底是物理概念还是逻辑概念很多教程说“FPGA 引脚是按 Bank 分组的”听起来像废话但它的实际意义比你想的大。Bank 首先是个物理概念FPGA 芯片外面一圈引脚被划分成若干个区域每个区域里的 IO 引脚、时钟引脚、参考电压引脚共享同一组供电和参考电路。Xilinx 的 7 系列里一个 Bank 大约有 50 个 User IO到了 UltraScale 系列高密度 Bank 的 IO 数量会更多。你在原理图或者封装图上看到类似A18、B21的引脚编号下面会标注它是属于哪个 Bank 的。Vivado 的 Device 视图里会把同一个 Bank 画成一个区块区块边界内的引脚颜色相同边界外就是另一个电压域。我一开始对这些区块不敏感直到有一次分配引脚时把一个 1.8V 电平的信号接到了某个 3.3V Bank 的引脚上结果那个脚实际输出电压被钳住了电平怎么都不对。查了老半天打开 Device 视图才发现那个引脚所在 Bank 的电压域根本不是我以为的那样。1.2 Bank 电压域所有问题的根源每个 Bank 都有独立的 VCCO 引脚部分新型号还支持 VCCIO 分段这个电压决定了该 Bank 里所有引脚的输出高电平范围。你给这个 Bank 供 3.3V那它的 LVCMOS33 输出就能正常到 3.3V你要是改成 1.8V那同样的引脚就只能按 LVCMOS18 来跑。同一个 Bank 内部的所有引脚电气特性必须保持一致。这里有个很常见的误解以为“只要电压匹配就行”。不是的除了 VCCO有些电平标准还需要 VREF 参考电压引脚比如 HSTL、SSTL 这类。VREF 在 Bank 内部或相邻 Bank 有专门引脚不能随便挥霍。还有终端电阻SelectIO 内部有可编程的片内端接比如 40Ω、50Ω、60Ω 系列但它依赖于 Bank 的供电状态不是你想配多少就配多少。1.3 引脚约束和 Bank 的关系写 XDC 约束时自然要写set_property PACKAGE_PIN但 PACKAGE_PIN 只是第一步。你在约束里同时还要写明IOSTANDARD比如LVCMOS33、LVDS25、HSTL_II。Vivado 会根据你选的 IOSTANDARD 去校验这个引脚所在的 Bank 是否支持该电平标准、VCCO 是否匹配。很多报错信息都是一大段英文其中最关键的一句通常是is not valid in a bank with VCCO...翻译过来就是这个 Bank 的当前供电不支持你选的电平标准。所以我的建议很直白拿到开发板或新板子的原理图第一步不是写代码而是把整板所有 Bank 的电压域拉一张表。每个 Bank 供电多少伏、哪些引脚接了按键/LED/串口/摄像头/PCIe全部列出来之后再做引脚分配心里就有底了。2. HD、HP、HR三类 I/O Bank 的定位差异与选型逻辑很多人在 7 系列里学到的是 HR 和 HP 两种 Bank。到了 UltraScale 系列比如 Kintex UltraScale、Zynq UltraScale又冒出来一个 HD Bank。这三兄弟如果把定位搞混后面选型会踩大坑。2.1 三者的核心参数对比先给一张我整理的对比表方便大家收藏备用Bank 类型全称典型电压范围支持的典型电平标准特点与适用场景HRHigh Range1.2V ~ 3.3VLVCMOS12/18/25/33、LVTTL、PCIe etc.电压范围宽适合连接各种各样的板级接口属于“万金油”HPHigh Performance1.0V ~ 1.8VLVDS、Mini-LVDS、HSTL、SSTL、LVCMOS18高速信号完整性更好适合 DDR、SerDes 接口、高速差分信号HDHigh Density1.2V ~ 3.3VLVCMOS、LVTTL、SSTL引脚密度高数量多适合低速并行总线但单引脚性能相对有限看到这个表你可能会问那 HD 和 HR 不都支持 3.3V 吗区别在哪区别主要体现在两个方面一是驱动能力和信号完整性二是封装上 HD Bank 通常是为了在有限面积里塞更多 IO 而设计的所以它的高速性能妥协了。你要是拿 HD Bank 的引脚去跑 200Mbps 以上的 LVTTL 总线虽然有时候能通但眼图质量会比 HR 或 HP 差不少。2.2 实际项目中怎么选从实战角度来看我一般会这样决策复位按键、UART、SPI Flash、低速 GPIO优先放 HR Bank。因为这类信号电平多变可能是 3.3V 的传感器也可能是 1.8V 的芯片HR 的宽电压范围最灵活。DDR3/DDR4 内存接口、LVDS 摄像头接口、HDMI、MIPI尽量放 HP Bank。HP Bank 对差分信号有更好的终端和延迟特性。很多开发板的 DDR、HDMI 默认连到 HP Bank这不是巧合。大位宽并行外设比如 FPGA 与 DSP 之间的 EMIF 接口、并行 ADC 接口如果信号速率不算很夸张但数据位宽动辄 16 位、32 位甚至更多引脚不够用的时候就去翻 HD Bank。HD Bank 就是为高密度场景准备的。有一种情况你必须特别小心如果某个 Bank 本身是 HP但板级设计只给了 1.8V 供电那你就没法在这个 Bank 上用 2.5V 或者 3.3V 电平的标准。同理HR/HD Bank 虽然允许 3.3V但 Xilinx 对某些出差分标准会限定时序性能。2.3 一种容易误判的情况LVDS 到底该放哪个 Bank很多人在 LVDS 摄像头接口上翻过车。网上的教程说 LVDS 要用差分引脚但我见过有人把摄像头接到 HR Bank 上结果也出图了。于是新手就松了一口“反正都能用”。实际上LVDS 在 HR 和 HP Bank 都支持但需要看清楚具体的标准名称比如 LVDS_25 和 LVDS_18。简单说1.8V 供电的差分接口用 LVDS_18 或 Mini_LVDS常见于 HP Bank 和部分 HR Bank。2.5V 供电的差分接口用 LVDS_25一般要求 HR Bank 或 HD Bank因为它的 VCCO 需要 2.5V 甚至 3.3V 配合。关键是看芯片手册的 Bank 电压要求而不是只看“LVDS 三个字母”。我见过不少人把 LVDS_25 配到一个 HP Bank 上编译通过了上板后偶尔丢数最后发现是差分摆幅不够。这种“偶尔丢数”是最难查的故障因为不是完全不通而是信号质量差导致误码。3. GT Bank 与高速收发器家族从 GTP、GTH 到 GTY接着讲另一个维度的 Bank——GT Bank。I/O Bank 负责通用数字信号GT Bank 负责的是串行高速收发器。这里面的概念比普通 IO 高一个台阶但逻辑上并不复杂。3.1 为什么单独要一组“GT Bank”普通 I/O 引脚的最高速率有一定上限。DDR 并行接口虽然速率看着不低但布线难、引脚多、同步复杂。于是 FPGA 内部引入 SerDes 收发器把并行数据在芯片内部串行化再从一对差分引脚上传出去。这样一对引脚就能跑到几 Gbps 甚至几十 GbpsPCIe、千兆/万兆以太网、SFP、JESD204B 这些接口都建立在它之上。这些收发器在 FPGA 里并不是散落在每个 Bank 的而是集中放在专门的 GT Bank 中。GT Bank 里有收发器通道、锁相环、参考时钟输入。以 Xilinx UltraScale 系列为例GT Bank 一般以 Quad 为单位Quad 里面有四条收发器通道每个 Quad 还对应一组参考时钟引脚比如GTREFCLK0、GTREFCLK1。3.2 GTP、GTH、GTY不是越贵越好要匹配传输速率我们常听到的 GTP、GTH、GTY是不同系列的收发器名字也可以理解成速率等级不同收发器常见器件系列典型最高线速率典型应用GTPArtix-7约 6.6GbpsPCIe Gen1/2、SATA、千兆万兆以太网GTXKintex-7 / Virtex-7约 12.5GbpsPCIe Gen3、10G 以太网GTHKintex-7 高端 / Virtex-7 / UltraScale约 13.1~16.3GbpsJESD204B、25G 以太网拆分为多通道、CPRIGTYUltraScale / Versal 部分型号约 25.78~32.75Gbps25G/100G 以太网、高性能 ADC 采集板、PCIe Gen4注意这里说的“不同器件系列支持不同收发器”不是绝对比如 Kintex UltraScale 是 GTHKintex UltraScale 是 GTH 和 GTY 并存。最稳妥的查法是用 Xilinx 官网的选型表或者看你要用的芯片具体型号手册。很多新手选型时容易陷入“速率越高越好”的误区。GTY 虽然快但功耗、封装复杂度、 PCB 布线难度都成倍上升。如果只做千兆以太网GTH 已经完全够用如果做 JESD204B 高速 ADC速率在 5~12Gbps 区间GTH 是性价比王者。不要把全家桶都上到顶配那只会给自己找麻烦。3.3 GT Bank 里的“参考时钟”和普通时钟不是一个东西这是新手最容易懵的地方。普通逻辑时钟可以来自板上的晶振直接进MRCC或者SRCC引脚。但 GT 收发器的参考时钟有专用的引脚GTREFCLK。它的用途是给收发器内置的锁相环QPLL 或者 FCPLL提供参考频率然后经过倍频/分频生成线路速率。比如你要跑 10.3125Gbps 的以太网参考时钟常见选 156.25MHz经过锁相环倍频到线速率。GT 参考时钟必须是干净的低抖动时钟。如果你图省事把 GTREFCLK 引脚接到一个普通有源晶振有时候也能跑但误码率可能高到让你怀疑人生。尤其是 10G 以上的线速率参考时钟抖动对眼图影响极大。我自己的做法是如果板上没有专门的 GT 参考时钟优先用 FPGA 内部的时钟管理器把干净的时钟引到 GTREFCLK 的专用输入实在不行也要选低抖动晶振并且布线时避开开关电源区域。4. 原语是 FPGA 的“底层 API”从 IBUF/OBUF 到 GT 原语4.1 原语到底是个什么鬼原语Primitive可以理解成 FPGA 底层资源的“官方 API”。你写 Verilog 时用的是assign led ...综合工具最后会把它映射成 FPGA 内部的查找表和触发器。但有些底层能力直接用 HDL 是绕不过去的比如驱动一个差分输出、读取一个高速串行通道。这时候就要例化原语模块。Xilinx 的原语一般以IBUF、OBUF、BUFG、IOBUF、IBUFDS、OBUFDS、IDELAYE2、OSERDESE2等命名。你直接在 Verilog 里写OBUFDS #(...)综合工具就知道你要用一个差分输出缓冲器会调用对应的硬资源。我见过很多新手在论坛里问“obuf原语是什么”其实就是 Output Buffer 的缩写。你可以把它看成一个引脚驱动器。你写led data的时候没有显式例化 OBUF但综合工具会自动帮你插进去。平时不用写原语因为你写的逻辑会自动推断但当你需要控制电平标准、差分对、驱动能力时就得显式地把它写出来。4.2 一个最常用的例化差分输出 OBUFDS很多项目要输出一对差分信号比如把调试用的串口数据转成 LVDS 给示波器看。此时如果直接写assign p_out data; assign n_out ~data;也不是不行但这样生成的差分对不走专用差分输出缓冲延迟和驱动能力会差一些。正确做法是OBUFDS #( .IOSTANDARD(LVDS_25), .SLEW(SLOW) ) obufds_inst ( .O(p_out), .OB(n_out), .I(tx_data) );这里的.O和.OB是两个互补输出分别对应差分对的 P 和 N 引脚。IOSTANDARD 必须和 Bank 电压、引脚约束匹配。你在 XDC 里只需要约束一个引脚Vivado 会自动把差分引脚对放好不需要给 N 端单独写约束。4.3 输入侧原语IBUFDS 与 GT 参考时钟有输出就有输入。差分输入引脚进入 FPGA 内部时要经过 IBUFDSInput Buffer for Differential Signals。在高速 GT 场景参考时钟的输入不是普通 IBUFDS而是更专用的原语比如 7 系列用IBUFDS_GTE2UltraScale 用IBUFDS_GTE4。这些原语的例化模板一般在 Vivado 的 Language Template 里都有不建议手敲因为端口太多手敲容易漏一个。我实际开发中经常会写一个小模块把IBUFDS_GTE4包起来对外提供干净的时钟输出和复位信号这样上层逻辑就不用关心底层原语细节。类似的封装思路也适用于 GS 输入/输出差分对。4.4 GT 原语看起来几百个端口其实有规律GT 收发器原语是令多数人恐惧的东西。以 UltraScale 的GTYE4_CHANNEL为例例化模板一展开有几百个端口。看着头皮发麻但实际上这些端口分四类时钟类TXUSRCLK、RXUSRCLK、TXOUTCLK、RXOUTCLK、REFCLK。这是收发器的命脉。数据类TXDATA、RXDATA一般位宽与内部用户时钟宽度相关。控制类TXRESET、RXRESET、TXPD、RXPD、PLL 锁定信号。状态类TXSTATUS、RXSTATUS、误码检测、热插拔指示等。我们在实际开发中很少手写几百个端口。更常见的是用 Xilinx 的 Transceiver Wizard IP 核配置出所需的线速率和协议然后让 Vivado 自动生成收发器逻辑。但你要看懂它生成的例化代码里哪些端口在起作用尤其调试的时候追数据出在哪里慢一拍就是靠读这些端口的波形。有一点想提醒大家Transceiver Wizard 生成的工程里gt_reset和data_sync这类信号有很强的时序要求。不要直接把它当普通信号随手复位。很多“GT 通道初始不稳定”的问题根源都是复位时序不对而不是收发器本身挂了。4.5 结合 testbench 验证原语行为既然是仿真原语也需要有仿真模型。Vivado 自带的仿真库里有所有原语的仿真模型不需要额外安装。所以你在 testbench 里可以直接例化原语然后给输入端口灌激励。比如你用 IBUFDS 做差分输入可以在 testbench 里给p_in和n_in分别冲击值观察内部o的输出。timescale 1ns/1ps module tb_top; reg p_in; reg n_in; wire o; IBUFDS #( .IOSTANDARD(LVDS_18) ) u_ibufds ( .O(o), .I(p_in), .IB(n_in) ); initial begin p_in 0; n_in 1; #10 p_in 1; n_in 0; #10 p_in 0; n_in 1; #20 $finish; end endmodule仿真里你会看到差分输入经过 IBUFDS 后内部输出o基本跟着 p_in 的电平变化。这就把一个底层原语的行为可视化出来了。以前有个读者写 UART_RX 仿真一直说收不到数据后来才发现他的差分管脚在顶层没用 IBUFDS而是直接把两个引脚分开处理了全到了错误的仿真路径上。仿真虽然能过但上板完全不是那么回事。5. 避坑指南这几类坑我替你先踩了5.1 Bank 电压不匹配最常见且最难定位的“软故障”这一类故障的可怕之处在于——它不报编译错误你上板调半天都发现不了。举个例子某块 Zynq UltraScale 开发板上某个 HP Bank 只供了 1.8V。你在这个 Bank 上接了一个 3.3V 的 SPI Flash信号线上越高电平上不去参数读回来全是0xFF或者随机数。你一开始怀疑时序怀疑代码甚至怀疑 Flash 芯片坏了最后才发现是 Bank 电压域不匹配。我的建议是硬件设计阶段就要在原理图上标注每个 Bank 的电压范围画 PCB 时同步列出引脚分配表然后软件工程师拿到板子时先对照着看一遍。如果是成品开发板去官网下载一个引脚定义表或 Bank 电压表打印出来放桌边。这个表比任何教程都管用。5.2 差分引脚的 N 端不是普通 IO很多 FPGA 新手拿到 LVDS 摄像头想当然地挑了两个相邻普通引脚就复用为差分。这是不对的。Xilinx FPGA 上差分引脚对是固定的组合一个 Bank 里面引脚M5和M6可能组成一对但M5和N5不一定是一对。你需要看封装的大表格里面会列出每个 Bank 里哪些引脚组成差分对。还有一个常见坑差分对的 N 引脚不能当普通单端 IO 随意使用。有的 FPGA 型号上差分负端确实有复用功能但它受到约束和封装限制不是你想用就能用的。所以不要轻易把 N 引脚拿去接 LED 或者其他什么控制信号一旦后续要改回差分接口Layout 又要返工。5.3 GT 参考时钟分配与复用GT Bank 里每 4 条收发器通道组成一个 Quad同一个 Quad 的参考时钟可以从专用引脚进也可以由相邻 Quad 共享这取决于器件的时钟路由能力。很多人忽略了这一点在做约束时把自己定义的 GT 时钟接到任意普通时钟引脚结果要么无法布线要么在高速下误码激增。我之前做一块 JESD204B 板卡时为了省晶振想复用相邻 Quad 的参考时钟。看了手册确实说允许但实际布线后眼图质量始终不好。最终改回每个 Quad 独立参考时钟问题立即消失。教训就一句话能用独立晶振就别共用共用的时钟路径在高速收发器上很容易成为瓶颈。5.4 GT 复位顺序不是随便放的GT 收发器里的复位信号有明确顺序要求。以 Xilinx 官方推荐的复位流程为例你需要先复位 PLL 相关逻辑等 PLL 锁定后再复位 TX/RX 通道再释放数据路径。如果你写一句always (posedge clk) gt_reset button;直接当全局复位用大概率会出现“有时能锁有时不能锁”的诡异现象。我自己的调试经验是把 GT 复位逻辑单独写一个模块用状态机控制复位释放顺序。这个模块不复杂也就几十行状态转移但能极大降低调试成本。很多从网上复制来的例程可能因为硬件环境不同复位时间要求也不同不要无条件信任。5.5 原语例化时端口常犯的错原语这东西端口多且名字相似。O、OB、I、IB看似简单但如果你把 OBUFDS 的O和OB接反了输出信号的极性就全反了。电平标准里的下划线也很容易看漏比如LVDS_25写成了LVDS25编译直接报错。还有位宽问题GT 原语的端口位宽是参数化的你例化时忘记给参数设对数据对不上也很常见。我的建议是不要手工去敲原语端口从 Vivado 的 Language Templates 复制再把参数改到当前方案。对于 GT 这种大原语用 Transceiver Wizard 生成封装模块然后再去改参数比自己人肉拼端口可靠得多。5.6 别忽略 IOSTANDARD 的位数与仿真模型最后一条坑是在仿真阶段遇到的。有些原语在仿真时需要额外的模型库比如常用的HSERDES和SERDES模型在仿真库里是有版本要求的。你用 Vivado 自带仿真器一般没问题但如果你用第三方仿真工具比如 ModelSim就要确认仿真库是否编译完整否则仿真直接一片红。遇到这种情况优先查仿真库不要怀疑自己的代码逻辑。6. 再说一句心里话如何从 0 基础跨过 Bank 这道坎我见过不少非常有天赋的新人写逻辑代码不在话下但一谈到 FPGA 的器件资源就犯怵。其实你可以把 I/O Bank 理解成港口把 GT Bank 理解成专门的物流通道。港口有不同吨位限制和电压等级物流通道有不同速率上限。你写 Verilog 只是把货装上船但船能不能停靠、货物能不能过检取决于你对 Bank 资源的理解和规划。当初我在学校第一次接触 FPGA 的时候也被 Bank 电压和原语折磨得不轻。后来总结出一个土办法每次都把芯片手册里跟 Bank 相关的图表打印出来用彩色笔标注自己正在用的那几个 Bank。等到真的上手了软硬件联调再回头发现“字段不对”、“电压不对”这些坑已经在心里有数了。这篇讲的 I/O Bank 与 GT Bank 只是整个 FPGA 工程里的一个基础侧面。后面有空我再写一篇专门讲 GT 收发器的参考时钟规划和复位时序调试把那些烧脑的工程细节展开聊聊。如果你也正在被某个 Bank 或者 GT 通道的问题卡住欢迎在评论里把现象写清楚我可以帮你一起排查。
返回列表