ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

国产FPGA PCIe调通指南:PGL50H从IP配置到Windows识别

国产FPGA PCIe调通指南:PGL50H从IP配置到Windows识别 做了这么多年FPGA说句实话国产FPGA的PCIe链路最难的不是RTL代码而是环境、IP、硬件、枚举、驱动这一整条链路中间任何一环出了岔子现象都长得一模一样开发板插上电脑设备管理器里死活不认卡。这篇文章我用紫光同创PGL50H开发板从PDS软件里PCIE IP核的调用配置开始一路讲到硬件上耦合电容怎么摆、差分阻抗该控多少、LTSSM状态机怎么拉起来最后让Windows设备管理器正确识别出你的PCIe设备。内容偏操作向新手照着做基本能跑通老手也可以当一份查缺补漏的清单用。1. 开工之前先搞清楚PGL50H和PCIe方案选型1.1 PGL50H内部到底有什么紫光同创PGL50H这颗芯片在国产FPGA里算是一个甜点位。逻辑资源在5万级LUT左右自带DDR3硬核、SerDes高速收发器最关键的是集成了一路PCIe硬核协议规格支持到PCIe Gen2最高可以配成x4链路。和纯逻辑软核实现相比硬核最大的优势是链路训练、物理层编解码这些脏活累活全部由固化电路完成你不需要自己写8b/10b编解码也不需要去抠Training Sequence的细节只需要把IP核的接口拉出来按照AXI总线或者单独的PIO接口去读写数据就行。用PGL50H做PCIe通信最典型的应用有两个一是做高速数据采集卡把ADC采到的数据通过PCIe搬给上位机二是做PCIe转其它接口的桥接设备比如PCIe转SFP网口、PCIe转UART调试口。不管哪种应用跑通信的第一步都是让电脑先认出这块板卡也就是完成PCIe枚举。这一步不解决后面全是白搭。1.2 为什么优先用PCIe硬核而不是自己写有朋友问过一个问题紫光PGL50H能不能不用硬核纯逻辑实现PCIe答案是可以但非常不推荐。PCIe协议从物理层到事务层有非常多的状态机跳转光是Link Training就要处理Detect、Polling、Configuration、L0这好几个阶段再加上TLP格式封装、流控机制、重传机制自己写一遍的工程量不亚于重新造一个网卡芯片。更麻烦的是PCIe跑在高速差分信号上GTP收发器的阻抗匹配、时钟恢复、均衡参数没有硬核帮你管理好信号稍差一点就会出现链路不稳定、偶尔掉卡的问题。所以我的建议很直接PGL50H上用PCIe就直接调官方IP核不要再自己造轮子。硬核方案不但稳定而且在PDS的IP配置界面里就能设置链路宽度、参考时钟频率、BAR空间映射等参数非常方便。后面你可以把精力放在业务逻辑上比如采集数据的DMA搬运、中断上报这些真正有价值的部分。1.3 PDS软件与License的坑紫光同创的开发环境叫PDS全称Pango Design Suite。下载安装没有什么特别的注意用管理员权限安装路径不要带中文。装完之后你会发现打开软件之后很多IP核选项是灰色的或者生成IP的时候提示License不完整这是正常的因为PDS默认License只包含基础功能PCIe这类硬核IP需要单独授权。解决办法是去紫光同创官网申请试用License一般用板卡上的网卡MAC地址或者机器码生成License文件然后把License文件放到指定目录在PDS的License管理界面加载即可。这里踩过一个坑License文件放的目录不能有中文也不能有空格否则PDS启动时识别不到。另外试用License通常有有效期如果有一天你发现PDS里PCIe IP突然不能重新生成了先看看是不是License过期了。2. 硬件设计上的几个关键耦合电容、阻抗、时钟2.1 参考时钟到底怎么给PCIe链路对参考时钟的要求很高一般要求100MHz差分参考时钟抖动指标满足PCIe规范。PGL50H的PCIe硬核输入参考时钟可以直接由板上的100MHz差分晶振提供也可以由PCIe插槽上的100MHz REFCLK提供。像PGL50H这种标准PCIe板卡我建议直接用插槽提供的REFCLK因为上位机主板输出的时钟和Root Complex是同步的链路协商会更顺利。但要注意REFCLK信号必须走差分对且要严格控制等长尽量控制在5mil以内。PCIe规范里还有Spread Spectrum ClockingSSC的要求也就是展频时钟不过这一点在硬件上一般已经由主板和时钟芯片处理好了FPGA侧只要正常接收即可。如果你用的是板上独立晶振记得确保晶振输出也是差分格式且频率稳定在100MHz否则LTSSM会一直卡在Polling阶段无法进入L0。2.2 耦合电容的摆放离发送端越近越好PCIe物理链路中高速差分信号通过AC耦合电容隔直然后送入接收端。这个电容的容值通常选0.1uF或0.22uF封装建议0402或者0603。之前有朋友在这个环节翻过车电容位置放得离FPGA引脚非常远导致链路上的阻抗不连续信号反射严重Link Training失败设备管理器一直不出现设备。实话说PCIe耦合电容摆放位置是个有讲究的事。PCIe规范给出的指导是AC耦合电容应靠近发送端放置建议距离发送端引脚不超过0.5英寸这样信号经过电容后还有足够长的走线余量到达接收端。但实际项目里板卡结构往往受限那么退一步电容放在走线中间偏发送端也比放在接收端强。另外电容的焊盘要尽量做小避免产生过大的寄生电容两个焊盘之间不要打过孔最好让差分走线直接穿过电容。2.3 差分阻抗是85欧不是100欧很多人习惯了一做差分就是100欧结果做PCIe板卡时想都没想也按100欧去控这是个大坑。PCIe规范的差分阻抗要求是85欧±10%单端阻抗50欧。如果你按100欧差分去设计虽然链路短的时候也能协商成功但信号质量会比较差尤其是跑Gen2速率时眼图余量小长时间高负载会偶尔出现数据错包。做PGL50H这种板级项目时最好在PCB设计阶段就跟板厂确认叠层和线宽保证差分阻抗落在85欧附近。叠层设计时微带走线参考地平面线宽和间距由阻抗计算工具得出不同板厂的工艺参数不同线宽会有细微差异。这个环节不要凭经验拍脑袋给板厂文件时一定要附带阻抗要求说明让板厂帮忙阻抗计算并做阻抗条验证。2.4 复位信号和上下拉电阻还有一个容易被忽略的细节是PERST#复位信号。PCIe规范规定PCIe设备必须支持PERST#复位Root Complex会在上电后拉低再释放PERST#设备需要在这个信号释放后才开始Link Training。如果你的板卡是标准PCIe金手指供电和信号连接那么PERST#一般由主板提供直接引到FPGA的复位引脚或者PCIe硬核的复位输入即可。有的开发板自带PCIe Switch或者电平转换电路这时候要特别检查PERST#的电平转换是否正常有些板子因为转换芯片供电顺序问题导致PERST#一直被拉低FPGA始终不启动链路训练。排查方法很简单上电后用示波器量PERST#引脚看它有没有一个从低到高的跳变。3. PDS实操从IP核调用到生成比特流3.1 在PDS中调用PCIe IP核打开PDS新建一个RTL工程目标器件选择PGL50H对应的型号。然后在菜单栏找到IP Compiler也就是紫光的IP核配置工具在IP列表里找到PCIe相关的IP核双击打开配置界面。配置界面里比较关键的有这几项Lane宽度可选x1、x2、x4如果只是验证明白x1就可以接插件连线少排查问题也更方便。速率PGL50H的PCIe硬核最高Gen2也就是5GT/s你可以配置成与主板自适应或者固定Gen1、Gen2。参考时钟频率一般选100MHz。BAR空间可以配置多个BAR每个BAR可以是内存映射或者IO映射。Windows枚举时会给BAR分配物理地址这个映射关系在驱动开发里很重要。配置完成后点击Generate生成IP。这个过程会生成一个打包好的IP核文件以及仿真模型和例化模板。建议把例化模板保存下来后面写顶层代码时直接用不容易把端口名搞错。生成完IP核后在工程里会多出一个可调用的module里面包含了链路状态输出、AXI接口、收发接口等端口。3.2 顶层RTL设计怎么把IP核拉起来顶层设计其实并不复杂。PCIe IP核提供了若干状态和控制接口你需要在FPGA逻辑里做一个简单的状态机等待LTSSM进入L0状态。作为最小验证工程可以不用实现复杂的DMA逻辑只做以下几件事将PCIe IP核的复位输入连接到PERST#或者用户复位将链路上报状态的信号比如当前LTSSM状态连接出去方便ILA抓取观察实现最简单的BAR0读改写逻辑让上位机通过读写BAR0地址能够看到数据回环。我在最小工程里会做这样一个逻辑当上位机向BAR0地址写一个32位数据时FPGA端把数据锁存然后在下一次读BAR0时返回这个数据。这样Windows端可以先用调试工具比如DebugView、ReadWrite Everything或者自己写一个简单的应用程序来验证PCIe链路是否通了。代码写完后记得对顶层模块进行例化检查。PDS的语法检查相对严格尤其是端口的位宽和方向建议在综合前先跑一下RTL elaboration把语法错误提前清掉。3.3 综合、布局布线、生成比特流综合前需要确认约束文件主要有两个一个是时钟约束告诉工具PCIe参考时钟是100MHz另一个是引脚约束告诉工具每个信号在芯片的哪个Pin上。PGL50H开发板一般会提供现成的引脚约束文件也可以根据原理图自己写。引脚约束最关键的是要把PCIe的TX/RX差分对分配到硬核对应的GTP引脚上这个信息在芯片数据手册里可以查到。布局布线时如果工程面积很小跑默认策略一般就能满足时序。链路训练这种功能对时序的要求主要在高速收发器内部逻辑侧的时序压力不大所以不用太担心。生成比特流后通过PDS的下载工具烧写到FPGA。如果板卡上有Flash也可以把固件固化到Flash里这样断电重来不需要每次重新下载。3.4 用ILA观察LTSSM状态如果插上电脑后设备管理器什么都没出现先不要急着怀疑驱动大概率是链路就没协商成功。这时候需要抓内部信号看LTSSM到底卡在哪个状态。PDS自带在线逻辑分析仪用法和Xilinx的ILA类似。在IP Compiler里可以生成一个ILA核把PCIE IP核的当前LTSSM状态、链路宽度状态、复位信号这些关键信号拉进ILA设置好触发条件在上电后触发抓取。正常的上电时序应该是这样的检测Detect状态然后进入Polling做8b/10b符号对齐再进入Configuration协商链路宽度和速率最后进入L0正常收发数据。如果你抓到的状态一直停在Detect或者Polling说明物理层可能没对通如果已经进入Config但跳不到L0往往是因为TX/RX方向搞反了或者链路宽度协商不匹配。注意ILA会占用一部分逻辑资源和布线资源调试完成后生成最终版本时记得把ILA去掉否则长时间运行可能影响PCIe硬核的时钟域稳定性。这是很实际的一个经验我在调试完经常忘记这件事后面重新生成bit流时Data不够才发现ILA占了不少面积。4. 上板调试与Windows设备管理器识别4.1 PCIe枚举过程电脑怎么发现你的板卡Windows识别PCIe设备依赖的是主板上的Root ComplexRC在上电初始化时发起的枚举过程。RC会先做链路训练成功之后给设备分配总线号、设备号、功能号然后通过配置读写请求去读取设备的配置空间。配置空间里包含了Vendor ID、Device ID、Class Code、BAR大小等信息Windows根据这些信息为设备安装合适的驱动并给BAR分配物理内存地址。如果你的板卡在设备管理器里完全看不到也可以用PCIe分析仪或主板BIOS里的PCIe设备列表来辅助排查。有些主板BIOS在开机自检时会直接列出挂在PCIe总线上的设备型号如果能在这里看到你的板卡说明链路训练和配置空间读取已经通过剩下的问题就集中在Windows驱动层。反之如果BIOS里都看不到那就回过去查硬件链路和IP配置。4.2 为什么设备显示为“未知设备”或“PCI设备”设备管理器里出现一个带黄色感叹号的“PCI设备”或者“未知设备”其实是一个好消息说明枚举已经完成了设备已经被挂到了总线上只是没有找到匹配的驱动。到这里PCIe链路已经从物理层跑到了配置层问题不大。这时候可以右键设备查看硬件ID。硬件ID里包含VID和DID比如你的板卡在IP核里配置Vendor ID为0x10EEXilinx的只是举例Device ID为0x9038那么在硬件ID里就能看到对应的值。记住这对VID/DID后面做驱动安装和应用程序开发时用得上。如果你发现VID和DID都是0或者不对说明配置空间的数据不是你预期的回IP核配置界面检查Vendor ID和Device ID设置。4.3 驱动安装那点事Windows设备管理器识别到未知设备后接下来就是驱动。Windows的PCIe驱动分两种一种是内核驱动另一种是用户态通过WinUSB访问设备的驱动。对于最开始的验证我不建议一上来就写WDF内核驱动调试麻烦还容易蓝屏。可以先用Zadig或者WinUSB类驱动把设备绑定成WinUSB设备然后在应用程序里通过WinUSB API读写BAR空间验证数据通路。需要注意64位Windows强制驱动签名WinUSB这类通用驱动已经过了微软签名一般不会有什么问题。但如果你自己写内核驱动就必须先做测试签名或者申请微软签名否则系统会拒绝加载。调试阶段最简单的方法是把Windows的测试签名模式打开命令是bcdedit /set testsigning on重启后生效这样自签名驱动就能加载了。4.4 通过BAR空间验证数据通路驱动层搞定后可以用一个简单工具向BAR0写入数据再读出来。之前提到的读改写回环逻辑在这里就派上用场了。打开工具选择正确的VID/DID找到BAR0的物理地址向偏移0写入0xA5A55A5A再从这个地址读回来如果读到的数据一样说明你的PCIe链路和Windows驱动已经完全打通。到了这一步设备管理器里的板卡已经不再是“未知设备”而是以你指定的设备名出现在设备列表中。整个PGL50H的PCIe通信链路从IP核到物理链路到Windows枚举就算全部跑通了。5. 常见问题排查与经验总结5.1 Link Training失败卡在Detect或Polling这是最常遇到的问题。卡在Detect通常意味着物理层信号没对上重点排查TX/RX是否接反、差分走线是否断线、耦合电容是否焊接正常、参考时钟是否稳定。卡在Polling则大概率是符号同步或者速率协商有问题可以尝试把IP核固定到Gen1速率排除高速率下信号质量不足的问题。针对这类问题我整理了一个简单的排查顺序表现象可能原因排查手段设备管理器完全无设备链路训练失败用ILA抓LTSSM状态确认卡在哪个阶段卡在Detect差分线接反、线断、电容虚焊万用表量通断示波器看波形调换TX/RX卡在Polling参考时钟不稳、符号对齐失败检查REFCLK抖动固定Gen1速率试验卡在Configuration链路宽度协商失败把IP核固定的x4改成x1或x2试验进入L0但仍不识别配置空间读取出错用BIOS设备列表或PCIe分析仪检查配置空间应答5.2 设备管理器出现设备但VID/DID不对打开设备属性如果VID是0xFFFF或者0x0000说明配置空间的vendor id读取失败。这种问题通常是IP核的配置参数没正确写入或者复位释放的时序不对设备在RC读取配置空间时没有准备好数据。解决办法是检查PCIe IP核的复位逻辑确保LTSSM至少进入L0后配置空间才允许被访问。5.3 偶尔掉卡、设备重启后消失这个问题往往是硬件信号完整性问题。当链路长时间高速传输或者上位机负载变重时偶尔会出现链路失锁导致设备消失。先检查耦合电容位置和容值再看差分阻抗是否匹配最后可以用频谱仪观察参考时钟的抖动。信号完整性这种问题不太好抓建议在PCB设计阶段就严格按照85欧差分阻抗、发送端耦合电容就近摆放这些规则来后期能省很多麻烦。5.4 几个值得记住的小技巧调试PCIe这类高速链路我总结下来最有用的一个技巧是多看状态少猜现象。PGL50H的PCIe IP核把LTSSM状态直接暴露出来了老老实实拉进ILA抓波形比自己拿示波器戳TX/RX引脚猜要高效得多。另外一个技巧是第一次跑通时尽量把链路配成最简模式x1、Gen1先把Windows识别搞定再逐步提高速率和链路宽度。不要一上来就x4 Gen2如果信号完整性有问题你根本分不清是硬件设计问题、IP配置问题还是驱动问题。先用最保守的配置跑通一把再往上加难度排查面就会小很多。最后就是License和工程备份的问题。PDS的License过期几乎是每个用国产FPGA的人都会遇到的事建议申请License时用固定机器的MAC并且把License文件放到一个不会被系统清理的位置。工程文件动不动就几百MB做好版本管理改IP配置前一定备份不然有时候改坏了想找回之前能跑通的版本都找不到。
返回列表