这一篇在干嘛?
这是安路官方 APUG092 应用笔记的精讲版,讲的是官方给出的 HDMI 1.4b 发送器(Transmitter)参考设计。我们会从”HDMI 到底是怎么传画面和声音”讲起,然后逐节拆解这个 IP 的架构、时钟、参数、接口时序,最后带你走一遍上板验证流程。全文以官方手册内容为准,信号名、参数、数值都可以直接对照原文使用。
先补课:HDMI 是怎么传画面和声音的
HDMI(High Definition Multimedia Interface,高清多媒体接口)是一种全数字化的影像和声音收发接口,可以收发未压缩的音频及视频信号。机顶盒、DVD 播放机、个人电脑、投影仪、电视机上都能见到它。它最大的好处是:音频和视频走同一条线材,大大简化了系统布线。
那一条线里到底传了什么?HDMI 的视频数据用的是 TMDS(Transition Minimized Differential Signaling,最小化传输差分信号)编码方式。简单理解:把并行数据编码成 10Bit 的串行码流,再用差分线高速发送出去。整个链路里有三条数据通道(分别承载音视频数据)加一条时钟通道,这也是为什么后面会看到 ch0/ch1/ch2 三组数据加一组时钟的接口。
一个容易忽略的细节
HDMI 里除了音视频数据本身,还有很多”辅助数据”——比如告诉显示器”我是什么分辨率”的 VIC 视频识别码、帮接收端恢复音频时钟的 ACR 数据包。发送器 IP 的一个核心工作就是把这些辅助包按时序插进数据流里。
还有两个常被一起提到的概念,本文都和它们有关:
- EDID / DDC:显示器(接收端)内部存有一块 128 字节的”自我介绍”数据,叫 EDID,里面写着它支持哪些分辨率、音频格式等。FPGA 想知道”对面是谁、能吃多高的分辨率”,就要通过 HDMI 的 DDC 通道(本质上是一条 IIC 总线)把 EDID 读回来。本设计就内置了 EDID 读取功能。
至于 HDCP 内容保护,这份手册并未涉及,这里不多展开。
这个发送器能干什么:特性与规格
这套 HDMI 1.4b Transmitter 参考设计在安路 AP106_V2.0 开发板上开发验证,支持的功能清单如下:
- 符合 HDMI 1.4b 协议标准;
- 最高支持 1080p60 显示分辨率;
- 支持两路音频(左、右声道);
- 支持 RGB 和 YUV444 两种视频颜色空间(均仅支持 8Bit);
- 支持内部视频测试源,不接外部视频也能输出测试画面;
- 支持 EDID 读取。
它的设计目标是”以较少的资源实现音频和视频数据的高速传输”——资源消耗后面有具体数字。
整体架构:协议层 + 物理层
官方把整个设计分成两层,先看框架图:

- 协议层:HDMI 1.4b Transmitter Core。负责所有”讲协议”的部分,对外提供 EDID Interface、Video Interface、Audio Interface、ACR Interface、DDC Channel、Link Data 等接口。
- 物理层:HDMI TX PHY。负责把编码后的 10Bit 数据串行发送出去。手册特别说明:物理层不限定实现方式,只要线速率满足要求、能实现 10Bit 数据串行发送、外部电路能满足 HDMI 电平要求,都可以拿来当物理层。这种解耦让你可以按所用的器件灵活选择串化方案。
为什么要分层?
协议层和物理层相互分离(这是 v1.0 版本特意修改的整体架构),好处是:协议逻辑可以跨器件复用(参数里的 DEVICE 选项覆盖了 EF2/EF3/EF4、SF1/SF2、EG、PH1A/PH1P/PH2A、DR1 等多系列),物理层则可以按器件的 IO 能力单独适配。
时钟架构:两个时钟、五倍关系
用这个 IP,第一件要搞懂的就是时钟。看官方时钟架构图:

