1. HDMI接口基础
做FPGA图像处理这些年,HDMI接口是我打交道最多的视频接口之一。说实话,刚接触那会儿我也被那些协议栈搞得头大——TMDS编码、DDC通道、EDID数据块……但搞明白之后你会发现,HDMI其实没那么玄乎。
今天我们就从最基础的东西聊起。把HDMI的底裤扒干净,后面做采集和DDR读写才不慌。
1.1 HDMI标准演进——从1.0到2.1
HDMI标准从2002年发布到现在,经历了多个版本。我最早做项目用的是HDMI 1.3,那时候1080p@60Hz就算高清了。现在2.1版本都支持8K@60Hz了,带宽飙到48Gbps。
下面这张表是我整理的几个关键版本对比,做FPGA选型时经常要翻出来看:
| 版本 | 最大带宽 | 最大分辨率 | 关键特性 |
|---|---|---|---|
| HDMI 1.0 | 4.95 Gbps | 1080p@60Hz | 基础TMDS编码 |
| HDMI 1.4 | 10.2 Gbps | 4K@30Hz | 以太网通道、ARC音频回传 |
| HDMI 2.0 | 18 Gbps | 4K@60Hz | 支持BT.2020色域 |
| HDMI 2.1 | 48 Gbps | 8K@60Hz | FRL模式、DSC压缩 |
重点提醒:做FPGA采集卡时,HDMI 1.4和2.0用的还是TMDS编码,到了2.1就换成FRL(Fixed Rate Link)模式了。如果你现在做项目,建议直接支持2.0,兼容性最好。
1.2 TMDS编码原理——数据是怎么飞起来的
TMDS全称是Transition Minimized Differential Signaling,翻译过来就是「最小化传输差分信号」。名字挺长,但核心就两件事:
- 编码:把8位数据变成10位,减少跳变次数
- 传输:用差分信号高速发送
为什么要这么做?你想想看,如果数据里连续出现01010101,信号跳变太频繁,电磁干扰就大。TMDS通过编码让跳变次数尽量少,同时保证直流平衡。
TMDS编码器内部其实有两个算法路径:
- 路径A:当数据中1的数量多,或者0和1连续出现时,取反后发送
- 路径B:否则直接发送原始数据
编码器会计算两种路径的跳变次数,选跳变少的那一路。最后再根据直流平衡状态,决定是否把整个10位数据取反。
我的经验:在FPGA里实现TMDS编码器,我建议直接用Xilinx的OSERDES原语。自己写逻辑的话,时序很容易跑不到1.65Gbps(1080p@60Hz的TMDS时钟)。
下面这张图展示了TMDS编码的基本流程,我画了个简化的框图:
注意:TMDS编码后的10位数据,在接收端需要用IDELAY做动态延迟校准。我曾经在一个项目里没做眼图优化,结果线缆长了点就出现雪花点,折腾了两天才找到原因。
1.3 HDMI连接器引脚定义——别焊错了
HDMI连接器分Type A(标准)、Type C(mini)和Type D(micro)。做FPGA开发板最常见的是Type A,19个引脚。
我刚开始做硬件时,有次把TMDS数据2和时钟通道焊反了,查了三天才发现。嗯,从那以后我每次画原理图都要对着引脚定义核对三遍。
Type A连接器关键引脚如下:
| 引脚 | 信号 | 说明 |
|---|---|---|
| 1, 4, 7 | TMDS Data 0/1/2+ | 三路数据通道正极 |
| 3, 6, 9 | TMDS Data 0/1/2- | 三路数据通道负极 |
| 10, 12 | TMDS Clock +/− | 时钟通道 |
| 15 | SCL | DDC时钟线 (I2C) |
| 16 | SDA | DDC数据线 (I2C) |
| 18 | +5V | 电源输出 (最大50mA) |
| 19 | HPD | 热插拔检测 |
布局建议:TMDS差分对要做等长布线,误差控制在±5mil以内。我一般会在PCB上预留π型滤波器的位置,万一EMI超标还能补救。
1.4 EDID与DDC协议——显示器在说什么悄悄话
EDID(Extended Display Identification Data)是显示器告诉显卡「我能支持什么分辨率」的数据块。DDC(Display Data Channel)就是传输EDID的I2C通道。
说白了,HDMI源端(比如你的FPGA板)上电后,会通过DDC通道读取显示器的EDID,然后根据EDID里的信息选择合适的分辨率和刷新率。
EDID数据块有128字节,结构如下:
- 字节0-7:头部标识,固定为00 FF FF FF FF FF FF 00
- 字节8-17:厂商信息、产品ID
- 字节18-53:EDID版本、基本显示参数
- 字节54-125:详细时序描述(DTD),最多4个
- 字节126-127:校验和
做HDMI采集卡时,我建议直接用一个EEPROM存储EDID数据。FPGA上电后通过I2C读取EEPROM,再响应显示器的DDC请求。
核心要点:EDID里的详细时序描述(DTD)包含了分辨率、刷新率、像素时钟等信息。FPGA解析这些参数后,才能正确配置PLL和DDR控制器。
DDC协议其实就是标准的I2C通信,地址是0xA0(写)和0xA1(读)。时序要求如下:
- I2C时钟频率:100kHz(标准模式)或400kHz(快速模式)
- 起始条件:SCL高电平时SDA下降沿
- 停止条件:SCL高电平时SDA上升沿
- 应答:每字节后接收方拉低SDA
我曾经在一个项目里遇到EDID读取失败的问题,用示波器抓I2C波形才发现是上拉电阻选小了,导致上升沿太慢。换成4.7kΩ后问题解决。
好了,HDMI接口基础就聊到这儿。这些内容看着多,但做项目时你会发现,真正需要关心的就是TMDS编码怎么在FPGA里实现、EDID怎么解析、DDC怎么通信。后面做采集实战时,这些知识都会用上。
小技巧:调试HDMI时,我习惯先测HPD信号——如果显示器没拉高HPD,说明物理连接有问题,后面的TMDS和DDC都不用查了。
可可精品资料库