4、HDMI接收端设计:硬件选型(ADV7611/IT6801)、原理图设计、时钟恢复
好,咱们进入第四章。这一章聊的是HDMI接收端的硬件设计。说白了,就是怎么把HDMI信号从接口上拿下来,转成我们能处理的并行视频数据。
我个人习惯把接收端设计分成三块:芯片选型、原理图设计、时钟恢复。这三块环环相扣,哪一块出问题,后面都跑不起来。
4.1 主流接收芯片选型:ADV7611 vs IT6801
市面上能用的HDMI接收芯片不少,但真正在工业级和嵌入式领域用得多的,就两家:ADI的ADV7611系列和ITE的IT6801系列。我两个都用过,各有各的脾气。
4.1.1 ADV7611
ADV7611是ADI家的经典款。支持HDMI 1.4a,最高到1080p@60Hz。它内置了EDID RAM和HDCP解密引擎。我最早用这个芯片做视频采集卡,稳定性确实好。
| 参数 | ADV7611 | IT6801 |
|---|---|---|
| 最大分辨率 | 1080p@60Hz | 4K@30Hz |
| HDCP支持 | HDCP 1.4 | HDCP 1.4 / 2.2 |
| 输出接口 | 24-bit RGB/YCbCr 4:4:4 | 24-bit RGB + 音频I2S |
| 工作温度 | -40°C ~ +85°C | 0°C ~ +70°C |
| 参考价格 | 较高 | 较低 |
关键点:ADV7611的I2C配置寄存器非常复杂。我第一次调这个芯片,光初始化序列就写了300多行。建议直接用ADI官方提供的Linux驱动,别自己从头写。
4.1.2 IT6801
IT6801是ITE(联阳)的芯片。它最大的优势是便宜,而且支持4K。我在一个低成本项目里用过它,1080p下表现不错。但要注意,它的HDCP 2.2支持需要额外授权费。
避坑:IT6801的电源纹波敏感度比ADV7611高。我曾经因为LDO选型不当,导致画面出现横纹干扰。后来换了低噪声LDO才解决。
4.2 原理图设计要点
原理图设计,我总结为「三路一控」:视频数据路、时钟路、控制路、电源。咱们一个一个说。
4.2.1 HDMI输入接口
HDMI连接器建议用带ESD保护的型号。TMDS差分对要等长布线,误差控制在±5mil以内。我习惯在每对差分线上串100nF的AC耦合电容,位置尽量靠近连接器。
// HDMI输入接口典型连接
HDMI_CONNECTOR {
TMDS_D0+ --- 100nF --- ADV7611_D0+
TMDS_D0- --- 100nF --- ADV7611_D0-
TMDS_D1+ --- 100nF --- ADV7611_D1+
TMDS_D1- --- 100nF --- ADV7611_D1-
TMDS_D2+ --- 100nF --- ADV7611_D2+
TMDS_D2- --- 100nF --- ADV7611_D2-
TMDS_CLK+ --- 100nF --- ADV7611_CLK+
TMDS_CLK- --- 100nF --- ADV7611_CLK-
DDC_SCL --- 2.2kΩ上拉 --- 3.3V
DDC_SDA --- 2.2kΩ上拉 --- 3.3V
HPD --- 100kΩ下拉 --- GND
}
4.2.2 电源设计
ADV7611需要三路电源:1.8V(核心)、3.3V(IO)、1.8V(PLL)。我建议每路都用独立的LDO供电,别用DC-DC。DC-DC的开关噪声会耦合到PLL,导致时钟抖动。
小技巧:PLL电源的滤波电容,我习惯用10μF+100nF+10nF三级去耦。10μF放远端,100nF和10nF紧贴芯片引脚。这个组合在多个项目里验证过,效果很好。
4.2.3 EDID电路
EDID是HDMI通信的「握手协议」。接收端必须提供有效的EDID数据,源端才会输出视频。我一般用一颗24LC02B EEPROM来存储EDID,或者直接用FPGA内部的BRAM模拟。
用FPGA模拟EDID的好处是灵活。我在一个项目里需要支持多种分辨率,就写了个状态机,根据HPD信号动态切换EDID内容。
4.3 时钟恢复与同步
时钟恢复,这是HDMI接收端最核心也最容易出问题的地方。HDMI信号里,时钟是和数据一起通过TMDS通道传过来的。接收芯片内部有一个CDR(Clock Data Recovery)模块,负责从数据流中提取时钟。
4.3.1 CDR工作原理
简单说,CDR就是锁相环(PLL)的一种。它比较输入数据的边沿和本地VCO的相位,然后调整VCO频率,直到锁定。锁定后,VCO输出的时钟就和源端的像素时钟同频同相了。
为什么会失锁?常见原因有两个:一是输入信号抖动太大,二是PLL带宽设置不对。我遇到过最头疼的情况是,某些笔记本的HDMI输出时钟抖动特别大,ADV7611的默认PLL配置锁不住。后来我把PLL带宽从2MHz调到500kHz,问题就解决了。
经验之谈:PLL带宽不是越小越好。带宽太小,锁定时间变长,热插拔时画面会黑屏好几秒。带宽太大,又滤不掉抖动。我一般取输入时钟频率的1/1000作为初始值,再根据实测调整。
4.3.2 同步信号处理
时钟恢复之后,我们得到的是像素时钟和并行数据。但数据里还包含了行同步(HSYNC)、场同步(VSYNC)和DE(数据使能)信号。这些信号需要正确解析,才能还原出完整的视频帧。
ADV7611的输出格式可以配置。我习惯用BT.656格式,它把同步信号嵌入在数据流里。这样FPGA端只需要一个FIFO就能完成跨时钟域处理。
// BT.656 数据格式示例
// 一行数据:SAV + 有效像素 + EAV
// SAV: 0xFF 0x00 0x00 XY
// EAV: 0xFF 0x00 0x00 XY'
// XY 包含场信息和奇偶场标志
always @(posedge pix_clk) begin
if (data == 8'hFF) begin
state <= SEEK_00;
end else if (state == SEEK_00 && data == 8'h00) begin
state <= SEEK_XY;
end else if (state == SEEK_XY) begin
// 解析XY字节,判断是SAV还是EAV
if (data[7:6] == 2'b10) begin
// 这是SAV,开始采集有效像素
capture_en <= 1'b1;
end else if (data[7:6] == 2'b11) begin
// 这是EAV,一行结束
capture_en <= 1'b0;
end
state <= IDLE;
end
end
4.3.3 时钟域交叉
接收芯片输出的像素时钟和FPGA内部逻辑时钟通常是异步的。这时候就需要异步FIFO来做跨时钟域处理。我一般用Xilinx的FIFO IP核,设置成独立时钟模式。
FIFO深度怎么选?1080p@60Hz一行有1920个像素,我习惯用2048深度的FIFO。这样即使源端和目的端有微小频率差,也不会溢出或读空。
注意:FIFO的满标志和空标志一定要做格雷码同步。我曾经偷懒直接用二进制计数器,结果出现了亚稳态,导致画面偶尔出现撕裂。后来老老实实加了格雷码转换,问题消失。
4.4 实战经验总结
最后,分享几个我在项目中踩过的坑:
- 热插拔问题:HDMI热插拔时,HPD信号会先拉高,然后源端开始读EDID。如果EDID还没准备好,源端会认为无设备。我建议在FPGA里加一个延时,HPD拉高后等200ms再响应。
- ESD保护:HDMI接口暴露在外,容易受静电影响。我吃过一次亏,没加ESD保护,结果一批板子返修。后来在TMDS线上加了PESD5V0S1UB,再没出过问题。
- PCB布局:接收芯片尽量靠近HDMI连接器。TMDS走线长度控制在2英寸以内。我见过一个设计,走线绕了半块板子,结果1080p都跑不稳。
嗯,这一章的内容就到这。HDMI接收端设计,说白了就是选对芯片、画好原理图、搞定时钟。这三步走稳了,后面的MIPI转换就顺了。