IP 工作需要两个时钟,都由 PLL 生成:
- 像素时钟 Pixel Clock:Core 的四个接口(EDID、Video、Audio、ACR)全部工作在这个时钟域下;
- 串行发送时钟 Serial Clock:频率是像素时钟的 5 倍(因为 1 个像素要串行发出 10Bit 数据,三条数据通道各分摊,时序上对应 5 倍过采样关系)。
频率怎么算
像素时钟不是拍脑袋定的,要根据分辨率算。以 1080p60 为例:有效分辨率是 1920×1080,但计算频率时必须加上消隐区,图像总长宽是 2200×1125,每秒 60 帧:
串行时钟再乘 5:
时钟算错,画面就废
像素时钟忘记加消隐区(比如用 1920×1080 而不是 2200×1125 去算),或 PLL 没按 5 倍关系生成 Serial Clock,都会导致接收端无法正确同步。换分辨率时,两个时钟都要重新计算配置。
参数怎么配:一张表定分辨率和格式
HDMI 1.4b Transmitter Core 通过一组参数来定制行为,官方参数表如下(表 2-1):
| 参数 | 可选值 | 默认值 | 说明 |
|---|---|---|---|
| DEVICE | ”EF2”, “EF3”, “EF4”, “SF1”, “SF2”, “EG”, “PH1A”, “PH1P”, “PH2A”, “DR1" | "EG” | 器件类型选择 |
| HTOTAL | 1~16383 | 2200 | 一行总长度,包括行消隐和行有效,单位为时钟个数 |
| HSA | 1~16383 | 44 | 行同步脉冲宽度,单位为时钟个数 |
| HFP | 1~16383 | 88 | 行显示前沿,单位为时钟个数 |
| HBP | 1~16383 | 148 | 行显示后沿,单位为时钟个数 |
| HACTIVE | 1~16383 | 1920 | 一行有效显示长度,单位为时钟个数 |
| VTOTAL | 1~16383 | 1125 | 总列数,包括场消隐和场有效部分,单位为图像行数 |
| VSA | 1~16383 | 5 | 场同步脉冲宽度,单位为图像行数 |
| VFP | 1~16383 | 4 | 场显示前沿,单位为图像行数 |
| VBP | 1~16383 | 36 | 场显示后沿,单位为图像行数 |
| VACTIVE | 1~16383 | 1080 | 有效列数,单位为图像行数 |
| VIDEO_VIC | - | 16 | 视频识别码 |
| VIDEO_TPG | ”Enable” / “Disable" | "Enable” | 测试视频源使能:“Enable” 时使能测试视频源、外部视频输入无效;“Disable” 时禁用测试视频源 |
| VIDEO_FORMAT | ”RGB” / “YUV444" | "RGB” | 视频格式:外部输入视频为 RGB 或 YUV444 |
| AUDIO_SAMPLE_RATE | ”32K” / “44.1K” / “48K” / “88.2K” / “96K” / “176.4K” / “192K" | "48K” | 音频采样率 |
| IIC_SCL_DIV | 1~65535 | 125 | EDID IIC 时钟分频系数 |
注意默认值这一列:HTOTAL=2200、HACTIVE=1920、VTOTAL=1125、VACTIVE=1080——默认参数就是按 1080p60 配的,和上一节的频率计算完全对应。
视频分辨率参数与时序
HTOTAL、HSA、HFP、HBP、HACTIVE、VTOTAL、VSA、VFP、VBP、VACTIVE 这十个参数共同决定显示分辨率。它们对应的标准视频时序长这样:

- 行方向:一行 = HSA(同步脉冲)+ HBP(后沿)+ HACTIVE(有效 1920 像素)+ HFP(前沿)= 2200 个像素时钟;
- 场方向:一帧 = VSA + VBP + VACTIVE(有效 1080 行)+ VFP = 1125 行。
想换分辨率,就按目标分辨率的标准时序改这十个数,同时别忘了同步改时钟。
VIDEO_VIC:告诉对面”我是什么格式”
VIC 是视频识别码,写进 HDMI 辅助视频信息包里,不同的视频格式有唯一的识别码(比如默认的 16 就对应 1080p60)。具体码表可以在《ANSI/CTA-861-H》标准里查。分辨率换了,VIC 也要跟着换,否则接收端可能按错误的方式解析画面。
VIDEO_TPG:内置测试画面
Core 内置了测试视频源。VIDEO_TPG 设为 “Enable”(默认)时,会按固定顺序循环播放测试画面,此时外部输入的视频无效;设为 “Disable” 才轮到外部视频上场。测试画面顺序如下:

