☰
国产FPGA高速光纤通信系统搭建:SerDes与PCIe接口调试实战
2026/10/7 5:05:58 网站建设 项目流程

搞FPGA高速接口开发的朋友,应该都体会过“接口越高速,调试越上头”的滋味。尤其当你拿到一块国产FPGA开发板,想把它跑成一套真正能干活的高速光纤通信系统时,要考虑的事情就远不止“点亮一颗LED”那么简单了:光模块的收发链路怎么建?SerDes参数怎么配?和上位机通信是走PCIe还是走网口?整套系统怎么保证长时间跑不出误码?

这篇文章我就拿紫光同创的PG2L100H开发板作为载体,完整梳理一套高速光纤通信系统的搭建过程。重点会落在两条主线上:一是基于板载高速收发器走SFP+光模块的光纤链路怎么从零调通,二是怎么把PCIe接口配好,让板卡能和主机之间高速交换数据。内容会覆盖方案选型、工具链操作、IP配置、联调流程和大量排障经验,适合正在用国产FPGA做通信设备、数据采集卡或板卡加速的工程师参考,也在某些环节照顾新手朋友,尽量把每一步的原理和操作意图都讲透。

1. 内容整体设计与思路拆解

1.1 为什么选择紫光同创PG2L100H做这套系统

先聊聊选型。紫光同创的Logos系列和Titan系列在国产FPGA里属于出片量大、资料相对完整的阵营,PG2L100H则是面向中高端逻辑密度和高速接口场景的一款器件。具体到“搭建高速光纤通信系统”这个需求,我用它做载体主要有三个原因。

第一,带有够用的高速收发器资源。光纤通信绕不开SerDes,而SerDes的数量和质量直接决定了你能同时驱动几路光模块、跑到什么速率。PG2L100H的HP(High Performance)IO和高速收发器通道,支持常见的1G/10G光口速率,配合SFP+笼子能覆盖绝大多数板卡通信场景。

第二,逻辑资源足够塞下完整的协议栈。一套光纤通信系统不只是“收发数据”这么简单,你还得有链路层状态机、数据缓冲、错误校验、甚至DMA引擎。这些逻辑全部吃资源,如果芯片的逻辑单元太少,光把基础框架跑起来就会发现LUT消耗已经过半,后面再想做功能扩展就很被动。PG2L100H在这个级别的资源量能让你有余量做协议封装和性能优化。

第三,PDS工具链和IP生态已经基本成熟。早期国产FPGA最头疼的就是工具链不够顺手、IP核不齐全。现在PDS(Pango Design Suite)配合紫光同创的IP Compiler,基本的Transceiver IP、PCIe IP、DDR控制器IP都能快速生成。虽然有些细节和Xilinx的Vivado使用习惯不一样,但整体流程已经能支撑正规项目开发。

用这三点来评估一块板子值不值得入手,基本不会跑偏。很多朋友上来就关心“速率能跑多高”,其实更重要的问题是“这套工具链你能不能顺畅用起来”以及“IP的可定制化程度能不能支撑你的架构设计”。

1.2 光纤通信系统的整体架构设计

做系统设计之前,先把架构图画在脑子里。所谓“高速光纤通信系统”,从数据流的角度看,至少包含四个环节:数据产生或接收、协议处理、SerDes收发、光模块转换。

我的整体思路是按“主机-PCIe-FPGA-SerDes-光模块”的链路来组织数据流。FPGA在这里承担的角色类似一个协处理器或者数据通路控制中心:

  • 上行方向:光模块接收到光纤信号,经SFP+座进入FPGA的SerDes接收通道,恢复出并行数据,经过协议处理和缓冲后,通过PCIe DMA送到主机内存。
  • 下行方向:主机通过PCIe把数据写到FPGA的DMA缓冲区,FPGA侧引擎读取后做组帧、编码,再通过SerDes发送通道送给光模块发射出去。

