ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

紫光同创PGL50H FPGA PCIe开发实战:从IP配置到Windows识别

紫光同创PGL50H FPGA PCIe开发实战:从IP配置到Windows识别 1. 这块板子和PCIe方案到底适合做什么先说清楚一个很多人容易误解的点紫光同创PGL50H并不是一颗主打PCIe功能的FPGA它的定位更偏中低容量的国产FPGA平台但PGL50H内部集成了一路硬核PCIe控制器支持Endpoint模式速率最高可达PCIe 2.0 x45GT/s per lane。这意味着在不需要太高带宽的工业控制、数据采集、视频传输、科研教学场景下完全可以用它来做一套完整的PCIe通信系统而不必一上来就上高端型号。我从实际项目经验来看最适合用这套方案的人群主要有三类高校和研究所的FPGA学习者想系统性地走通PCIe协议栈的枚举、配置空间、中断、DMA传输但又不想用Vivado那套成熟得过于自动化的流程紫光同创的PDS工具链能逼你把每个环节搞清楚。做国产化替代的工程师项目要求必须用国产FPGA平台实现标准PCIe接口PGL50H是少数在性价比上能打的型号。做自定义数据采集卡的硬件开发者需要把ADC、传感器数据通过PCIe总线高速上送主机但带宽需求不超过2GB/s的场景。这套方案的典型通路总结下来是这样的FPGA作为PCIe Endpoint设备插到主板的PCIe插槽上通过硬核控制器完成链路训练主机侧枚举出未知设备后加载驱动最终在设备管理器里看到完整识别信息然后开始正式的数据传输。我要把这条链路从零开始完整走一遍包括IP核安装这种最容易卡住新手的环节。2. 开发环境准备PDS软件和License的一个大坑2.1 PDS版本选择与安装紫光同创的FPGA开发软件叫PDSPango Design Suite在开始PCIe开发前先要把这个平台装好。官网下载页面目前提供多个版本我建议直接选较新的2021.2及以上版本因为PCIe IP核在早期版本里存在一些已修复的Bug比如链路训练不稳定、中断引脚映射错误等问题。安装过程不多讲Windows下直接一路Next。但有一点必须提醒安装路径千万不要带中文和空格这个工具链对路径敏感之前有人装在D:\软件\PDS下结果综合时报出一堆莫名其妙的路径错误。建议统一放C:\PDS这种纯英文路径。2.2 License配置的隐藏细节这部分是新手最容易卡住的地方。紫光同创的License分两种一种是评估License一般通过代理或官方申请有时效限制另一种是绑定机器码的正式License。拿到License文件后不是随便找个地方放就行。打开PDS软件菜单栏找到License配置工具一般在开始菜单的Pango Design Suite目录下选择指定License文件然后浏览到你存放License的路径。这里有个关键点License文件的路径也不能有中文而且建议放在PDS安装目录以外的固定位置比如C:\Licenses\pango_license.dat避免之后重装软件时被覆盖。验证License是否生效的方法打开PDS新建工程后在IP核仓库IP Catalog里搜索PCIe如果能看到PCIe IP核并且可以双击打开配置界面说明License正常。如果看不到或者提示License不支持回到License配置步骤重新检查也可以运行安装目录下的license_check工具查看具体报错。我遇到过一次比较坑的情况License明明正常但PCIe IP核仍显示灰色不可用查了半天发现是PDS版本和License不匹配旧License只支持到2020.1版本换新版本后必须同步更新License。所以版本升级之前一定先确认License支持范围。2.3 检查硬核资源PGL50H的PCIe硬核在Device视图里可以确认。打开PDS新建一个空工程选择PGL50H-6FBG484或者你板卡对应的具体封装在Device Overview里能看到芯片资源表格。PCIe硬核在资源列表里会以PCIe Hard IP或类似条目标识确认存在后再进行后续开发。如果用的是更小规模的PGL25G或者更老的型号很可能没有PCIe硬核那就得用软核方案工程复杂度会上升一个数量级不在本教程范围内。3. PCIe IP核的生成与配置每个参数背后的原理3.1 IP核创建流程在PDS中创建PCIe IP核的路径是IP Catalog - Interfaces - PCIe。双击打开后会进入IP配置界面。这个界面分几个Tab下面逐个拆解。General配置项Component Name给IP核命名比如pcie_ep_0名字后面会作为生成文件的前缀。模式选择Endpoint端点是设备端Root Complex是主机端。我们做开发板插主机必须选Endpoint。这里特别解释一下为什么是EndpointPCIe体系结构是树形的主机CPU和南桥芯片组属于Root Complex根复合体挂在它下面的是各种Endpoint设备显卡、网卡、SSD。RC负责枚举和管理总线EP是被动响应的一方。PGL50H的硬核只支持Endpoint模式这决定了我们用它做的是被主机识别和控制的设备而不是控制其他设备的主机。Lane配置Lane宽度可选x1、x2、x4。PGL50H硬核最高支持x4板卡上实际走线能支持多少取决于硬件设计金手指或PCIe插槽的连接方式。如果板卡是x4的金手指直接选x4。如果板卡只是x1的插槽或走线也要选x1否则链路训练会失败。速率可选2.5GT/sGen1和5GT/sGen2。建议初期开发先用Gen1链路训练成功率更高排查问题也更容易。后面稳定后可以切Gen2测速。Reference Clock配置参考时钟频率100MHz是PCIe规范定的没得选但需要指定时钟源。一般开发板会从PCIe插槽的REFCLK引脚引入主机侧的100MHz时钟在IP配置里选择External或From Board并指定对应的时钟引脚。BAR空间配置 这是重点直接关系到主机怎么访问FPGA的寄存器空间。BARBase Address Register是PCIe设备向主机声明自己资源范围的寄存器。我们要做数据通信一般开两个BARBAR0作为控制寄存器空间大小设为4KB就够了用来放状态寄存器、控制寄存器、中断控制位。映射方式选Memory内存映射因为IO空间在现代系统中已经很少使用且效率低。BAR1作为数据缓冲区空间大小可以设到1MB或更大用于DMA传输时的缓冲区映射。同样选Memory映射。中断配置PCIe支持三种中断机制Legacy INTx、MSIMessage Signaled Interrupt、MSI-X。强烈建议用MSI因为INTx在共享中断时容易出问题而MSI是直接写消息到主机内存效率高且不占用共享中断线。PGL50H硬核支持MSI在配置里可以设MSI的Capability结构和中断消息数量。前期调试建议先设1个中断向量MSI Capability里的Multiple Message Enable设为1即可简化逻辑。3.2 生成IP核后的关键文件配置完成后点击GeneratePDS会生成一组文件。你要重点关注这几个顶层例化模板通常以_top.v结尾官方给的例化参考里面有IP核的端口定义和连接示例。IP核的仿真模型用于前仿真验证。IP核的用户指南PDF这个一定要看里面是寄存器描述和接口时序比任何教程都详细。4. 硬件设计检查清单耦合电容和阻抗控制要命标题里的热搜词提到了pcie耦合电容摆放位置说明这是很多人栽过跟头的地方。在我开始写逻辑之前先花点篇幅把这里的硬件要点讲透。4.1 AC耦合电容的基本要求PCIe协议规定每个发送端的差分信号线上必须串联AC耦合电容电容值规范要求在75nF到200nF之间常用值是100nF。这个电容的作用是隔直流通交流让链路双方的共模电压可以不同而不互相影响。摆放位置按照PCIe规范AC耦合电容要放在发送端一侧且距离发送端封装引脚最好在500mil以内一般设计上控制在0.1到0.5英寸之间。如果走线较长电容的位置需要做阻抗补偿通常是补线否则会造成阻抗不连续点影响信号完整性。对于PGL50H开发板这种成品板耦合电容在出厂时已经由板厂设计好了一般不需要你处理。但如果你是自己画板子注意发送端的每一对差分线上都要放电容接收端可以不放。别两边都放两边都放会导致等效电容减半且引入两个阻抗不连续点。4.2 差分阻抗控制PCIe Gen1/Gen2的差分阻抗要求是85欧姆±10%注意不是100欧姆很多新手按千兆网口习惯了100欧姆这里容易错。对于PGL50H的引脚扇出和PCB走线建议走线宽度、间距根据叠层计算表层微带线参考地去层走线尽量短且等长。热搜词里还有一个pcie的发送差分对间需不需要等长——需要的。PCIe规范对差分对内等长要求非常严格Gen2速率下对内偏差要控制在5mil以内对间等长相对宽松但整体偏差最好控制在100mil内因为接收端有弹性缓冲Elastic Buffer来处理跨时钟域问题但处理不了极端的skew。4.3 参考时钟的走线检查100MHz参考时钟通常是从PCIe插槽引过来直接连到FPGA专用REFCLK引脚。检查一下板卡的原理图确认REFCLK对有没有做AC耦合有些板卡会在时钟源与FPGA之间加电容有没有串联端接电阻。参考时钟质量差会直接导致链路训练失败现象是设备管理器里根本看不到未知设备。5. 逻辑设计与关键接口时序5.1 最小可识别系统需要哪些逻辑要让Windows设备管理器识别到设备FPGA内部逻辑需要完成以下几件事硬核PCIe初始化上电后硬核会自动与主机RC进行链路训练不需要用户逻辑参与。配置空间应答硬核已经内置了配置空间包括Vendor ID、Device ID、BAR、MSI Capability等。我们只需要在IP配置时传入正确的ID参数。用户逻辑访问BAR空间主机枚举设备时会读取配置空间来分配资源但如果后续主机要往BAR0写数据或读状态FPGA用户逻辑必须响应这些访问否则驱动加载后会卡死。所以最小系统的用户逻辑至少包含对BAR0空间的读写应答逻辑用一个简单的Register File即可。状态寄存器比如一个固定值0xDEADBEEF让驱动能读回并判断设备是否正常工作。一个可写的控制寄存器让驱动能写值进来。5.2 例化IP核与连接AXI接口PGL50H的PCIe硬核对外接口是AXI4或AXI4-Stream。大部分开发场景建议选AXI4接口因为它有独立的地址读写通道适合做寄存器访问和DMA缓冲区访问。IP配置时可以选AXI4 Memory Mapped模式。IP核生成后的端口大致分几组系统接口复位、时钟、链路状态指示。PCIe物理接口TX差分对、RX差分对、REFCLK。AXI接口读地址通道、读数据通道、写地址通道、写数据通道、写响应通道。顶层逻辑要做的事就是把系统接口处理好复位同步、时钟连接把AXI接口接到你的寄存器文件或FIFO上。链路状态信号如link_up要引出来观察调试时用LED或逻辑分析仪看能快速判断链路是否训练成功。5.3 最简单的寄存器读写逻辑以AXI4接口为例BAR0空间对应一片地址映射。硬核会把主机发往BAR0地址的AXI事务转换成AXI接口上的读写请求。寄存器文件核心逻辑就是解析AXI地址并根据地址返回对应寄存器的值。一个注意事项AXI接口的读写时钟是250MHzGen2 x4模式下而你自己的用户逻辑可能工作在较低频率两个时钟域之间的数据传递要处理好。最简单的办法是把寄存器文件直接跑在AXI时钟域避免跨时钟域问题。// 伪代码寄存器文件 always (posedge axi_aclk or negedge axi_aresetn) begin if (!axi_aresetn) begin reg_status 32hDEADBEEF; reg_control 32h0; end else begin // 写通道处理 if (axi_awvalid axi_wvalid axi_wready) begin if (axi_awaddr[15:0] 16h0000) reg_control axi_wdata; end // 读通道处理 if (axi_arvalid axi_arready) begin case (axi_araddr[15:0]) 16h0000: axi_rdata reg_control; 16h0004: axi_rdata reg_status; default: axi_rdata 32h0; endcase end end end这里踩过的一个坑是AXI的握手时序arready不能一直拉高必须和arvalid同步拉高一拍并保证arready是依赖状态机的否则如果arvalid在高电平期间arready抖动容易造成事务处理错乱。最稳妥的做法是参考官方例化模板里的状态机。5.4 时钟复位处理PCIe硬核对复位时序有严格要求。IP核会输出一个user_reset信号在链路训练完成后释放用户逻辑应该用这个信号做全局复位而不是直接用外部按键复位或者上电复位。原因很简单如果链路还没训练好你就开始操作AXI接口事务大概率失败。6. 综合、布局布线到生成烧写文件6.1 约束文件的编写要点PCIe设计的时序约束里最关键的是两个输入时钟约束REFCLK 100MHz要创建时钟约束。输出延迟约束PCIe接口是源同步接口IP核内部已经做了处理和时序例外通常不需要用户额外约束但有时需要设置set_false_path跳过一些无关紧要的时序路径。PDS的约束文件格式是SDC。一个最小约束示例create_clock -period 10.000 -name refclk [get_ports refclk_p]注意PCIe差分时钟有正负两端约束时通常只约束P端作为时钟源。6.2 综合参数的一个建议PDS的综合策略里有几个预设等级。PCIe工程建议选Performance性能优先这会让工具花更多时间在时序优化上对高频的AXI接口有好处。如果选了Area面积优先有时会导致PCIe硬核周围逻辑布局紧张出现时序违例。6.3 烧写方式bit文件与固化文件的区别PCIe工程的烧写方式有讲究调试阶段用JTAG下载bit文件到SRAM掉电丢失但下载快适合反复修改。固化阶段生成.svf或.bin文件烧写到SPI Flash上电自动加载。注意固化完成后要让FPGA先加载配置再让主机加电或复位PCIe链路顺序反了可能导致链路训练时FPGA还没起来。生成烧写文件时在PDS的工程菜单里选择Generate Bitstream完成后在Output目录下能找到bit文件如果做固化镜像需要额外添加一个SPI Flash控制器IP或使用PDS的固化工具生成.mcs文件。7. 上板调试从链路训练到Windows识别7.1 上电后的第一件事看灯板子上如果有PCIe链路状态指示灯很多开发板把link_up信号引到了LED上电插进主机PCIe插槽后开机时观察灯的状态灯亮链路训练完成物理层已经通。灯闪或不亮检查参考时钟、复位、配置引脚。如果没有LED指示可以用JTAG连接PDS的ChipScope紫光同创的逻辑分析仪工具抓内部信号看link_up信号的真值。7.2 Windows设备管理器的初次识别这里有个很多人不知道的知识点Windows对PCIe设备识别是即插即用的不需要进操作系统前就看得到。上电开机后BIOS/UEFI会做PCIe枚举然后Windows继续枚举和分配资源。如果你的设备配置空间是正确的开机进入系统后打开设备管理器应该能在其他设备下看到一个新的未知设备显示PCI Device或未知设备。如果整个设备管理器里完全没有任何新设备出现排查顺序是确认板卡插好了金手指完全嵌入插槽。确认REFCLK时钟有没有用示波器量FPGA的REFCLK引脚。确认FPGA是否成功配置bit文件是否烧写成功指示灯是否正常。检查硬核是否因为配置错误而一直处在Detect状态。7.3 驱动安装完成识别最后一步Windows识别到未知设备后需要安装驱动才能看到设备管理器里正常的设备名。这里给两种方案方案一使用WinDriver或类似工具生成通用驱动WinDriver可以自动识别未知PCIe设备并生成一个基本的驱动框架适合前期验证和调试。它会把Vendor ID和Device ID读出来然后你分配一个驱动绑定。方案二写一个最简单的WDF/KMDF驱动如果做产品最终肯定要写正式驱动。前期快速验证的话可以用Windows SDK里的示例代码改一个最小驱动主要做三件事在DriverEntry里设置AddDevice回调。在AddDevice里创建设备对象。根据设备的Vendor ID/Device ID判断是否为我们的设备。一个用于快速验证的.inf文件关键部分如下[Version] Signature $WINDOWS NT$ Class System ClassGuid {4d36e97d-e325-11ce-bfc1-08002be10318} Provider %ProviderName% [Manufacturer] %ProviderName% DeviceList,NTamd64 [DeviceList.NTamd64] %DeviceDesc% PCIE_Device_Install, PCI\VEN_1D29DEV_4000 [PCIE_Device_Install] Include wdmsec.inf Needs wdmsec.inf里面VEN_1D29是紫光同创的Vendor ID不同批次或定制版本也可能是其他值DEV_4000是你在IP核配置里填的Device ID。这两个ID必须和IP核配置的一致否则驱动装不上。右键未知设备 - 更新驱动程序 - 手动选择.inf文件安装成功后设备管理器里就会出现带名字的设备条目比如PGL50H PCIe Device。7.4 快速验证读写是否正常识别成功只是第一步还要验证数据通路。最直观的方法是用一个简单的上位机工具比如使用PCITree或自写的WinDriver应用往BAR0的0x0004地址读数据应该能读到0xDEADBEEF往0x0000地址写一个值再读回来验证一致性。这一步如果通过整套PCIe通路就已经通了后面做DMA、中断、大数据传输都是在已验证的通道上加功能。8. 从识别成功到稳定传输要跨越的三个坎8.1 中断MSI配置不当导致设备报错很多人在中断上卡壳。MSI的中断消息是由硬核根据配置空间自动生成的用户逻辑只需要在IP核配置时设置MSI Capability寄存器然后在有事件时发出中断请求。常见问题MSI Enable位没有置1驱动或BIOS需要负责在配置空间把MSI Enable位写1。如果驱动没做这个操作设备发不出MSI中断。调试时用ChipScope观察硬核的中断相关信号。中断向量数量不匹配如果IP配置时设置了多个中断向量但驱动只申请了一个会导致中断消息被主机忽略。8.2 DMA最大带宽瓶颈在用户逻辑PCIe Gen2 x4的理论带宽是2GB/s单向实际上扣除协议开销实测能到1.2~1.5GB/s就很不错了。但很多人发现实际DMA速率远低于预期问题往往不在PCIe本身而在用户逻辑的数据源不够快。比如如果你用一个低频FIFO往AXI接口灌数据DMA自然跑不起来。要达到高带宽数据路径要设计好AXI数据宽度选128位硬核支持的最大值。突发长度Burst Length要充分利用尽量一次发256字节的burst减少AXI握手开销。源数据用异步FIFO缓冲保证AXI时钟域下数据不间断。8.3 热插拔和唤醒国产平台的一个软肋PCIe规范支持热插拔和电源管理唤醒但国产FPGA的硬核在这方面的验证相对少。在实际产品里建议默认关闭热插拔特性要求用户断电插拔以免出现设备挂了但代码没问题的情况。9. 排错手册链路训练失败的全套排查链路最后专门写一整套排查链路这也是我实际调试中总结出的经验顺序。遇到设备管理器不识别时按下述顺序查效率最高。第一步确认FPGA配置是否完成用JTAG连接在PDS里查看下载状态。如果bit文件没有正常下载注意上电后FPGA可能被主机复位逻辑提前唤醒导致配置失败重新下载后拔插一次板卡或重启主机。有些主板会在启动早期复位PCIe总线如果你的FPGA配置时间较长可能错过第一次链路训练窗口此时主机重启或关闭再开启就能识别。第二步检查链路状态寄存器用ChipScope抓link_up信号。如果link_up为0链路训练没有完成。需要回头查物理层信号和参考时钟。第三步检查REFCLK示波器量FPGA的REFCLK输入引脚正常应该看到100MHz、摆幅满足要求的时钟波形一般是差分LVDS或LVPECL电平。时钟幅度偏小会直接导致链路训练失败。第四步检查硬核状态输出IP核有状态输出信号如ltssm_state链路训练状态机的当前状态正常最终停在L0态。如果停在Polling.Active或Configuration.LanenumWait等状态说明对端主机没有正确响应这时查主板的PCIe插槽是否正常换个插槽试试。第五步检查设备ID和驱动匹配如果设备管理器中出现了未知设备但驱动装不上基本不是链路问题而是.inf里Vendor ID和Device ID没对上或者设备实例ID路径格式错误。重新确认ID值。刚开始做PCIe调试我建议你先在PCIe Gen1 x1模式下把所有通路跑通再切换到高配置因为链路速率越高对信号质量的要求就越苛刻问题排查的复杂度也成倍上升。10. 后续可以扩展的三个方向整套流程走通后可以考虑在现有基础上做下面几个扩展都基于同一套硬核和框架高速数据采集系统把ADC采样数据通过AXI-Stream接口直接注入PCIe DMA通道实现连续采数上送主机。多通道DMA引擎在硬核的AXI接口上加DMA控制器实现多个描述符链批量搬移大块数据。多板卡协同多块PGL50H板卡插在同一主机上区分不同设备的实例枚举用同一个驱动管理多个设备实例。我个人在实际调试中体会最深的一点是PCIe调试的本质不是调FPGA而是建立一个信号-时序-软件配置三者联动的排错思维。同样的报错现象可能来自PCB信号问题也可能来自IP配置参数错误还可能来自驱动没写对。每改一步都建议只动一个变量否则问题交织在一起时很难准确定位。遇到卡壳时多做一次从物理层到应用层的状态确认往往比盲目尝试配置参数更有效。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表