测试源只认 RGB
内部测试视频源只支持 RGB。所以 VIDEO_TPG=“Enable” 时,VIDEO_FORMAT 必须同时设为 “RGB”,否则显示的颜色会异常。上电先开 TPG 看彩条、再切外部源,是很好的验证顺序。
VIDEO_FORMAT:声明颜色空间
VIDEO_FORMAT 用来告知 HDMI 接收端图像数据的颜色空间:外部视频是 RGB 就设 “RGB”,是 YUV444 就设 “YUV444”。目前 RGB 和 YUV444 仅支持 8Bit。
AUDIO_SAMPLE_RATE:音频采样率
可选项有 “32K”、“44.1K”、“48K”、“88.2K”、“96K”、“176.4K”、“192K”,需要按实际的音频采样率来设定,默认 “48K”。
IIC_SCL_DIV:EDID 读取的 IIC 时钟
这个参数设定 EDID IIC 时钟的分频系数,计算公式为:
例如像素时钟 150M、IIC_SCL_DIV=125 时,IIC 时钟 = 150M/(2×125) = 600kHz。
接口信号一览:Core 的”面板”
参数配好后,就要接线了。先看 Core 的接口全景图:

Core 的接口包括:工作所需的时钟和复位信号、EDID 读取接口、视频数据输入接口、音频数据输入接口、音频时钟再生辅助数据包(ACR)输入接口、TMDS 编码输出接口和 DDC 信号。完整信号表(表 2-2)如下:
| 接口名称 | 信号名称 | 方向 | 时钟域 | 描述 |
|---|---|---|---|---|
| clock and reset | I_pixel_clk | in | NA | 像素时钟 |
| clock and reset | I_rst | in | NA | 异步复位信号,高电平有效 |
| EDID Interface | I_edid_read_trig | in | I_pixel_clk | EDID 读触发信号 |
| EDID Interface | O_edid_read_valid | out | I_pixel_clk | EDID 读有效信号 |
| EDID Interface | O_edid_read_data[7:0] | out | I_pixel_clk | EDID 读数据 |
| Video Interface | I_axis_s_user | in | I_pixel_clk | 视频输入帧起始信号 |
| Video Interface | I_axis_s_valid | in | I_pixel_clk | 视频输入有效信号 |
| Video Interface | I_axis_s_data[23:0] | in | I_pixel_clk | 视频输入数据 |
| Video Interface | I_axis_s_last | in | I_pixel_clk | 视频输入行结束信号 |
| Video Interface | O_axis_s_ready | out | I_pixel_clk | 视频输入 ready 信号 |
| ACR Interface | I_acr_valid | in | I_pixel_clk | ACR 有效信号 |
| ACR Interface | I_acr_cts[19:0] | in | I_pixel_clk | ACR CTS |
| ACR Interface | I_acr_n[19:0] | in | I_pixel_clk | ACR N |
| Audio Interface | I_audio_valid | in | I_pixel_clk | 音频输入有效信号 |
| Audio Interface | I_audio_left_data[23:0] | in | I_pixel_clk | 音频左声道数据 |
| Audio Interface | I_audio_right_data[23:0] | in | I_pixel_clk | 音频右声道数据 |
| Status Signal | O_video_locked | out | I_pixel_clk | 输入视频接口锁定信号 |
| HDMI DDC Interface | O_ddc_scl | out | I_pixel_clk | DDC 通道时钟 |
| HDMI DDC Interface | IO_ddc_sda | inout | I_pixel_clk | DDC 通道数据 |
| Link Data | O_ch0_tmds_data[9:0] | out | I_pixel_clk | 通道 0 编码数据输出 |
| Link Data | O_ch1_tmds_data[9:0] | out | I_pixel_clk | 通道 1 编码数据输出 |
| Link Data | O_ch2_tmds_data[9:0] | out | I_pixel_clk | 通道 2 编码数据输出 |
| Link Data | O_clk_tmds_data[9:0] | out | I_pixel_clk | 时钟通道编码数据输出 |
几个关键接口的读法:
- Video Interface:这是一个类 AXI-Stream 风格的握手接口——
user标一帧开始、valid/ready握手传数据、last标一行结束,24Bit 数据正好装下一个 RGB(或 YUV444)8Bit 像素; - Link Data:三组 10Bit 数据 + 一组 10Bit 时钟通道编码,这就是要交给物理层做串行发送的东西;
- O_video_locked:状态信号,视频时序锁定后拉高,后面细讲。
复位是高电平有效
I_rst是异步复位、高电平有效。接到自己的设计时注意极性,别用低电平有效的复位直接怼上去。
接口时序逐个看
EDID Interface:一拍脉冲,读回 128 字节

