做FPGA项目做到一半,发现要接一路MIPI摄像头、一路HDMI显示,还得跟ARM或者PC端做高速数据交互,这时候板卡的选型就成了第一个绕不开的坎。我当时拿到紫光同创PGL50H盘古50KH视频板,第一反应是"国产FPGA做视频处理到底行不行",用完整套工具链和开发流程之后,我的结论是:这块板子在多媒体处理和高速通信这个定位上,确实能干活,而且踩过坑之后效率可以很高。这篇文章就把我从零开始做视频通路、DDR缓存、高速接口的完整过程摊开讲,包括PDS工具链的license配置、资源规划、带宽计算、时序收敛这些关键环节,希望给准备上手同类型板卡的工程师省点时间。
1. 项目选型:PGL50H与盘古50KH的组合到底能接住哪些活儿
很多做视频或通信项目的人一开始都会纠结:PGL50H这个级别的FPGA,够不够用?我的回答是,关键在于你怎么定义"够用"。PGL50H属于紫光同创Logos-2系列,逻辑单元约5万级,内置Block RAM和DSP硬核,还集成了支持PCIe和千兆以太网的高速收发器通道。这个资源规模,放在纯逻辑开发里可能显得中规中矩,但放在"视频采集+帧缓存+显示输出+高速通信"的多任务场景里,卡位卡得刚刚好。
1.1 视频处理场景对FPGA资源的需求画像
先给刚接触FPGA的读者一个感性认识。视频链路里最消耗资源的往往不是算法本身,而是行缓冲、帧缓冲和时序转换。比如做1080p60的RGB888显示通路,仅像素速率一项就达到约150MHz,每一行的数据量是1920×3字节,约5.6KB。如果你想在FPGA内部做几行数据的处理,Block RAM还能勉强扛住;但一旦要做帧级别的缓存、做OSD叠加或者多路视频切换,片内RAM是绝对不够的,必须挂外部DDR。
PGL50H的Block RAM容量对做"行级处理"和"小型图像处理算子"来说很充裕,搭配板载DDR3后,帧级缓存问题也解决了。再加上DSP硬核可以用来做色彩空间转换、缩放滤波、边缘检测等运算密集型操作,一颗芯片能把"采集、处理、缓存、显示"串成一条完整链路。
1.2 盘古50KH板卡外围资源盘点
盘古50KH视频板的优势在于它不是一个裸核心板,而是围绕视频和通信场景做了外围设计。我手上这块的核心配置大致如下:
- FPGA:紫光同创PGL50H,带高速收发器
- 存储:DDR3,容量足够做多帧视频缓存
- 视频输入:HDMI输入接口、MIPI CSI摄像头接口
- 视频输出:HDMI输出、MIPI DSI显示接口
- 网络通信:千兆以太网RGMII接口
- 高速扩展:PCIe金手指接口,可以插到台式机主板上做实卡验证
- 调试接口:UART、JTAG、按键、LED、扩展排针
这个外设组合意味着你可以通过一块板子同时验证视频采集端和传输端。我在项目中实际用它完成了摄像头MIPI采集、DDR3帧缓存、HDMI显示、千兆以太网上传四个模块的联合调试。
1.3 边界在哪里:这块板卡不适合做什么
选型这件事,光看"能做什么"不够,还得看"不能做什么"。PGL50H毕竟不是动辄几十万逻辑单元的大规模FPGA,以下几类场景我建议还是换更高级的平台:
- 超大分辨率视频处理:4K60以上多路并发,带宽和存储资源会比较紧张
- 复杂的神经网络推理加速:虽然能用DSP做一些定点运算,但算力有限
- 多路高速串行接口同时跑满:如果同时要求多个PCIe通道或10G光口,资源不够
把这些边界搞清楚,后续做架构设计时才不会在一半的时候发现资源不够推倒重来。
2. 环境搭建的拦路虎:PDS安装、license激活与工程模板
紫光同创的开发工具叫PDS(Pango Design Suite),如果你之前只用过Vivado或者Quartus,刚开始会有一段适应期。PDS的界面风格和操作逻辑跟主流EDA工具相似,综合、布局布线、时序分析、在线调试这些环节都有,但一些细节藏在菜单深处,第一次用容易找不到。
2.1 PDS工具链和Vivado/Quartus的差异
从我个人的使用体验来看,PDS和Vivado最大的差异点是"工程管理逻辑":
- 在Vivado里,创建工程、添加约束、生成比特流是一套成熟的流式操作,在线调试工具(ILA)直接集成在界面里;PDS也类似,但部分IP的配置界面更"原始",需要手动关联的选项更多。
- PDS的IP核生成器覆盖了PLL、DDR3控制器、MIPI D-PHY、PCIe等常用硬核,但不像Vivado那样有大量免费图像处理IP可以直接拖。很多视频处理模块需要自己写RTL或者调用基本算子IP来搭。
- PDS的时序约束采用SDC标准语法,如果你熟悉Constraint文件写法,上手很快。
我的建议是,别急着在界面上点来点去,先花半小时把PDS的官方用户手册里的"工程创建流程"过一遍,尤其是目录结构说明和IP核生成步骤,能省掉后面很多莫名其妙的报错。
2.2 license激活的完整流程
"紫光同创license"这个热搜词确实不是凭空来的,License配置是新手最容易卡住的地方之一。PDS工具本身是免费下载的,但综合和布局布线需要有效的License,而且License跟你的网卡MAC地址绑定。
我当时按照这个流程成功激活:
- 打开PDS安装目录,找到License申请工具,或者直接从官网下载License申请模板
- 运行本机的MAC地址查询命令,把网卡MAC记录下来
- 在官网注册账号,提交MAC信息和申请表单
- 等邮件回复,通常几个小时内会收到License文件(.dat或.lic格式)
- 启动PDS,进入License配置界面,加载收到的License文件
激活后最好验证一下环境变量。PDS会读取LM_LICENSE_FILE或者PDS_LICENSE_FILE等环境变量,如果路径配置错误,工具能打开但一综合就报"License not found"。我遇到过一种情况,License文件路径里包含中文目录名,导致工具无法识别,改成英文路径后就正常了。
另外一个小提示:License里通常会包含不同的功能特性(Feature),比如综合、布局布线、仿真等可能对应独立的Feature项,如果某个操作提示缺少对应Feature,不要怀疑是License坏了,先查一下这个功能是否在你的授权范围内。
2.3 从模板工程快速出发
拿到License之后,最快上手的方法不是从空白工程开始,而是打开PDS自带的示例工程。官方例程包含了DDR3读写、MIPI RX等基础Demo,直接编译下载到板卡上能看到效果,这个过程能帮你确认:
- JTAG下载链路是否正常
- DDR3初始化是否通过
- 时钟系统是否工作正常
我在开发时就是先把"MIPI摄像头采集+HDMI显示"的官方Demo跑通,然后再逐步替换成自己的模块。这个方法对于任何新板卡都适用,先跑通最小系统,再往上叠加功能。
3. 数据通路设计:视频流与高速通信共享DDR3的方案
做视频板最核心的就是DDR3数据通路。盘古50KH板卡上所有需要大数据吞吐的模块——MIPI摄像头、HDMI显示、千兆以太网——最终都要跟DDR3打交道。如果数据通路设计不合理,轻则带宽不够导致花屏,重则多个模块互相抢占导致系统卡死。
3.1 总体数据流架构
我的方案是构建一个以DDR3为中心的AXI互联架构:
- MIPI CSI-2接收模块把摄像头数据解析成并行像素流,经过一个写通道模块转换成AXI写请求,送入DDR3控制器
- 显示输出模块通过AXI读请求从DDR3取出帧数据,送入HDMI TX接口
- 千兆以太网模块通过独立的AXI端口访问DDR3中的数据包缓存
- 一个轻量级ARM软核(如果有需要)通过AXI总线配置各个模块的寄存器
这个架构的优点在于,每个外设模块都通过AXI接口连接DDR控制器,逻辑上互相独立,只要仲裁器保证优先级合理,就能做到"视频写入、视频读取、网络读取"三条数据流并行工作。
3.2 DDR3带宽核算法
在做具体设计之前,我把DDR3的带宽需求算了一遍,这个计算非常关键,直接决定你能不能跑1080p60。
以1080p60 RGB888为例:
- 分辨率:1920×1080,约200万像素
- 帧率:60fps
- 每像素3字节
- 单帧大小:1920×1080×3 ≈ 6.2MB
- 写入DDR3带宽:6.2MB × 60 = 373MB/s
- 读出DDR3带宽:同样373MB/s
- 加上刷新开销和其他模块占用,DDR3总带宽需求大约在800MB/s ~ 1GB/s
DDR3即使在较低的时钟频率下(比如400MHz DDR,数据率800Mbps),16位总线也能提供约1.6GB/s的理论带宽,32位总线则翻倍到3.2GB/s。所以1080p60场景下带宽余量是够的。但如果你想做4K30,像素量是1080p的4倍,带宽需求瞬间飙升到约3GB/s,这时候就必须仔细计算,并且可能需要对数据格式做压缩(比如YUV422替代RGB888,带宽减半)。
我的做法是在设计文档里画一张带宽分配表,把每路数据的带宽需求、突发长度、优先级都列出来,避免拍脑袋分配。
3.3 仲裁与优先级设计
多个AXI主机共享DDR3时,仲裁策略会影响实际吞吐。我推荐以下优先级设置:
- 实时性要求最高的视频显示读取:最高优先级,因为刷新一旦断流就会闪烁或黑屏
- 摄像头写入:中高优先级,摄像头数据如果不及时写入,要么丢帧要么DDR带宽被无意义占用
- 以太网读取:中优先级,网络数据包有缓冲可以容忍一定延迟
- CPU配置读写:低优先级,寄存器读写本身频率很低,不需要抢占带宽
实际实现时,我一般给仲裁器加上"防饿死"机制:高优先级请求次数超过一定阈值后,强制让低优先级通道有一次访问机会,避免以太网和CPU完全被饿死。
4. 视频处理链路实现:把摄像头图像送到屏幕上
视频链路是整个项目中最直观、也最容易出成就感的部分,但由于涉及多个时钟域和时序协议,同时也是坑最多的地方。我按照"输入→缓存→处理→输出"的顺序逐个模块说。
4.1 MIPI CSI-2输入子系统搭建
MIPI摄像头接口在PGL50H上通过板载D-PHY引脚接入,PDS提供了MIPI D-PHY IP核和CSI-2控制器示例。
需要注意的几个点:
- D-PHY的时钟是由摄像头端随路提供的,进入FPGA后要经过一个物理层接收模块,产生字节时钟和像素时钟。这里的时钟域非常关键,所有后续处理必须在这个"像素时钟域"下操作,或者通过异步FIFO切换到系统时钟域。
- MIPI可以配置为1-lane、2-lane或4-lane模式,lane数越多,同一像素时钟下能跑的帧率越高。我用的摄像头是4-lane,实测1080p30没有问题。
- 收到数据后,CSI-2协议解析层需要恢复出行场同步信号。很多初学者在这里犯迷糊,以为MIPI也有和传统BT.656类似的独立同步信号,其实CSI-2是把同步信息编码在包头里,解析时要特别留意帧开始、帧结束、行开始、行结束这四个关键包。
我在调试MIPI时,喜欢在FPGA内部用逻辑分析仪抓CSI-2解析后的数据,确认行场时序。如果发现图像滚动、偏移或者花屏,基本就是行同步计数或者包解析的字节数错了。
4.2 帧缓存与显示通路
摄像头数据进入FPGA逻辑后,会先写入DDR3的一片帧缓冲区域,然后显示输出模块再从DDR3读出来送HDMI。
这里涉及一个常见设计模式——双缓冲或三缓冲。双缓冲的意思是,DDR3中开辟两个帧缓冲区,摄像头模块写缓冲A时,显示模块读缓冲B,下一帧写缓冲B时,显示模块读缓冲A,两者交替。这样做可以避免读写同一帧时出现撕裂(画面上下部分是新旧两帧的拼接线)。
我自己实际使用的是三缓冲,多一块缓冲做余量,在DDR带宽不太紧张的场景下,三缓冲能有效降低帧率波动带来的卡顿感。
显示输出部分,如果用的是标准HDMI接口,需要生成符合VESA标准的时序信号,包括水平同步、垂直同步、有效数据选通。PGL50H内部可以把并行RGB数据直接转成TMDS差分信号,但要注意输出时钟频率。1080p60的像素时钟是148.5MHz,这对PGL50H的I/O和PLL来说没有压力。
4.3 视频处理中的DSP应用
既然叫"多媒体处理"项目,不能只是把摄像头画面搬上屏幕,总得做点处理。我在这个项目里用PGL50H的DSP硬核实现了三个基础但实用的功能:
- 色彩空间转换:把摄像头的RGB转成YCbCr,方便后人脸检测或其他算法做分析
- 2D卷积滤波:用一个3x3的Sobel算子做边缘检测,处理结果用另一路HDMI口输出,方便做效果对比
- 简单的亮度/对比度调节:通过线性映射实现,DSP乘加一步完成
实现细节上,3x3卷积需要至少3行像素数据和9个乘加运算,DSP硬核能显著加快吞吐。如果纯用LUT搭乘法器,会消耗大量逻辑资源,而且时序也不好收敛。
PDS的IP核生成器里有基本DSP算子,但如果你想做得更灵活,自己用RTL写一个流水线卷积器也不复杂,核心是把每行像素延迟一个行周期,形成三行数据对齐窗口。
5. 高速通信实现:PCIe与千兆以太网
视频板的数据只在本机显示还不够过瘾,跨设备传输才是"高速通信方案"的重头戏。PGL50H带的高速收发器同时支持PCIe和千兆以太网,让我这两条路线都做了实测验证。
5.1 高速收发器的实例化与自环测试
不管做PCIe还是千兆以太网,第一步都是先把高速收发器的硬核跑起来。很多人忽略这个基础步骤,急着直接调协议层,结果一上来就懵。
我在板卡上跑了一个最经典的GT自环测试:把发送端的数据在芯片内部环回到接收端,然后通过FPGA内部计数器统计收发数据是否一致。这个测试能一次性验证:
- GT参考时钟是否正常
- PLL是否锁定
- 收发通道的字节对齐是否有效
值得注意的坑是GT的参考时钟输入。PGL50H的PCIe和以太网的参考时钟通常来自板载晶振或扩展接口,如果参考时钟频率选择错误(比如PCIe Gen2需要100MHz,SGMII需要125MHz),GT根本无法锁定。先看原理图确认时钟通路,再配置IP核,这是最稳妥的顺序。
5.2 PCIe端点与DMA数据传输
PCIe接口对视频板的意义在于,可以直接把采集到的图像数据高速上传到PC端处理,同时从PC端下发配置和控制命令。
PDS提供了PCIe IP核,我配置成了Endpoint模式(Gen2 x1或者x2,看板卡支持)。从上位机角度看,FPGA会枚举成一个PCIe设备,包含若干BAR空间:
- BAR0:控制状态寄存器,PC通过读写BAR0来下发配置,比如采集帧率、分辨率、启动/停止采集
- BAR2:用作DMA描述符的环形缓冲区,PC端填写描述符,FPGA端读取后发起DMA传输
在PCIe DMA的实现上,我踩过一个很有意思的坑:如果不做描述符解析和缓存,而是PC每发一次请求FPGA才搬一次数据,吞吐量只能达到几十MB/s,远远达不到PCIe应有的性能。后来改成描述符环机制,FPGA主动从DDR3中读出视频帧,然后通过DMA写入PC内存,吞吐量才真正跑起来。
如果要简单评估PCIe性能,可以在FPGA内部生成一个固定测试图案,通过DMA不断上传,在PC端用工具统计接收速度。实测下来,采用合理的描述符机制,跑满几百MB/s是可行的。
5.3 千兆以太网UDP传输方案
在不需要PCIe的场景下,千兆以太网是更通用、更容易调试的高速通信方案。盘古50KH板载RGMII接口,外接PHY芯片,FPGA侧需要实现MAC层。
有两条路可选:
- 使用PDS的以太网MAC IP核,配合自己写的RGMII接口驱动
- 完全用RTL实现一个精简的MAC,适用于定制化UDP传输
我选择了第二种,不只是为了"秀技术",而是因为标准MAC IP核在我需要的场景下手感比较重,而一个精简MAC配合轻量UDP协议栈,代码量大概只要几百行,逻辑开销小,调试也直观。
UDP传输视频数据的核心模块包括:
- 发送端:从DDR3读取视频帧数据,按UDP报文格式封装,加上以太网包头、IP包头、UDP头,然后通过RGMII接口发送
- 接收端:解析UDP报文,提取有效数据缓存在DDR3中,供其他模块使用
实测下来,千兆以太网的有效吞吐能做到700Mbps~900Mbps之间,对于传输1080p30的原始视频或者压缩后的码流绰绰有余。
RGMII接口的一个常见坑是时钟相位问题。RGMII约定数据在时钟上升沿和下降沿同时采样(DDR模式),因此对PCB和IO延时非常敏感。还好PGL50H的IO资源中有可调延时链,可以通过约束或者动态调节接口延时来规避时序问题。
6. 联调踩坑实录:时序、跨时钟域和带宽瓶颈
当你把视频输入、DDR缓存、显示输出、以太网上传全部拼接在一起时,事情才真正有趣起来。你以为单独验证都没问题了,合在一起就能跑,但实际上各种时序违规、数据乱码、带宽瓶颈都会在这个阶段集中爆发。
6.1 时序收敛:第一版综合全是时序违例
我的第一版设计在综合上板后发现,HDMI输出在部分分辨率下会有像素错乱,用PDS的时序报告一跑,果然是一堆时序违例。
排查后发现主要问题集中在:
- 数据总线上逻辑级数太长,导致组合逻辑路径延迟超标。解决办法是插入流水线寄存器,把一条乘法链路拆成两级。
- PLL时钟配置后,部分模块在同一时钟域内使用了过多异步复位信号,导致复位释放时钟偏斜。解决办法是把异步复位同步化,统一使用同步复位。
时序收敛的本质就是"路径长度"和"时钟频率"之间的博弈。如果一条组合逻辑路径需要经过20级逻辑门,那就把它拆成两拍来处理,代价是多一个时钟周期的延迟,但对建立时间裕量是巨大的改善。
6.2 跨时钟域处理:视频时钟与系统时钟的握手
MIPI接收逻辑工作在摄像头像素时钟域,DDR3控制器工作在自己的时钟域,HDMI输出又工作在另一套像素时钟域。三个时钟域之间通过异步FIFO或AXI同步器衔接。
我见过很多新手的做法是直接用一个全局信号去控制另一个时钟域的模块,结果就是偶尔出现错乱,而且这种问题极难复现和定位。正确做法是:
- 单bit控制信号,用两级同步器打两拍
- 多bit数据流,使用异步FIFO
- 如果要跨时钟域传递一组数据包的完成信号,不要只同步"完成"这一个bit,必须连同数据一起通过FIFO传递
我在跨时钟域上交过一笔学费:调试MIPI到DDR的写入路径时,摄像头画面偶尔出现一条水平花带。最后定位到原因是"帧结束"信号用了直接打拍同步,而它到来时对应的最后一行数据还没写完,导致DDR中的帧数据缺了尾部。改成把"帧结束"信号和行数据一起走FIFO后,问题彻底消失。
6.3 带宽性能实测与调优
联调阶段我还做了一组DDR3带宽压力测试,方法很简单:FPGA内部生成一个数据源,连续向DDR3写入128MB数据,然后读出并校验。通过逐步提高读写频率,观察控制器是否出现超时或错误。
实测下来,只要仲裁器优先级设置合理、突发长度配置得当(我用了16拍的突发),DDR3实际有效带宽能达到理论值的70%~80%。如果你发现实际带宽只能到理论值的50%以下,优先检查:
- AXI突发长度是否过短(突发长度太短会让DDR预充电和行激活开销占比过高)
- 是不是多个非对齐访问频繁切换Bank
- 仲裁器是否频繁中断长突发,导致来回切换开销
另外一个调优手段是使用DDR控制器的自动预充电功能(Auto Precharge),让控制器在突发结束后自动关闭行,省去显式发送预充电命令,能明显提升小数据包场景的效率。
做完整套联调之后,我对PGL50H + 盘古50KH这块板子的整体评价是:它用一颗中等规模FPGA把"多媒体采集处理"和"高速通信"两条主线完整地串了起来,而且留下了足够的扩展接口让你做二次开发。从工程实践的角度讲,国产FPGA工具链虽然在成熟度上和国外老牌厂家还有差距,但PDS的进化速度很快,License申请流程清晰,IP核文档也越来越完整。最后分享一个我个人的调试习惯:每次改动代码后,不要急着综合下载,先在纸上把数据流路径画出来,标出每个模块所属的时钟域,检查跨时钟域接口是否都做了同步处理。这个习惯帮我省掉了大量在板卡上抓波形的时间,也推荐给所有做FPGA项目的朋友。