这套架构的关键点在于“控制面”和“数据面”要分离。控制面使用PCIe的BAR空间映射寄存器,负责配置、状态查询、启动停止;数据面则是纯粹的流式处理通路,不占用CPU干预。

在选择具体方案时,有两条路线需要明确。第一条是数据面完全走PCIe DMA,这种方式适合“板卡需要和主机频繁交换批量数据”的场景;第二条是数据面直接由FPGA内部逻辑处理,PCIe只承担控制功能,比如光口转网口的二层转发设备就属于这种。我这次做的是前者,因为更贴近数据采集、信号回放、加速卡这类典型应用。

1.3 为什么PCIe与光纤通信必须放在一起讲

很多初学者会有疑问:我做光纤通信,老老实实把光口调通不就行了,为什么要牵扯PCIe?

原因是应用场景决定的。单独的光纤链路只是物理通路,它解决了“数据怎么从一个设备传到另一个设备”的问题,但解决不了“数据到设备之后怎么处理”。如果整个系统没有主机参与,那么FPGA自己闭环处理也可以;但一旦涉及配置管理、数据存储、远程控制、上层应用分析,就必然需要一块“大脑”。PCIe就是这块大脑和FPGA之间最高效的沟通管道。

举个例子。你做一个高速数据采集卡,光口从传感器端收到海量数据,FPGA做完解析和预处理之后,如果没有PCIe,你怎么把数据交给上位机软件分析?串口太慢,千兆网口勉强但CPU开销大,PCIe则能提供高带宽、低延迟、原生DMA能力。所以这套系统里,光纤负责“远距离高速传输”,PCIe负责“板内主机零拷贝搬运”,两者配合才能构成完整的产品形态。

另外,从工程学习的角度,把PCIe和高性能SerDes放在同一个项目里做,能让你在一套设计中同时掌握FPGA两个最核心的高速接口领域,这比零散地点亮某个IP有价值得多。

2. 硬件资源梳理与开发环境搭建

2.1 精确掌握PG2L100H开发板的硬件资源

拿到板子第一步,不是急着写代码,而是把硬件资源吃透。我在调试过程中总结了一张常用资源表,建议你拿到自己的板子时也做同样的事:

资源分类关键项目注意事项
FPGA芯片PG2L100H系列,确认具体封装和速度等级速度等级影响SerDes能跑到的最高线速率
高速收发器板载SerDes通道数量、对应的FPGA引脚位置必须确认哪些通道连接到了SFP+座子
光模块接口SFP/SFP+笼子数量、是否支持10G速率很多板子的SFP口只走1.25G,注意区分
PCIe接口金手指规格(x1/x4/x8)、参考时钟来源确定PCIe是Gen2还是Gen3,用的独立时钟还是公共时钟
全局时钟板载晶振频率、是否可编程SerDes参考时钟必须干净、稳定
DDR资源是否有板载DDR颗粒、接口位宽光纤数据缓存会用到

拿到原理图之后,优先做一件事:把SFP+座和FPGA收发器引脚的对应关系找出来。因为很多开发板的SFP+高速串行对并不是从第0号收发器开始排的,如果你想当然地从0号开始接,回头综合布局布线时就会出现引脚锁不上的问题。

我手上这块板子的情况,是4路SFP+光口,对应的收发器通道分布在不同的高速Bank里,同时PCIe金手指使用了独立的收发器通道和专用的参考时钟引脚。这种分布要求你在工程里面把不同速率的时钟域划分清楚,别把所有收发器共用一个参考时钟就完事,具体原因后面再展开。

2.2 安装PDS工具链并配置License

紫光同创的开发环境是Pango Design Suite,简称PDS。下载安装的过程不复杂,但有几个坑要先避开。

首先是版本选择。建议直接用官网最新的正式版本,不要用相对老的版本,因为PG2L100H这种偏新的器件,老版本可能没有对应的器件库,或者IP版本太旧导致生成的IP核不支持某些参数。PDS支持64位Windows和Linux,实际项目里我建议用Linux版本做大规模综合,Windows版本用来快速验证小工程,两者工程文件可以互相打开,但不要在两个平台之间频繁切换改工程,容易出一些莫名其妙的缓存问题。