用法非常简单:I_edid_read_trig 是一个单时钟周期的脉冲,拉高一次就触发一次 EDID 读操作,Core 会通过 DDC 通道读出 128 字节 EDID 数据;在 O_edid_read_valid 为高期间,O_edid_read_data[7:0] 上的数据有效。你在自己的逻辑里数好字节、攒成完整 EDID 即可。
Video Interface:握手规整,但一行不能断

时序要点:
I_axis_s_user:帧起始信号,单时钟周期,在第一行第一个有效数据处拉高;I_axis_s_valid:数据有效;I_axis_s_last:行结束信号,在一行数据结尾拉高;O_axis_s_ready:接收端准备信号,为高表示可以写入数据。
最容易踩的坑:数据不能断流
O_axis_s_ready只会在I_axis_s_last(行结束)之后拉低,再次拉高表示能继续写入。因此 Video Interface 不支持断续的数据输入——一行数据必须连续发完。如果你的视频源做不到行内连续,就得自己加 FIFO/缓存来保证。
相位匹配与锁定:O_video_locked 为什么重要
在 HDMI 协议中,视频和辅助数据的发送要遵循严格的视频时序。为了保证发送时序稳定,Core 内置了一个 Video Source,用来生成不同分辨率的视频控制信号,然后视频数据和辅助数据先后映射到传输路径上。
问题来了:视频数据量太大,不可能把一整帧缓存下来,所以外部视频数据映射到 HDMI 数据路径时必须考虑相位问题——内部 Video Source 生成的时序和外部输入的数据之间有偏移,若外部数据超前或滞后,映射时就会数据错位。
Core 内部为此设计了相位匹配机制,对内、外视频时序做相位校准。当两者对准并锁定后,O_video_locked 信号拉高,表明视频输入数据被正确捕捉。上板调试时,这个信号就是你判断”视频链路对没对上”的第一观测点。
外部输入的三个关键参数
要把外部视频正确映射进传输路径,需要注意行长度、行间距、帧间距三个参数:

对照图中定义和前面的分辨率参数:
- 行长度 line_length = HACTIVE(一行实际长度,1920);
- 行间距 line_space = HTOTAL(图像一行总长度,2200);
- 帧间距 frame_space = VTOTAL(图像总行数,1125)。
也就是说,外部源必须严格按照与 Core 参数一致的总长/有效长度来产生行场时序。
像素在 24Bit 数据里怎么排
24Bit 视频数据的像素位分布如下:

接 RGB888 视频源时,按图上的位对应关系连线即可,别把高低位接反了。
Audio Interface:速率必须等于采样率

音频输入数据的速率需要等于音频采样率。例如采样率为 48K,那么 1 秒内必须发送 48000 次音频数据。数据分左右声道各 24Bit(I_audio_left_data / I_audio_right_data),由 I_audio_valid 标记有效。
音频快了慢了都会出问题
音频发送速率不等于 AUDIO_SAMPLE_RATE 设定的采样率,接收端解出的声音就会变速、变调或断续。用板上 I2S 音频源时,务必确认采样率与参数一致。
ACR Interface:帮接收端恢复音频时钟

