FPGA图像处理入门:HDMI视频输入与环路输出实验解析 📅 发布时间:2026/9/7 4:48:27 👁 浏览次数: 做FPGA开发尤其是想往图像处理方向走的朋友HDMI 视频输入与环路输出实验基本是绕不开的一课。它听着像是个“外设接口实验”但跑通之后你会发现整个视频采集链路——从 TMDS 差分信号到 RGB888 像素流、从行场同步到数据有效信号、从像素处理到再输出——全都串起来了。黑金的 FPGA 基础课程里把这个实验放在很靠前的位置我认为是对的它门槛不高不需要 DDR 帧缓存又能让你肉眼直接看到 FPGA 在“干活”。这个实验做完你再去碰图像滤波、目标检测、多路拼接这类项目心里才真正有底。这篇文章我会尽量按带新人时的思路来写实验构架以 Xilinx Artix-7 系列开发板加外置 HDMI 收发芯片的经典方案为例适合入门到进阶的 FPGA 开发者参考。1. 实验定位与整体设计思路1.1 为什么入门视频实验首选 HDMI 接口FPGA 接触视频接口的路径其实不少常见有 HDMI、DVI、LVDS、MIPI、eDP 等等。但真正适合拿来入门“视频数据流处理”的HDMI 是最友好的一档。原因很直接HDMI 在逻辑侧解出来的数据格式非常干净本质上就是“像素时钟 RGB888 DE HS VS”这几根信号和早期 VGA 的时序模型一脉相承。你不用先去折腾 MIPI 那种基于 lane 的字节流解包也不用像 LVDS 那样纠结串行通道映射HDMI 接收芯片已经帮你把最麻烦的 TMDS 解码做完了FPGA 要做的只是按 DE 信号把像素数据接住然后该怎么处理就怎么处理。同时 HDMI 接口本身非常普及信号源随手就能找到。电脑主机、电视盒子、游戏机甚至一块带 HDMI 输出的开发板都能当实验信号源。显示器也到处都有不用额外买专用设备。对比之下MIPI 信号源基本只能在手机模组和专用测试板上找eDP 又大多出现在笔记本屏幕上配套的转接板都不好买。所以我一直建议新人如果目标是先搞懂视频流在 FPGA 里是怎么流动的从 HDMI 入口下手是性价比最高的路径。1.2 环路输出到底在“环”什么“环路输出”这个词英文叫 Loop-through字面意思就是信号从入口进来经过处理后形成一条环形的通路再送出去。放在这个实验里具体干的事情是外部 HDMI 信号源输出的视频信号通过 HDMI 线接到 FPGA 开发板的 HDMI 输入接口板上的接收芯片把串行的 TMDS 信号解码成并行 RGB888 数据送进 FPGAFPGA 内部可以对这路视频做任意处理比如灰度化、颜色反转、叠加边框处理完的数据再送给 HDMI 发送芯片编码成 TMDS 信号从 HDMI 输出接口出去最终在显示器上显示出来。这个“环”的意义在于它完整经历了一次“视频进来 → FPGA 处理 → 视频出去”的闭环。信号源、开发板、显示器三者串在一起形成一条有始有终的链路。跟那种只做 HDMI 输出、用 FPGA 内部生成彩条信号的实验相比环路输出多了“外部视频输入”这一环难度上了一个台阶因为你要面对的是外部信号源的时序、时钟恢复、有效数据窗口这些真实问题。跟“视频输入后存到 DDR 再做处理和输出”的方案相比环路输出又是简单的不需要帧缓存不涉及跨时钟域大带宽改动输入输出用同一套时钟体系就能跑通。1.3 系统链路逐级拆解先看整体链路每一级的作用都很清楚链路节点说明关键动作视频信号源输出标准 HDMI 信号分辨率、刷新率决定像素时钟HDMI 输入线缆传输 TMDS 差分信号线材质量影响信号完整性板上 HDMI 接收芯片完成 TMDS 解码恢复像素时钟和 RGB 数据输出 DCLK、DE、HS、VS、24bit 数据FPGA 内部处理模块接收并行视频流做像素级处理灰度化、反色、画框、直通板上 HDMI 发送芯片将 RGB888 重新编码为 TMDS 输出配置像素格式、时钟极性HDMI 输出线缆将处理后的信号送进显示器环路输出完成显示器呈现最终图像根据时序自动识别分辨率链路里最容易让人忽略的是“接收芯片帮你解掉了 TMDS”很多教程没有明说这一点导致新手以为 FPGA 直接去解 HDMI 差分信号。实际上除非你的板子用的是带 HDMI 硬核的 SoC 方案或者你准备用 FPGA 逻辑自己写 TMDS 收发这种也不是不行Xilinx 7 系列可以直接用 GTP/GTX 或者 ISERDES 做但难度和调试成本都在另一个量级否则普通开发板上 HDMI 输入输出几乎都是靠外部芯片完成的。搞清楚了这条链路后面调试出问题才知道往哪一级查。2. HDMI 协议基础与收发电路要点2.1 TMDS 编码与速率计算要顺利做这个实验HDMI 的物理层和数据格式还是得知道一些。HDMI 使用 TMDSTransition Minimized Differential Signaling传输数据物理上是 4 对差分线其中 3 对传数据、1 对传像素时钟。每对数据线上每个像素时钟周期要传 10 bit 经过 8b/10b 编码后的串行数据。换句话说TMDS 每通道串行速率 像素时钟 × 10。这个式子非常重要很多新人在选型、约束、查问题的时候都会用到。举两个例子720p60像素时钟 74.25 MHzTMDS 每通道串行速率就是 742.5 Mbps三个数据通道合计约 2.2275 Gbps。1080p60像素时钟 148.5 MHzTMDS 每通道串行速率 1.485 Gbps三个数据通道合计约 4.455 Gbps。注意这里不直接等于“HDMI 带宽”的常见宣传值因为官方标称带宽通常按单通道最高速率乘上因子而且有不同定义口径。但在 PCB 布线、信号完整性分析、以及判断某块板子能不能支持某种分辨率时按“像素时钟 × 10 × 通道数”去估算实际承载的数据量是准确的。在实验环境里我建议优先用 720p60 或 1080p30 做调试像素时钟分别是 74.25 MHz。这个频率对 Artix-7 这类中低端 FPGA 来说非常轻松引脚逻辑时序随便约束一下就能过布线压力小。一上来就跑 1080p60 也不是不行但如果你用的是没有认真做阻抗匹配的杜邦线或者面包板来飞 TMDS 信号这么干的人真有大概率会出一堆莫名其妙的花屏问题。2.2 引脚定义与输入电路设计HDMI Type-A 接口大家见得最多一共 19 个引脚。除了 4 对 TMDS 差分线还有几根对实验影响很大的信号背下来不亏引脚信号名作用1/34/67/9TMDS Data2/1/0 差分对三路像素数据10/12TMDS Clock 差分对像素时钟13CEC消费电子控制实验一般不用14Reserved保留通常不接15/16SCL/SDADDC 通道读取 EDID 用17DDC/CEC GND地185V Power热插拔检测和 DDC 供电19HPDHot Plug Detect热插拔检测输入电路设计上接收端通常要对输入的 TMDS 差分对做 100 Ω 差分端接这是差分信号的标配不做端接信号反射会很难看。HDMI 输入接口附近还要加 ESD 防护因为 HDMI 线缆经常热插拔静电打进来是家常便饭。很多开发板会直接选用自带 ESD 保护功能的 HDMI 连接器或者在差分线上加 TVS 管这都是成熟做法。另外很多人会搜“HDMI 供电电流需要多大”这个问题。HDMI 规范里源端 5V 引脚要求至少能提供 50 mA 电流这块电主要供给 DDC 通道、HPD 检测和接收芯片的 IO 电平使用功耗并不大。但有一个认知得纠正HDMI 线的 5V 绝不是给整个开发板供电用的更不能指望它带动 FPGA 内核。实验里如果电源方案设计不合理靠 HDMI 的 5V 去驱动整块板子是极其危险的轻则掉电重启重则烧接口。真正常见的做法是HPD 信号用一个电阻上拉到接收板自己的 3.3V5V 只做检测和 DDC 供电FPGA 供电走板卡独立电源。2.3 接收与发送芯片选型对比HDMI 环路输出实验的硬件核心是输入侧接收芯片和输出侧发送芯片。常见方案有两类第一类是完全靠 FPGA 内部逻辑或硬核收发器实现 TMDS 编解码板上只需要 HDMI 连接器和端接电阻第二类是外置 HDMI 编解码芯片FPGA 只处理并行 RGB 数据。入门实验几乎都是第二类。黑金 EGO1 这类基于 Artix-7 的板子用的就是第二类方案。接收侧常见的是 Silicon Image 的 SiI9022 或 ADI 的 ADV7611发送侧常见的是 SiI9134、ADV7513 这类芯片。它们的工作分两段接收芯片把 TMDS 解码成并行 RGB888 和 DCLK、DE、HS、VS发送芯片则做逆过程。FPGA 夹在中间只需要按芯片手册配置好寄存器、接好数据总线剩下的就是视频流处理逻辑的事了。选择这类芯片要注意几个点一是接收芯片对分辨率的自适应能力好的芯片能自动检测 720p、1080p、甚至 4K 时序差的芯片需要你在寄存器里手动指定时序参数二是时钟恢复能力低端芯片在信号源非标准时序时可能锁不住三是输出数据格式要确认清楚是 RGB888 还是 RGB565DE 极性是高还是低这些都会直接影响 FPGA 逻辑设计。拿到一块陌生的开发板第一步永远是仔细读原理图确认芯片型号、数据位序、复位和 I2C 配置方式别想当然。3. 核心细节解析与图像处理模块设计3.1 从 TMDS 到 RGB888时序恢复过程接收芯片输出给 FPGA 的信号核心是这几根像素时钟 DCLK、数据有效 DE、行同步 HS、场同步 VS以及 24 bit RGB 数据。实际上你完全可以把接收芯片想象成把 HDMI 线里的“串行像素快递”拆成了“并行像素包裹”DE 信号就是包裹上的“有效”标签——DE 为高时DCLK 上升沿对应的 RGB 数据是真实图像内容DE 为低时数据落在消隐区没有显示意义。这里想补充一个概念DE 信号在 VGA/HDMI 时序里和 HS/VS 是配套出现的。一个完整的视频帧由行同步、后肩、有效像素、前肩组成DE 只在整个有效像素区间拉高。计算像素时钟有个公式行总长 H_Total 乘以场总长 V_Total 再乘以刷新率就是像素时钟。以 1080p60 为例H_Total2200V_Total11252200×1125×60148.5 MHz。这个算法在调试外部信号源时尤其有用——如果接收芯片输出的 DCLK 频率和你预期不符说明输入分辨率或刷新率跟你想的不一样。实验里你不需要在 FPGA 里重建时序接收芯片会把恢复出的 DCLK 和行场信号都给你。但有个细节要注意有些接收芯片输出的 HS/VS 是低电平有效有些是高电平有效极性配置在初始化寄存器里。调试时一旦发现画面左右错位、上下跳首先要怀疑的就是同步极性没配对。3.2 像素处理模块的 Verilog 实现环路输出最大的学习价值就在于在任何一路视频流中间你可以插入一个“处理盒子”。先看最基础的直通数据进来什么都不改直接给发送芯片这能验证整个链路是否通。接着就可以做像素级处理了。这里给出一个灰度化模块的参考写法代码不复杂但对理解视频流很有帮助module video_proc( input wire clk_pix, // 像素时钟 input wire rst_n, input wire [7:0] r_in, input wire [7:0] g_in, input wire [7:0] b_in, input wire de_in, input wire hs_in, input wire vs_in, output reg [7:0] r_out, output reg [7:0] g_out, output reg [7:0] b_out, output reg de_out, output reg hs_out, output reg vs_out ); // 灰度计算公式Y 0.299R 0.587G 0.114B // 定点化系数取 77/256、150/256、29/256误差很小 reg [15:0] gray_sum; reg [7:0] gray; always (posedge clk_pix or negedge rst_n) begin if (!rst_n) begin gray_sum 16d0; gray 8d0; end else if (de_in) begin gray_sum r_in * 8d77 g_in * 8d150 b_in * 8d29; gray gray_sum[15:8]; end end // 同步打拍保证数据、DE、HS、VS严格对齐 always (posedge clk_pix or negedge rst_n) begin if (!rst_n) begin r_out 8d0; g_out 8d0; b_out 8d0; de_out 1b0; hs_out 1b0; vs_out 1b0; end else begin de_out de_in; hs_out hs_in; vs_out vs_in; if (de_in) begin r_out gray; g_out gray; b_out gray; end else begin r_out 8d0; g_out 8d0; b_out 8d0; end end end endmodule这里有个很多新手容易忽略的问题数据在模块里打了几拍DE、HS、VS 也必须跟着打同样的拍否则图像内容会和同步信号错位画面轻则出现边缘偏色、重则整幅图偏移。实际上处理延迟多少拍同步信号就要跟着延迟多少拍这是所有视频处理流水线的铁律。上面代码里 de_out、hs_out、vs_out 都只打了一拍和 r_out、g_out、b_out 严格对齐这就是对的。3.3 环路直通与带处理模式的切换要点环路输出实验里建议做一个可以随时切换直通和处理模式的开关这样调试会更直观。可以分配一个按键按一下直通再按一下灰度再按一下反色或者颜色通道交换立刻就能在显示器上看到 FPGA 到底在做什么。这个设计对新人理解“可编程逻辑在视频链路上做的事”有奇效。切换模式时要特别注意一个坑任何时刻都不要让输出端的 DE 信号提前拉高或者延后拉低。有些人处理帧内画框、叠加 OSD 时为了省事直接改 DE 的宽度结果就是行有效区被拉伸或者压缩显示器很可能直接黑屏或者花屏严重的会触发显示器重新协商分辨率。正确做法是DE 受输入驱动只在有效像素数据上做替换不要改动 DE 本身的时间宽度。还有一个容易被忽略的点发送芯片的输入时钟极性、数据格式、输出分辨率必须从寄存器层面和接收侧保持匹配。曾经有人接收侧解出来是 RGB888、DE 高有效发送芯片配置还停留在 RGB565、DE 低有效画面全是花的查了很久才意识到是寄存器没配。建议把接收芯片和发送芯片的初始化脚本统一放在工程里管起来做成复位后自动配置改分辨率时一起改。4. 实操手记从零搭建环路输出工程4.1 硬件连接与实验环境准备做实验之前先把设备准备好。你需要一块带 HDMI 输入输出接口的 FPGA 开发板一张带 HDMI 输出的信号源这里用电脑主机或者笔记本都行还有两根 HDMI 线和一个带 HDMI 输入口的显示器。注意很多笔记本的 HDMI 口是输出口不能当输入用信号源务必确认是输出口。连接方式信号源 → HDMI 线 → 开发板 HDMI IN开发板 HDMI OUT → 另一根 HDMI 线 → 显示器。这样整个回路就搭起来了。开发工具方面Xilinx 平台用 Vivado不同版本对器件支持有差异Artix-7 用 2018.3、2020.1 这类长期维护版本都行。实验不涉及复杂 IP一个标准工程够用。我个人习惯在工程根目录下面把 src、constraints、ip 三个目录分开src 放 RTLconstraints 放 XDC 约束ip 放 MMCM 这类 IP 工程文件。这个习惯在实验变复杂后收益很大不然等到你加帧缓存、加 DDR、加 ILA 的时候工程一团乱光是找文件就够烦的。4.2 Vivado 工程搭建与约束编写完整步骤写下来很啰嗦但核心流程是固定的新建工程器件选你板子对应的 Artix-7 型号比如 XC7A35T。添加接收芯片初始化模块多数开发板会提供 Verilog 源码通过 I2C 配置芯片寄存器以及发送芯片初始化模块。添加视频处理顶层逻辑把接收侧输出的 DCLK、DE、HS、VS、RGB 数据引到内部处理模块再从处理模块输出到发送侧。添加时钟资源。直通场景可以直接用接收芯片输出的 DCLK 作为全局时钟如果需要把 720p 转换为其他时序就要用 MMCM/PLL 重新生成像素时钟比如把 74.25 MHz 倍频。编写 XDC 约束文件包括引脚位置约束和时钟约束。综合、实现、生成 bitstream烧录到 FPGA插上 HDMI 线和显示器观察效果。引脚约束是新人最容易栽的地方。XDC 里必须对每一根接收和发送数据线、时钟线、I2C 引脚做 PACKAGE_PIN 绑定。不同开发板引脚定义完全不同务必去查板子的原理图不要猜。时钟约束也很重要如果接收芯片输出的 DCLK 是 74.25 MHz你可以在 XDC 里显式声明create_clock -name hdmi_rx_clk -period 13.468 [get_ports hdmi_rx_clk_p]74.25 MHz 对应的周期是 1/74.25 MHz ≈ 13.468 ns。这样 Vivado 在时序分析时才会以这个时钟域为基准去检查逻辑路径。有些人偷懒不写时钟约束结果实现之后时序报告一片 red烧进去显示器就是雪花回头还以为是代码问题。4.3 在线调试ILA 抓信号环路输出实验里调试手段比写代码还重要。Vivado 的 ILAIntegrated Logic Analyzer核非常实用你可以把接收侧的 DCLK、DE、HS、VS、RGB 数据引到 ILA然后在显示器出问题的时候抓一拍波形看看数据对不对。我最常用的调试顺序先抓 DE 和 HS/VS确认时序关系是否符合输入分辨率。比如信号源是 720p60DE 为高的周期应该占每个行周期的绝大部分HS 应该每行脉冲一次。如果抓到的时序根本不对先查接收芯片有没有初始化成功、芯片输出极性寄存器是否配错。时序正常之后再看 RGB 数据在 DE 为高时是否有变化如果数据一直是 0多半是数据总线位序接反了或者芯片输出了 RGB565 而你按 RGB888 解了。数据有变化但画面还是不对再怀疑同步信号和数据的对齐问题。这里有件事多说一句ILA 触发条件不要一上来就设得很复杂。新手喜欢用“R255 G0 B0”抓红点结果抓半天抓不到。正确姿势是先设深触发条件比如 DE 上升沿、VS 上升沿把一整行甚至一整帧的波形抓下来再看局部。视频信号是周期性的只要你抓到了 DE 有效窗口任何一处像素异常都能顺藤摸瓜查下去。4.4 扩展玩法FMC 联动与图像算法进阶环路输出实验做完路并没有走完恰恰是起点。最自然的扩展方向之一是往 ARM 侧联动。像 STM32H743 这类带 FMC 接口的 MCU可以直接通过 FMC 总线和 FPGA 连接FPGA 把采集到的视频帧通过 FMC 间接传给 MCU 去做算法处理再由 MCU 传送回 FPGA 输出。这种“FPGA 做前端采集和预处理、ARM 做高层算法”的构架在很多工业相机、视频分析设备里都能看到。做这个扩展实验时重点在于 FMC 读写时序的握手设计以及视频数据流的缓冲切分难度比纯 FPGA 环路输出高一些但方向很值得走。另一个扩展方向是往图像算法上板方向走。灰度化只是最简单的像素处理之后可以做颜色空间转换、直方图均衡、高斯滤波、边缘检测甚至卡尔曼滤波这类更复杂的算法在 FPGA 上的定点化实现。有人觉得算法上板门槛高但核心套路其实是一致的视频流进来按行按窗口去处理像素再把结果同步输出。好莱坞电影那种实时特效背后本质上也是这条流水线做了很多级而已。还有做 MIPI 或 eDP 转 HDMI 项目的朋友会频繁遇到“时序、lane 数、速率”的匹配问题。拿 eDP 来说它同样是差分线传输视频lane 数常见 1/2/4 对每 lane 速率按像素时钟和通道占比换算思路和 HDMI 一模一样。搞懂了 HDMI 的“像素时钟 × 通道数 总带宽”这个基本模型碰到其他高速视频接口至少不会被名词吓住。5. 常见问题排查与避坑清单5.1 无视频输入问题定位显示器没有任何画面是环路输出实验里出现频率最高的问题。遇到这种情况不要第一时间怀疑 FPGA 代码先按链路排查。第一步看信号源是否真的输出了 HDMI 信号单独插到显示器上确认一下。第二步确认 HPD 信号是否正常很多接收芯片是靠 HPD 电平判断下游设备是否连接的HPD 没拉高信号源根本不会把信号输出出来。第三步检查接收芯片初始化是否成功I2C 配置有没有写到寄存器里最简单的判断方式是抓 I2C 波形或者看芯片手册里状态寄存器的值。第四步才轮到检查 FPGA 内部逻辑。还有一个容易踩的坑没有插好 HDMI 线导致“无视频输入”。HDMI 接口没有机械锁扣比较松插不到位时 TMDS 通道会接触不良芯片检测不到时钟自然没有 DE 信号。我见过不少新人折腾一下午最后发现是线没插到底。所以排查的第一步永远是物理层线、接口、供电都确认了再往下查。5.2 花屏、错位与颜色异常花屏、错位这类问题绝大多数和同步时序有关。先整理一个快速对照表现象常见原因处理方式完全花屏、雪花点TMDS 时钟没锁住、端接问题检查接收芯片时钟锁定状态、线缆质量图像整体左移/右移HS 极性反了或 DE 对齐错误ILA 抓 HS/DE 波形确认极性寄存器配置图像上下跳动VS 极性反了调整发送芯片同步极性配置偏色严重数据位序错、RGB888/RGB565 格式不匹配对照原理图检查数据总线映射图像颜色正常但有噪点像素时钟抖动、线缆过长换短线材、适当调整时序约束画面一半正常一半花有效像素窗口截断检查 DE 高电平宽度是否覆盖全部有效像素调试花屏的时候强烈建议大家用桌面壁纸而不是纯色屏做信号源这样能一眼看出图像有没有左右错位。OLED 和普通 LCD 显示器在接收异常时序时的表现还不一样有些显示器容错性强画面虽然错位但不黑屏有些直接显示“无信号”。所以不要拿显示器“有没有画面”当唯一判定标准抓波形看时序才可靠。5.3 HDMI 供电、HPD 与线材问题搜索记录里高频出现的“HDMI 供电电流需要多大”和“HDMI 电路”相关疑问在实验里最容易转化为实际问题的是这几种一是开发板 HDMI 接口的 5V 检测电路供电不足导致 HPD 拉不高信号源不输出二是使用了特别长的 HDMI 线信号衰减严重接收芯片锁不住时钟三是用了一些转接器、分配器它们内部自己做了 EDID 管理可能导致信号源输出了一种开发板不支持的分辨率。应对建议很直接优先使用 1 米以内的品牌 HDMI 线确认开发板的 HDMI 5V 检测电路设计是否符合规范必要时用万用表量一下 HPD 引脚电平如果用了转接器先去掉转接器直连测试。有些开发板的 HDMI 输入口和输出口共用同一个 EDID EEPROM环路输出时输入和输出会互相干扰这种板子建议先把发送侧和接收侧的 I2C 地址区分配置好避免读写冲突。这个细节在某几款低价开发板上真实存在查问题的时候可以留意。5.4 避坑清单新手最容易犯的五个错误最后按我带新人的经验总结五个高频错误踩过的基本都说疼第一不查原理图就飞线。HDMI 数据线位序错了图像必然偏色或花屏而且显得很低级。第二忘记同步打拍。数据延迟了但 DE/HS/VS 没跟着延迟图像边缘出现色偏或错位。第三不写时钟约束。综合实现一堆时序违例烧进去又不稳定调试变成玄学。第四盲目上 1080p60。如果对信号完整性和时序约束没把握先用 720p60跑稳了再升分辨率。第五所有问题都归咎于 FPGA 代码。HDMI 这个链路硬件、线材、芯片配置、信号完整性都可能出问题先分层排查再动手改逻辑。这些错误都不是什么高深问题但确实是最消磨时间的。做实验时养成一个习惯每次修改后只改一个变量然后观察显示器变化不要同时动代码、约束和芯片配置否则出了问题都不知道是哪一步引入的。最后说点个人体会黑金的这个实验我前后带过不少新人做自己也在不同板子上重新搭过好几遍。每次做都有收获尤其是当你意识到显示器上的每一帧画面都是从一对对差分线上的高速串行信号一路解码、处理、再编码出来的那种“把抽象协议变成可见图像”的感觉非常上瘾。如果你正在学 FPGA这个实验值得仔仔细细做一遍甚至做完再故意制造几个故障去排查收获会比照着教程跑通一次大得多。FPGA 这东西看着教程觉得自己懂了那是错觉亲手把一个复杂链路跑通、再亲手修好它才是真的懂了。