安装完成后马上要处理的就是License。PDS的License分为评估版和正式版,评估版有设备型号和时间的限制,只适合入门学习;正式做项目建议申请对应器件型号的授权。配置License的方法是在安装目录下找到license.dat文件,把申请到的License内容替换进去,然后在PDS的License管理界面指定路径。

安装完成之后别急着建工程,先把驱动检查一遍。如果板卡是PCIe接口,插到电脑上后需要安装对应的驱动才能被主机识别。需要特别注意的是PCIe设备的驱动安装顺序——先把板卡插好,开机进入系统后再装驱动,比先进系统再插卡的成功率高很多。

2.3 新建工程并验证板卡基本运行

工具链装好之后,走一遍“新建工程-添加约束-综合实现-下载bit”的最小闭环。这个环节的目标不是跑任何复杂逻辑,而是确认三件事:器件型号选择正确、下载器能被识别、bit文件能烧进芯片。

新建工程时,选择器件型号PG2L100H,工程名和路径不要带中文和空格。PDS对路径的处理有时候不太友好,中文路径在综合阶段可能出现文件访问异常。

然后写一个最简单的LED翻转程序,把引脚约束加到工程里。PDS的约束文件是.fdc格式(类似Xilinx的XDC),语法上支持引脚位置约束和时钟约束。先不加任何时序约束,只做引脚绑定,综合实现后生成bit文件。

用下载器连接开发板的JTAG接口,在PDS里打开Programmer,选择设备并加载bit文件,点击Program。这一步走通之后,整个开发环境的可用性就确认了,后续所有精力都可以集中在逻辑设计和调试上。

3. 光纤高速收发链路搭建与调测

3.1 Transceiver IP的实例化与关键参数选择

光纤通信在FPGA里落地,第一步是实例化Transceiver IP。PG2L100H的收发器IP在PDS里的路径一般是IP Compiler -> High-Speed Transceiver,具体名称可能随版本略有变化,但核心配置项是固定的。

配置IP的时候,有几个参数必须花时间想清楚。

第一个是线速率(Line Rate)。这决定了物理链路上的传输速度。如果你准备用10G光模块,线速率就配成10.3125Gbps(这是10G以太网的标称速率);如果只是做1G光纤通信,用1.25Gbps就够了。不要为了追求参数好看把线速率配得过高,SerDes的可靠性、板材损耗、连接器质量都会影响高速信号质量,速率越高,对布局布线和电源的要求越苛刻。调试阶段建议从1.25G起步,链路稳定后再逐步提速到10G。

第二个是参考时钟频率。Transceiver的参考时钟通常取125MHz、156.25MHz等常见频率。这里要记住一个原则:参考时钟的质量直接影响SerDes输出的抖动性能。如果板子上有专用的低抖动时钟芯片给光口提供参考时钟,一定要用那一路,别直接挂一个普通的全局时钟引脚。

第三个是编解码方式。如果链路两端都是FPGA自发自收,可以用8B/10B或者64B/66B编码,具体看IP支持哪些。如果是要连接标准的以太网交换机或光模块,则需要选择对应的PHY模式,比如1000BASE-X或10GBASE-R。

3.2 用户侧接口的选择:AXI4-Stream还是独立收发接口

Transceiver IP配好之后,面对的第二个选择是用户侧接口。紫光同创的收发器IP一般提供两类接口风格:一类是简单的本地并行接口(类似Xilinx的原生接口),另一类是封装好的AXI4-Stream接口。

我建议在绝大多数场景下选AXI4-Stream。原因很简单,后续你要接的FIFO、DMA引擎、协议解析模块,基本都是围绕AXI4-Stream来做的。如果你选了原生接口,后面每个数据通路模块都得自己写转换逻辑,麻烦不说,还容易在跨时钟域处理上出问题。