HDMI 里没有专门的音频时钟线,接收端要从 TMDS 时钟里再生音频时钟,靠的就是发送端周期性插入的音频时钟再生(ACR)辅助数据包,里面有 CTS 和 N 两个值。用法:I_acr_valid 为高时,Core 从 ACR 接口读取 CTS(I_acr_cts[19:0])和 N(I_acr_n[19:0])的值,然后发送 ACR 数据包。更多细节参见 HDMI 1.4b 规范第 7 章。
上板验证:开发环境怎么搭
这套设计在 AP106_V2.0 开发板上验证,官方给出的开发环境如下:

测试工程的玩法:
- 默认分辨率 720P60;
- 通过按键触发读取 EDID 数据,用 CWC(安路 TD 软件的综合/观测工具)观测读回的数据;
- 板内设置了 I2S 接收器,用于接收 I2S 音频数据来测试音频功能。输入音频采样率需要固定为 48K,I2S 信号通过板上的 J8 座子输入(信号位置见图中标识)。
把这套 IP 用到自己设计里的典型流程就是:按目标分辨率配置分辨率参数和时钟 → 接好像素时钟/复位 → 视频源按 Video Interface 时序接上(先开 TPG 验证链路)→ 音频按采样率接上并配好 ACR → 需要时触发 EDID 读取。
建议的调试顺序
- 先用默认 TPG(记得 VIDEO_FORMAT 配 RGB)点亮显示器,验证时钟和物理层链路;
- 看
O_video_locked是否拉高,确认相位匹配;- 再切外部视频源,排查像素位序和行连续性;
- 最后调音频和 EDID。花屏先查时钟频率和分辨率参数是否匹配,再看颜色异常是不是 RGB/YUV 格式设错。
资源消耗与工程文件
Core 的资源占用(表 4-1):
| 器件 | LUT | REG | ERAM |
|---|---|---|---|
| PH1A 系列 | 838 | 1875 | 9 |
| EG4 系列 | 1734 | 1925 | 17 |
示例工程文件信息(表 5-1):
| 参数 | 说明 |
|---|---|
| Reference Design | Yes |
| RTL Language | Verilog |
| Test bench | N/A |
| Test bench Format | N/A |
| Simulation | N/A |
| C | N/A |
| IP Model | N/A |
| Project Platform | Yes |
| TD Soft Version | TD5.6.88061 |
也就是说,官方给的是 Verilog 编写的参考设计 + 工程平台(基于 TD 5.6.88061 版本),没有附带仿真 testbench 和 IP 模型,验证以实际上板为主。
通关标准
- 能独立算出任意分辨率的像素时钟和串行时钟,并说出”为什么是 5 倍”;
- 看着表 2-1 能配出一套 1080p60 的完整参数,并知道 TPG、FORMAT、VIC 之间的联动关系;
- 能按 Video Interface 时序接上外部视频源,并用 O_video_locked 判断链路是否锁定。
自测 1:为什么 1080p60 的像素时钟是 148.5MHz,而不是直接用 1920×1080×60?
因为计算像素时钟必须把消隐区算进去:图像总尺寸是 2200×1125(含行消隐 280 个时钟和场消隐 45 行),所以 F_pixel = 2200×1125×60 = 148.5MHz。若漏掉消隐区,时钟偏低,接收端无法同步。
自测 2:外部视频接上后画面错位/无显示,O_video_locked 一直不拉高,最可能是什么原因?
相位匹配机制要求外部视频时序与 Core 内部 Video Source 对准。应检查:① 外部源的行长度/行间距/帧间距是否与 HTOTAL/HACTIVE/VTOTAL 等参数一致;② 数据是否满足”一行必须连续”的要求(ready 只在行结束 last 后才会拉低再拉高,不支持行内断流);③ 像素时钟是否与参数计算的频率一致。
参考文档:[1] HDMI Specification Version 1.4b;[2] VESA E-EDID Standard 1.4;[3] ANSI/CTA-861-H。原文档为上海安路信息科技股份有限公司 APUG092(v1.0,2024 年 9 月)。