
1. 4K视频处理的板卡选型先想清楚为什么用PG2L200H做把紫光同创PG2L200H开发板当作4K视频处理的核心板我第一个要回答的问题不是“怎么跑代码”而是“这块板子到底够不够用”。很多人拿到FPGA开发板就急着点灯、抓I2C、跑彩条结果做到一半发现LUT不够、BRAM不够、或者HDMI物理层的管脚根本没拉到合适的地方整个项目推倒重来。把选型的问题前置后面才能少走弯路。1.1 为什么不用ARM/MPU而用FPGA做视频处理视频处理链路里有一个很典型的矛盾HDMI输入源的时序是死的显示器或者后级设备的时序要求也是死的但中间的图像算法是灵活的。用ARM或者Linux的MPU优点是跑算法方便缺点是视频数据进到总线再出显示延迟和带宽的不确定性很大。FPGA的优势正好是给数据流搭一条专用管道HDMI输入进来TMDS解码变成像素流像素流在FPGA内部做色彩空间转换、缩放、滤波、叠加最后再编码成TMDS送出去。整个过程每一级延迟可控带宽是并行展开的不会因为CPU负载波动掉帧。PG2L200H这颗芯片属于紫光同创的主流FPGA系列核心逻辑规模在200K左右有充足的DSP和BRAM资源去处理像素级运算。200K这个数字对于4K视频处理场景来说不算奢侈但完全够用4K30的像素时钟约297MHz4K60约594MHz只要数据位宽设计合理LUT规模是撑得住的。如果只是做一个1080p的低延迟转换器其实用更小的芯片也能做既然题目是4K视频处理就要把资源账算到4K这个档位上。1.2 选型时最该关注的三个资源维度做视频处理项目不要只盯着逻辑单元数量我习惯把资源分成三块来看LUT/FF用来搭控制逻辑、状态机、行缓冲控制、DDR读写仲裁。4K视频处理流水线一旦跑起来整条链路上的控制逻辑非常零散这里几十那里几百最后很容易吃掉一两万LUT。BRAM主要给行缓冲、FIFO、帧缓存的行切块用。比如3840宽度的24位RGB图像一行就有92,160字节如果要做3x3卷积至少要3条行缓冲BRAM不够就只能往DDR搬延迟马上变大。DSP Slice做像素计算。色彩空间转换的矩阵乘法、缩放系数计算、Sobel/高斯滤波这些都会用DSP。4K30下每像素周期只有3.37ns用DSP代替LUT拼乘法器是必须的。PG2L200H在这三块上都有余量但真正决定项目成败的往往是另一个容易被忽略的点高速I/O的数量和位置。HDMI的TMDS信号需要高速差分接口开发板在PCB设计时有没有把HDMI座子接到FPGA的高速BANK上这比芯片本身资源更重要。买板子之前一定要看原理图确认HDMI输入输出对应的FPGA引脚是不是在同一个BANK、能否使用所需的IO标准。1.3 软件开发环境PDS和IP核的熟悉成本紫光同创的FPGA开发环境是Pango Design Suite简称PDS工程管理和综合布局布线都在里面。第一次用的时候会有个适应过程很多人以前用的是其他厂商的工具按键位置和IP生成脚本都不一样容易急。我的建议是把PDS当成一个全新的工具来学不要带着既有操作的肌肉记忆硬套。PDS里生成IP核、写约束文件、跑综合和布局布线流程上是顺的。这里特别提醒一点视频项目的约束一定要重视尤其是时钟约束。4K30的像素时钟是297MHz4K60是594MHz如果约束写错了布局布线出来的时序报告会直接给你颜色看。综合过不等于能用要看时序收敛。布局布线是两件事布局决定逻辑单元在芯片上的物理位置布线决定它们之间的连线路径视频系统里的像素时钟频率高布局布线的质量直接影响TMDS输出眼图和稳定性。2. 先算清4K视频的带宽和时序再动手写逻辑FPGA视频项目最忌讳的事情就是代码还没写先不管时钟和带宽。HDMI不是简单的“有信号就能显示”它是一套带时钟、带编码、带握手协议的实时传输机制。动手之前先把HDMI协议和4K视频的数据量算明白后面所有模块的参数就都清楚了。2.1 HDMI里到底传了什么数据HDMI物理层通过TMDS通道传输数据早期版本有3个数据通道加1个时钟通道。每个数据通道传输的不只是RGB像素还有控制信号和数据包。在每一行有效像素期间TMDS通道传输的是像素数据在消隐期间传输的是HSYNC、VSYNC这些控制信号以及音频、辅助数据等信息。TMDS的由来是“最小化传输差分信号”本质是把8bit数据编码成10bit符号保证直流平衡和信号跳变密度这样接收端可以用时钟通道采样、恢复数据。这个编码不需要你从零手写但必须理解数据通道的比特率是像素时钟的10倍。比如像素时钟297MHz单通道数据率就是2.97Gbps三个通道加起来是8.91Gbps。很多初学者混淆了“像素时钟”和“数据率”的关系。像素时钟是RGB像素逐个进入链路的速度HDMI传输24位彩色每个像素需要3个通道各传8bitTMDS编码后每个通道每像素周期传10bit带宽自然就上来了。2.2 4K30和4K60的链路预算4K分辨率指的是3840x2160但这并不是真实传输的全部像素。视频信号包含行消隐和场消隐HDMI传输时必须保留完整时序。常见3840x2160p30和p60的时序参数如下分辨率帧率有效像素总行像素总行数像素时钟总TMDS带宽3840x216030Hz3840x216044002250297MHz8.91Gbps3840x216060Hz3840x216044002250594MHz17.82Gbps从这个表能看出来4K30的像素时钟正好是297MHz而4K60直接到594MHz。HDMI 1.4时代最高通常做到4K30HDMI 2.0之后才支持4K60。做系统设计的时候不要把“3840x2160”和“60Hz”默认绑定。先和客户/需求方确认帧率因为60Hz对FPGA内部逻辑、DDR带宽和PCB走线要求都高一个档次。我的做法是目标按4K60设计第一版先以4K30跑通。原因很简单4K30的像素时钟297MHz在FPGA内部更容易收敛HDMI的TMDS通道抗干扰能力也更好。等整个视频链路验证完毕再逐步把帧率提上去这样排错范围小很多。2.3 系统架构HDMI输入、处理、HDMI输出的完整链路整条4K视频处理链路可以从信号流上分为三段输入段HDMI连接器进来的TMDS信号经过PHY芯片或者FGPA高速接口恢复出像素时钟、行场同步信号和像素数据。如果要兼容外部HDMI源还需要通过I2C读取显示器的EDID让源端知道“我这边能接收什么格式”。处理段像素流按照视频处理算法依次通过色彩空间转换、缩放/滤波、OSD叠加等模块。这里的关键是数据位宽和时钟域的衔接通常会用异步FIFO把输入时钟域和处理时钟域隔离。输出段处理后的像素流进入发送逻辑生成符合目标格式的行场时序编码成TMDS后经过PHY芯片输出到显示器。这个架构决定了项目开发顺序先做输入再做输出最后把中间处理模块插进去。不要一上来就写复杂的图像算法先把HDMI输入到DDR再到HDMI输出的“空管道”打通后面加东西就简单了。3. HDMI输入输出配置管脚、硬件电路和I2C初始化顺序HDMI的软件配置难点不在像素数据而在物理层握手。我之前踩过很多次坑明明PC已经识别到HDMI输出但FPGA这边就是没有数据或者FPGA输出的彩条在显示器上花屏。这些问题绝大多数出在HDMI接口电路和初始化时序上。3.1 Type A接口信号定义与常见接口形式HDMI接口有Type A、Type C、Type D等不同物理形态Type A是最常见的19针接口。不管外形怎么变电气信号是一致的。Type A核心引脚如下引脚信号说明1/3TMDS Data2/-数据通道2差分对4/6TMDS Data1/-数据通道1差分对7/9TMDS Data0/-数据通道0差分对10/12TMDS Clock/-像素时钟差分对13CEC消费电子控制15/16SCL/SDADDC通道用于EDID传输和HDCP握手185V源端提供的5V电源19HPD热插拔检测DDC通道的SCL/SDA是I2C总线FPGA或者PHY芯片通过它读取显示器的EDID。热插拔HPD很关键只有HPD为高电平源端才认为显示设备已经就绪才会开始输出TMDS信号。所以做HDMI输入时板卡必须正确上拉HPD。3.2 TMDS硬件电路设计和布局布线要点HDMI的TMDS信号是高速差分信号硬件设计上不能当作普通GPIO处理。关键点有这几个差分阻抗控制TMDS对的差分阻抗要求通常是100ΩPCB设计时一定要按差分阻抗要求走线不能直接拿普通走线两根并列就完事。等长控制同一差分对内P/N等长要严格各数据通道之间的等长也要尽量控制否则会出现通道间偏移直接导致像素错位或者花屏。ESD保护HDMI是外露接口经常带电插拔TMDS线上必须加ESD保护器件。很多低成本板子省掉ESD用一段时间就会出问题。电平匹配如果FPGA IO的电平标准和HDMI源不匹配需要加上电平转换或交流耦合。某些HDMI PHY芯片会内置端接和均衡直连FPGA时则要注意端接电阻是否符合器件要求。这里再解释一下布局和布线的区别。布局是器件和FPGA内部逻辑在板上的物理位置安排布线是物理走线的实现路径。视频项目里HDMI连接器和FPGA之间的距离决定信号质量的基础布局比布线更关键而布线决定了阻抗连续性、串扰和损耗。很多人看到显示屏闪烁第一反应是代码问题其实是布局时把HDMI座子放得离电源模块太近噪声耦合进了TMDS。3.3 FPGA内部做TMDS解码还是外接PHY芯片HDMI输入输出怎么接到FPGA是两种常见方案方案AHDMI座子直连FPGA高速IOFPGA内部用差分缓冲和串并转换实现TMDS解码。这种方式硬件简单但对FPGA IO的接收灵敏度和内部时序要求高适合固定分辨率的场景。方案B板载HDMI PHY芯片PHY负责TMDS物理层处理并输出并行像素总线。FPGA通过I2C配置PHY寄存器后续只需要处理像素数据和时序即可。这种方式更通用方便支持HDMI 2.0的4K60。我手上这块PG2L200H开发板典型配置就是用外挂PHY芯片。好处是FPGA不用处理2.97Gbps级别的串行信号PHY已经把数据恢复成并行像素总线坏处是配置PHY寄存器也是一门学问。拿到板子后第一件事就是把PHY的数据手册完整看一遍别跳着读尤其是上电时序、I2C地址、输出接口模式这几个章节。3.4 I2C配置PHY的实用顺序PHY芯片的初始化顺序错了后面全白费。我踩过的问题包括先配置输出后配置输入导致PHY内部无像素时钟或者还没等到PLL锁定就写寄存器结果全部写飞。按照下面这个顺序来成功率最高给PHY芯片上电等待电源稳定通常是几毫秒时间按数据手册要求来。如果有复位引脚释放复位再等一段时间。通过I2C读取芯片ID寄存器确认I2C通信正常。这一步绝对不能跳过因为I2C地址和寄存器映射可能和手册上不完全一致有些板子因为地址跳线不同实际地址会偏移。配置HDMI输入相关寄存器输入通道使能、输入均衡、像素时钟分频、输出数据格式。配置EDID相关逻辑确保外部源能读到合法EDID否则PC或者播放器会提示“无信号”。读取PHY的中断状态或者锁定状态确认TMDS时钟已经锁定再往下处理像素数据。I2C配置频率不要太高100kHz到400kHz都可以。FPGA内部写一个简单的I2C Master模块通过状态机逐字节读写。这里有一个容易被忽略的细节I2C总线需要外部上拉电阻如果用FPGA的IO模拟I2C记得在约束里把IO标准设置为3.3V并且确认引脚是否支持开漏输出。否则SCL/SDA电平拉不到高I2C通信会时好时坏。4. 视频处理Pipeline设计与定点数实现的细节HDMI输入输出都通了视频处理Pipeline才是项目的核心。PG2L200H跑视频处理最重要的原则是能并行的绝不串行能定点的一定不要用浮点能缓存的要提前把带宽算好。4.1 处理流程怎么切模块一个可维护的4K视频处理系统应该按信号流切成若干独立模块每个模块之间用像素有效信号DE和行场同步信号传递控制信息。我建议的模块划分如下色彩空间转换模块把RGB转YCbCr或者反过来。HDMI源输出的常见格式是RGB或YCbCr 4:4:4而图像处理算法里YCbCr更适合对亮度和色度分别处理。缩放模块把输入分辨率缩放到目标分辨率。缩放在视频系统里几乎必用尤其是要做画中画或者分辨率转换时。滤波/边缘增强模块对亮度通道做高斯滤波或者锐化。FPGA里做卷积就是行缓冲加乘法累加器。OSD叠加模块把文字、光标或者矩形框叠加到画面上。这个模块最容易本质上是在像素坐标命中某个区域时用叠加颜色替换或混合原像素。帧缓存模块如果需要缩放、帧率转换或者去隔行就绕不开DDR帧缓存。模块之间的握手信号一定要标准化。我最常用的做法是每个模块都输入clk, rst_n, de_in, hsync_in, vsync_in, data_in输出de_out, hsync_out, vsync_out, data_out。这样模块之间可以像积木一样插拔排查问题时也可以用ILA直接抓任意一级的总线。4.2 定点数运算和色彩空间转换FPGA里不适合做浮点运算不是因为不能做而是消耗的DSP和LUT太多、时序不容易收敛。视频处理的系数基本都是固定的小数比如RGB转YCbCr的系数用定点就能满足需求。以RGB转到YCbCr为例常用公式是Y 0.257R 0.504G 0.098B 16Cb -0.148R - 0.291G 0.439B 128Cr 0.439R - 0.368G - 0.071B 128FPGA实现时我把系数放大256倍变成定点整数0.257乘以256约等于660.504约等于1290.098约等于25。运算时先乘再累加最后右移8位再加上偏移量。这样做的好处是只需要整数乘法器和移位寄存器。具体代码可以写成reg [8:0] coeff_r_y 9d66; reg [8:0] coeff_g_y 9d129; reg [8:0] coeff_b_y 9d25; wire [17:0] y_tmp r * coeff_r_y g * coeff_g_y b * coeff_b_y; wire [7:0] y y_tmp[15:8] 8d16;这里的乘法运算尽量用DSP Slice综合工具一般会自动推断。如果资源紧张也可以用移位加法的形式实现固定系数乘法但要保证时序满足像素时钟频率。4.3 行缓冲、卷积与缩放4K视频处理里最常用到的结构是行缓冲。要做3x3的卷积例如Sobel边缘检测或者高斯滤波至少需要3行像素同时参与计算。行缓冲的实现方式是用BRAM按行存储写入当前行读出上一行和上两行形成一个3x3窗口。以3840x2160图像为例一行24位RGB数据是92,160字节3行就是276,480字节。PG2L200H的BRAM块做行缓冲要把BRAM配置成大位宽模式否则读带宽不够。行缓冲的关键技巧是写指针和读指针的错位写入第N行时读出的应该是第N-1行和第N-2行这样窗口中心像素才能对齐到当前处理的坐标系。缩放模块更复杂一点。双线性插值需要计算源图像坐标用整数部分和小数部分分别查找周围4个像素。FPGA实现双线性插值时小数部分可以作为权重查表。性能更高的是多相滤波器通过一组相位系数做像素加权画质更好但消耗资源也更多。第一版建议先做双线性插值稳定后再升级多相滤波。4.4 DDR带宽规划这一笔一定要算只要用了帧缓存DDR带宽就是项目成败的关键。以4K30 RGB888为例一帧原始数据是384021603字节约24.88MB。如果处理器需要用一个帧存做缩放输入端写入一帧输出端读出一帧一帧就要读写约49.76MB。乘上30帧/秒DDR上光是帧缓存的流量就约1.49GB/s。这还不算OSD字符缓存和CPU/控制核的访问。PG2L200H开发板板载DDR的带宽通常足够但DDR控制器的效率不可能达到100%实际可用带宽要打折扣。比如DDR3-1600 16bit的理论带宽是3.2GB/s实际效率可能只有70%左右约2.24GB/s扣除帧缓存流量后余量并不多。所以设计帧缓存时要做到两点一是尽量按行/按块突发访问避免单个像素小粒度读写二是能用BRAM做行缓存的不要全部丢到DDR里减少无谓带宽消耗。还有一个常见优化如果只是做OSD叠加或者色彩空间转换完全不需要帧缓存走流式处理就够了。只有当模块需要用到前后帧数据时才必须引入DDR。4.5 跨时钟域和复位同步视频系统中的时钟域很多输入像素时钟来自HDMI源的TMDS时钟处理模块可能使用FPGA内部PLL生成的处理时钟输出端又回到HDMI PHY的像素时钟。跨时钟域处理必须用异步FIFO不能简单打两拍。异步FIFO的深度根据跨时钟域的频率比例和突发大小计算通常256到1024足够。复位信号同样容易被忽略。FPGA上电或者PLL失锁时复位信号如果直接进入像素时钟域会出现亚稳态导致第一帧图像花屏或者偶发死机。正确的做法是做复位同步释放采用“异步置位、同步释放”的方式让复位信号在目标时钟域内先打两拍再释放。这个教训我在项目里遇到过很多次特别是直接从按键或者电源监控信号拉复位时问题尤其明显。5. 上板调试HDMI无图像的完整排查链路软件仿真只能证明代码语法正确、时序大致合理上板才是真正检验项目的地方。视频系统的调试和普通串口调试不同不能打印一行printf就判断图像对不对。我调试HDMI输入输出时有一套固定的排查链路可以帮你快速定位90%的问题。5.1 第一步先不要接视频源先把自检彩条跑通无论HDMI输入还是输出建议先在FPGA内部生成一个测试图源比如彩条或者棋盘格直接把数据送到HDMI输出PHY。这一步能验证三件事FPGA到HDMI PHY之间的像素总线和时序是否正常PHY芯片I2C配置的结果是否生效显示器和HDMI线缆是否支持当前分辨率彩条模式下如果显示器能正常显示说明输出链路没问题。如果不能显示就要按照下面的链路排。5.2 输入无信号时的最完整排查顺序当HDMI源插入后FPGA侧一直没有有效像素数据按以下顺序逐步定位看HPDHDMI源一定要在HPD为高时才输出信号。用万用表测HDMI座子第19脚如果没有高电平说明接收端的HPD没有拉起来。检查对应引脚是否有上拉、PHY或FPGA是否已经配置为HPD输出状态。看5VHDMI座的5V是源端提供的如果源端没有输出5V很多PHY芯片内核就不会工作。测18脚电压正常应该是5V左右。读PHY芯片ID通过I2C扫地址确认PHY芯片能正常响应。如果I2C读不到检查SCL/SDA上拉、电平、复位引脚。检查TMDS时钟锁定PHY芯片一般会有一个锁定状态寄存器指示TMDS时钟是否锁定。如果始终不锁定大概率是物理层问题比如线缆、HDMI座虚焊、差分信号极性反了。抓像素总线的DE信号用逻辑分析仪/ILA抓HDMI PHY输出的de和vsync/hsync确认输入已经开始有视频有效信号。如果DE一直为低说明PHY没有识别到视频源如果DE存在但像素数据全零再往前查输入配置寄存器的格式。看分辨率是否在EDID内源端能否输出正确分辨率取决于接收端EDID。用I2C回读EDID数据确认里面写的时序参数和板卡期望处理的分辨率一致。这张排查表是一个保底方案遇到黑屏时按顺序走不要跳过HPD直接去抓像素数据。很多问题的根源就在硬件握手阶段。5.3 输出端黑屏或花屏的特殊排查点如果输入端已经抓到了正常的像素数据和DE但显示器一直黑屏就要从输出PHY侧重新查起。输出PHY的像素时钟有没有生成。很多PHY要求FPGA提供输出像素时钟如果这个时钟没有输出或者频率不对PHY不会进入正常工作状态。输出格式配置是否正确。比如PHY配置成RGB888输出但FPGA侧一直给的是YUV444色彩空间不匹配就会偏色或者无法显示。显示器的EDID回读。如果输出端连接的不是HDMI直通设备而是经过转换器或者采集卡EDID里的时序可能和显示器真实能力不一致导致无法显示。时钟极性或差分极性。HDMI标准允许时钟和数据极性反相在物理上不工作但不同PHY的寄存器不一样有一个专门的字段来控制极性配置错了会花屏或完全无信号。5.4 用好ILA抓时序而不是靠眼睛盯屏幕调试视频系统最忌讳的是反复插拔HDMI线盯着显示器看效果。正确做法是用FPGA内部的逻辑分析仪抓关键信号。紫光同创的PDS软件带逻辑分析仪功能可以在线抓取FPGA内部信号。我需要抓的信号包括PHY输出的de、hsync、vsync、data[23:0]以及DDR控制器的读写请求、异步FIFO的空满标志。抓数据时要注意设置合适的触发条件。比如找黑屏问题可以设置de上升沿后连续抓若干个像素时钟周期找花屏问题则连续抓整个行循环看行有效像素个数是否正好是3840。逻辑分析仪采样深度有限4K30下行像素时钟297MHz抓几万个周期也就一毫秒不到但足够看出问题。要是怀疑帧缓存数据错误可以抓DDR读写两边的地址和数据对比是否有覆盖或者错位。6. 从4K30到4K60以及视频系统的后续扩展第一版把4K30整个链路跑通后整个开发板的能力边界已经摸清了。接下来如果需求要提帧率到60Hz不是简单改一下参数的事情而是从硬件到逻辑都要过一遍。6.1 升级60Hz时最容易卡住的地方4K60的像素时钟是594MHz整个数据通路都要重新评估PHY芯片是否支持HDMI 2.0。HDMI 1.4的PHY最高只能到300MHz左右像素时钟必须确认PHY型号支持594MHz。FPGA到PHY之间的并行数据总线位宽可能不够。很多PHY在高分辨率下会切换到双沿采样或增加总线位宽如果FPGA侧代码默认只有一个像素一拍需要在逻辑上改成双像素或四像素并行。DDR带宽翻倍。4K60帧缓存读写带宽是4K30的两倍约3GB/s几乎把16bit DDR3的可用带宽吃满。如果同时还要读OSD必须优化仲裁器甚至要牺牲部分功能。时序收敛难度。594MHz的像素时钟在FPGA内部不再是“怎么综合都过”的状态。建议把内部处理时钟降频采用并行多像素处理比如每周期处理2个像素时钟降到297MHz处理4个像素时钟降到148.5MHz。不要迷信“FPGA能跑到594MHz”。FPGA内部逻辑跑594MHz非常难所以主流做法都是把像素总线加宽用2像素/4像素并行来降低工作频率。PG2L200H在这个场景下完全适合并行像素架构。6.2 接入MIPI、SDI或者传感器扩展ISP能力HDMI输入输出只是4K视频处理系统的一种前端形态。同样的视频处理Pipeline也可以把前端换成MIPI CSI-2摄像头传感器接口FPGA内部做Sensor配置、去马赛克、坏点校正、自动白平衡。这个方向对资源消耗更大因为ISP算法里的去马赛克和降噪都是像素级运算需要更多DSP和BRAM。但核心架构是不变的物理层恢复像素流、像素流进入处理管线、结果输出到显示或编码模块。这次用PG2L200H搭HDMI输入输出的经验后面做MIPI ISP项目时可以直接复用。6.3 从“能显示”到“工程化”项目管理建议最后分享一点个人经验视频项目最容易翻车的地方不是算法而是版本管理。HDMI的寄存器配置极其繁琐不同PHY芯片、不同开发板版本、不同HDMI源设备的行为都可能不同。我强烈建议把PHY初始化配置单独做成一个ROM或者配置文件每次改动都记录到Git里并且给板卡上的不同信号源做一个配置矩阵。这样后续复现问题时能快速确定是寄存器值的问题还是时序问题。我在实际开发中的体会是国产FPGA工具链虽然需要一点耐心去适应但对于视频处理这类有明确时序和带宽需求的场景紫光同创PG2L200H的资源和生态是够用的。真正决定项目进度的还是你对HDMI协议的理解深度和调试排查的系统性。先把链路走通再谈优化这比什么都重要。