但AXI4-Stream接口也有个坑:数据位宽通常比较宽。比如10G以太网模式下,用户侧数据位宽往往是32位或64位,内部时钟频率就等于线速率除以位宽系数。你要确保逻辑设计的时钟域管理是正确的,尤其是从用户逻辑时钟跨到收发器的TXUSRCLK域时,必须用跨时钟域FIFO或者同步握手来处理。

TX/RX数据通路建议各安排一个独立的FIFO,一个是深度的考虑(数据缓冲、速率匹配),另一个是隔离时钟域的需要。不要图省事直接把上游逻辑的输出接到Transceiver的输入,中间一定要有缓冲。实际调试中,很多“偶发误码”和“链路间歇性断开”的问题,根源都出在数据通路没有做时钟域隔离。

3.3 回环模式的妙用:从内部回环到外部回环

在正式连接远端设备之前,必须先做回环测试。回环测试分为由浅入深的几个层次,每一层都有各自的调试目的。

第一层是内部PCS回环,也叫近端回环。这种模式下,发送数据经过PCS层编码之后直接环回到接收路径,不经过物理介质。它的作用是验证Transceiver IP本身配置是否正确、时钟是否工作正常、PCS收发通路是否通。如果内部回环都不通,问题一定出在IP配置或时钟上。

第二层是内部PMA回环。调试时看眼图要用,通过PMA回环可以观察从接收端进来的信号质量,分析幅度和抖动情况。

第三层是外部回环,用一根光纤跳线把SFP+模块的TX和RX对接。这一层才是真正考验硬件设计的环节。外部回环如果跑不通,信号可能从FPGA引脚到光模块这一段就出了问题,也可能SFP+模块本身的问题(比如速率不支持、管脚定义不兼容)。

3.4 眼图检查与误码率验证

回环跑通之后,下一步是做眼图测试和误码率验证。

眼图反映了高速信号的质量。PDS的调试工具里可以提供类似眼图扫描的功能(或是配合示波器观测)。如果眼图的“眼睛”张开程度不够大,说明信号质量有隐患,长期运行可能出现误码。眼图不干净通常由三种原因导致:参考时钟噪声过大、电源纹波超标、PCB走线损耗太大。遇到眼图不好,优先查这三样。

误码率测试则更直接。在FPGA逻辑里做一个伪随机序列生成器(PRBS),发送端持续发送PRBS,接收端对收到的数据进行比对。我用的是PRBS31,它能更充分地暴露高速链路的偶然性误码。测试时长不要太短,至少跑30分钟以上,并且记录累计误码数。如果长时间零误码,链路才算是基本可靠。

4. PCIe接口配置与主机联调

4.1 PCIe IP配置的要点与BAR空间规划

PCIe部分我用紫光同创的PCIe IP来做。配置之前先搞清楚需求:板卡要承担的功能是什么,决定了IP需要配成Endpoint模式还是Root Complex模式。绝大多数场景下,开发板是插在主机主板上的,所以选Endpoint模式。

配置的主要项目包括链路宽度和速率。PG2L100H的PCIe硬核一般支持x1/x2/x4,速率支持Gen1和Gen2。调试阶段建议先把链路宽度设为x1,速率设为Gen1,跑通之后再加宽提速。不要一开始就上x4 Gen2,链路训练阶段越复杂,出问题越难定位。

BAR空间是PCIe设备与主机通信的窗口。规划BAR时遵循几个原则:

  • BAR0分配给小空间的寄存器,大小对齐到4KB就够,用于控制状态寄存器映射。
  • BAR1或BAR2分配给DMA数据缓冲区,大小取决于你的DMA引擎需要多大地址空间,一般分配16MB到64MB。
  • 凡是硬件不打算支持的地址空间,不要轻易让出BAR资源,减少地址译码逻辑的复杂度。

中断方式上,推荐使用MSI中断而不是传统的INTx引脚中断。MSI本质上就是一次内存写操作,在Linux下的处理效率远高于INTx,而且国产FPGA的PCIe IP对MSI的支持一般都比较完善。

4.2 DMA数据通路设计

PCIe配置完成之后,性能瓶颈通常不在PCIe链路本身,而在DMA数据通路设计。同样的PCIe x4 Gen2,DMA引擎设计得好能跑到接近带宽上限,设计得不好可能连一半都跑不到。

常见的DMA架构是“描述符环”。主机侧在内存中维护一个环形描述符队列,每个描述符包含数据缓冲区的物理地址、长度、完成状态等信息。FPGA侧DMA引擎自动从环上抓取描述符,按描述符内容搬运数据,完成后更新状态字段并触发MSI中断通知主机。

这套机制的核心是“描述符预取”和“数据批量搬运”。描述符环一般驻留在主机内存里,FPGA通过PCIe读取描述符;为了避免频繁发起小粒度读请求,DMA引擎要一次预取多个描述符缓存到本地。数据搬运时尽量把单次事务的负载做大,减少PCIe层的TLP开销。同样搬1MB数据,拆成256次4KB的请求比拆成1024次1KB的请求效率高得多。

主机侧驱动方面,需要分配物理连续的内存来存放DMA缓冲区,并且把物理地址通过某种方式(比如IOMMU关闭或使用专用DMA API)告诉FPGA。Linux下通常使用DMA API来申请一致性内存。驱动编写时要注意Cache一致性处理,避免DMA写入的数据在CPU侧读到的是旧数据。

4.3 Linux环境下的枚举与性能测试

系统安装好之后,就是验证环节。Linux下查看PCIe设备最直接的方式是lspci命令。如果枚举成功,你能在输出里看到板上设备的Vendor ID和Device ID。

关于PCIe链路状态,可以直接读取设备的Link Status寄存器,检查当前链路是Gen1还是Gen2,宽度是x1还是x4。如果实际协商到的速率低于预期,很可能是PCB走线质量问题导致训练降级,这时候需要检查参考时钟、连接器焊接、PCIe通道的走线长度匹配。

性能测试方面,如果你的驱动和DMA引擎已经正常工作,我通常习惯先做一次“DMA回环”测试:主机分配一个缓冲区,填充数据,下发DMA写请求,FPGA把收到的数据又通过另一条DMA通道写回主机,主机比对数据一致性。数据一致性能通过,说明链路的数据通路没问题;之后再测试持续带宽,看看单方向吞吐率能达到多少。

测试过程中用iostat或perf观察DMA中断频率,如果中断过于密集,说明描述符处理逻辑或中断合并策略需要优化。

5. 常见问题与排查技巧实录

5.1 光纤链路无法建立或频繁断开

“光口指示灯不亮”是出现频率最高的问题。排查顺序我一般固定为“软件配置、时钟、光模块、信号完整性”四步。

先确认软件配置:线速率、编码模式、回环模式是否匹配。如果是连接标准交换机,还要确保PCS/PMA层的自动协商开关打开了。接着确认时钟:用示波器或频率计看参考时钟是否起振、频率是否准确。时钟频率偏了,链路一定不稳定,这种问题在排查时很容易忽略。

再往下就是光模块本身。不同的光模块对不同速率的支持情况不一样,一个标称10G的光模块插到1.25G速率的链路上没问题,但反过来把1G光模块硬跑到10G速率就会失败。光模块的兼容性也值得留意,国产模块和某些IP的兼容性参差不齐,采购时尽量选用有依据的型号。

最后是信号完整性。如果收发器芯片到SFP+座这段走线过长或过孔太多,高频损耗会很明显。测试方法是把速率降低到1G试试,如果降速后链路稳定,基本可以断定是信号完整性瓶颈,需要在PCB设计阶段提前规划好。

5.2 PCIe枚举失败与速率降级

PCIe枚举不到设备,先分清是硬件问题还是软件问题。硬件方面,重点检查复位信号时序。PERST#信号必须满足PCIe规范的上电时序要求,FPGA侧的配置完成信号要和PERST#有正确的先后关系。如果FPGA还没配置完成就释放了PERST#,上游设备就无法识别到你。

软件方面,检查系统是否识别到未枚举的设备,用lspci -v看总线扫描情况。如果设备被枚举但驱动加载失败,查看dmesg日志里的错误信息,很多情况下可以定位到BAR配置或MSI申请失败。

速率降级问题就更有意思了。如果你希望跑Gen2 x4,但协商结果只有Gen1 x2,大概率是链路训练过程中的信号质量问题。PCIe规范允许链路在训练失败时降速降宽,这是保护机制而不是故障。解决思路是改善信号完整性,重点看PCIe差分对的布线长度匹配和参考层完整性。另外,参考时钟的展频(SSC)设置也要和主机侧匹配,如果FPGA侧不支持展频但主板开启了展频,也会引起训练不稳定。

5.3 时序收敛问题与处理方法

高速接口工程的另一个大头是时序收敛。PDS综合实现后如果出现时序违例,不要急着提高约束强度,先学会看时序报告。

优先处理跨时钟域的路径。Transceiver的用户时钟、DMA引擎的时钟、系统总线的时钟都是不同频率同源的异步时钟域,这些路径上的约束如果标错了,就会出现大量违例。正确做法是使用异步FIFO切分时钟域,并且对AsyncFIFO内部的跨时钟路径设置false path或max delay约束。

同频同源路径的违例则通常是代码风格问题。组合逻辑链路太长、扇出过大都会造成时序不收敛。修的时候先看最差的几条路径,从代码上拆分或插入流水寄存器。综合工具本身的优化策略调整也有帮助,比如调整综合努力等级、打开物理综合、修改布局布线的种子数。有时候同一个工程换一个布局种子,结果就能大幅改善。

5.4 问题排查速查表

最后给一张按症状分类的排查表,方便调试时对照:

症状可能原因处理办法
光信号指示灯不亮光模块未插牢、模块速率不匹配重新插拔,检查模块规格
链路偶发断开参考时钟抖动太大、电源纹波大用示波器测时钟和电源,确认是否在正常范围
长时间运行有误码眼图裕量不足、散热问题导致温漂检查眼图,加装散热片,延长PRBS测试时间
PCIe枚举不到设备复位时序异常、FPGA未配置完成调整PERST#逻辑,确认配置完成后再拉高
PCIe速率降级PCB走线质量差、参考时钟不一致缩短走线长度,检查SSC设置
DMA传输数据不对地址映射错误、Cache未同步核对地址映射,检查驱动是否做了Cache操作
时序违例严重跨时钟域约束缺失、代码路径太长拆分时钟域,插入流水寄存器

6. 后续扩展与我的个人体会

系统能稳定跑起来之后,这个平台可扩展的方向非常多。比如在PCIe数据通路之上叠加TCP/IP协议栈实现光纤转网口;或者把光纤链路升级到多通道,配合DDR做数据缓存实现更复杂的数据采集回放系统。PG2L100H的资源足够支撑你再叠加不少逻辑,这也是我选择用它做这套系统的重要原因。

根据我实际调试的经验,国产FPGA工具链相比国外主流工具,在手感上确实有不同,但核心逻辑是相通的。遇到问题多读数据手册,多用工具的调试功能,多写“最小复现”的验证工程,基本都能解决。做高速接口测试时,建议每次改动只动一个变量,不要同时调整多个参数——比如这次改线速率,下次再动参考时钟,否则出了问题根本分不清是哪个改动引起的。

最后再分享一个小技巧:把每次调试的寄存器配置、改动项和测试结果记录到表格里。高速接口调试时经常出现“昨天还能跑通今天就不通”的诡异情况,有了记录才能快速回溯差异在哪里。这套系统从设计到跑通,我踩过的坑不少,但真正把每个细节弄明白以后,你会发现国产FPGA做高速通信项目,完全是可以依赖的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询