720p HDMI 透传工程 — 涵盖 TMDS 编解码、LVDS 差分 IO、SERDES 原语、相位对齐算法、跨时钟域设计
一、背景知识:HDMI 与 TMDS
1.1 HDMI 物理层
HDMI 使用 TMDS(Transition Minimized Differential Signaling) 串行差分传输,包含:
| 通道 | 内容 | 本工程速率(720p) |
|---|---|---|
| DATA[0](蓝) | B[7:0] + HS + VS(消隐期) | 742.5 Mbps |
| DATA[1](绿) | G[7:0] | 742.5 Mbps |
| DATA[2](红) | R[7:0] | 742.5 Mbps |
| CLK | 像素时钟(74.25MHz编码为固定码 1111100000) |
74.25 MHz |
1.2 TMDS 编码原理(8b10b,非标准)
TMDS 不是标准 8b10b,而是 DVI/HDMI 专用编码方案:
原始 8bit 像素数据
↓ 第一步:异或/同或(选择 1 个数少的结果),得到 9bit
↓ 第二步:DC 平衡(记录累计极性,决定是否取反),得到 10bit
10bit 中:
bit[9] = 是否取反
bit[8] = 异或/同或选择位
bit[7:0]= 编码后数据
消隐期(HS/VS/DE=0):发送固定控制字(CTRL TOKEN)
CTRLTOKEN0 = 10'b1101010100 (HS=0, VS=0)
CTRLTOKEN1 = 10'b0010101011 (HS=1, VS=0)
CTRLTOKEN2 = 10'b0101010100 (HS=0, VS=1)
CTRLTOKEN3 = 10'b1010101011 (HS=1, VS=1)
要点:控制字(CTRL TOKEN)的特殊编码使其在统计上极不可能出现在正常像素数据中,接收端专门检测这些固定码型来进行字对齐和相位校准。
1.3 TMDS 接收时序关系
串行数据 ─────┐
├──→ ISERDES (1:10解串) ──→ 10bit 并行 ──→ TMDS解码 ──→ 8bit 像素
位时钟 │
(742.5MHz) ────┘
↑
pll_5x × 5
↑
CLKIN (74.25MHz,来自TMDS CLK通道)
二、工程整体架构
A板(发送)
video_pll(50→74.25MHz)
↓ pix_clk
sync_vg → pattern_vg → rgb2tmds → LVDS TX → [HDMI线缆]
↑ ↑
视频时序 tmds_encoder + outputserdes
B板(接收透传)
[HDMI线缆] → LVDS RX → tmds2rgb → [rx_vid_de/hs/vs/data]
↓
rgb2tmds → LVDS TX → [显示器]
三、TX 路径详解
3.1 视频时序生成(sync_vg)
标准视频时序由水平/垂直计数器产生,720p@60Hz 参数:
H_TOTAL=1650 H_ACT=1280 H_SYNC=40 H_BP=220 H_FP=110
V_TOTAL=750 V_ACT=720 V_SYNC=5 V_BP=20 V_FP=5
像素时钟=74.25MHz
输出:hs(水平同步)、vs(垂直同步)、de(数据有效)、act_x/y(当前像素坐标)
3.2 图案生成(pattern_vg)
根据 act_x 和 act_y 坐标生成 RGB 测试图案(彩条/渐变)。
3.3 TMDS 编码(tmds_encoder,每通道一个)
// 消隐期:输出控制字
// 有效期:8bit RGB → TMDS 8b10b 编码 → 10bit
// 蓝色通道(i=0)特殊:pc0=HS,pc1=VS 编入控制字中
3.4 串行化(outputserdes)
使用 MASTER+SLAVE 两片 GTP_OSERDES_E2 级联实现 10:1 DDR 并串转换:
10bit 并行(pixelclk=74.25MHz)
↓ GTP_OSERDES_E2 (DDR10TO1)
1bit 串行(serialclk=371.25MHz,DDR等效742.5Mbps)
↓ GTP_OUTBUFDS
TMDS 差分输出 (LVDS25,VCCIO=2.5V)
关键:Slave 提供 bit[9:8],Master 提供 bit[7:0],通过 cascade 连接。CLK 通道固定发送
10'b1111100000(无需编码)。
四、RX 路径详解(核心难点)
4.1 时钟恢复(tmds_input_clk_serdes)
HDMI CLK 差分输入
↓ GTP_INBUFGDS(差分→单端)
↓ GTP_CLKBUFG(进全局时钟网络)
↓ pll_5x(74.25MHz → 74.25MHz + 371.25MHz)
↓ ↓
tmds_clk_1x tmds_clk_5x
(像素时钟) (串行采样时钟)
为什么需要 pll_5x:接收到的 74.25MHz TMDS 时钟只是像素级频率,ISERDES 需要 5 倍的 371.25MHz 来对 742.5Mbps 的数据进行 DDR 采样(371.25×2=742.5Msps)。
4.2 解串与延迟调整(tmds_input_data_serdes)
差分数据输入
↓ GTP_INBUFDS(差分→单端)
↓ GTP_IODELAY_E2(输入延迟,5ps/step,动态可调)
↓ GTP_ISERDES_E2 MASTER(捕获 bit[7:0])
GTP_ISERDES_E2 SLAVE (捕获 bit[9:8])
↓ 数据位序翻转(GTP_OSERDES 输出是反序的)
↓ 10bit 并行数据
IDELAY 的作用:精细调整数据采样时刻,找到信号眼图中心。步长 5ps,范围 0-247 步(0-1235ps)。
BITSLIP 的作用:当 10bit 字边界对齐错误时,移动一个比特位,重新建立字对齐。最多需要 10 次 BITSLIP 遍历所有可能对齐。
4.3 相位对齐状态机(phasealign)—— 最复杂的模块
核心思路:利用 TMDS 消隐期发送的固定 CTRL TOKEN,自动搜索正确的 IDELAY 步数和 BITSLIP 次数。
┌─────────────────────────────────────────────────────┐
│ 状态机执行流程 │
│ │
│ ST_RESET → ST_IDLE │
│ │ │
│ 在这里等待 CTRL TOKEN 或 超时(50μs) │
│ │ │ │
│ token出现 超时,信号不对 │
│ ↓ ↓ │
│ ST_TOKEN ST_JITTER_ZONE │
│ │ ↓ │
│ 稳定16个 pix_clk ST_INC_DELAY │
│ ↓ (delay_cnt+1) │
│ ST_ALIGN_PASS ST_DELAY_OVERTEST │
│ (锁定完成✅) │ │
│ 若delay<64: → ST_IDLE 重试 │
│ 若delay=64: → ST_ALIGN_ERROR│
│ ↓ │
│ 触发 BITSLIP │
│ 复位重试最多10次 │
└─────────────────────────────────────────────────────┘
两个关键时钟域的协作:
-
pix_clk(74.25MHz):运行 FSM 主体,检测 TOKEN,计数 BITSLIP 延迟 -
clk_200m(200MHz):运行超时计数器(200MHz 更稳定,且时钟频率固定,pix_clk 失锁时不稳定) -
跨时钟域:
timeout_rst_pix → 200m(2-flop同步),timeout_max_200m → pix(2-flop同步)
IDELAY 搜索参数(优化后):
Findeye_MAXDelay = 64 // 64步×5ps = 320ps,>pll_5x最大偏移±270ps
Timeout_total_cnt= 10000 // @200MHz=50μs,覆盖完整H-blank(4.99μs/行)
4.4 通道对齐(channel_align)
三路通道(R/G/B)的 phasealign 完成时刻可能不同,传播延迟也有差异。需要 FIFO 补偿通道间延迟差:
// 原理:
// 1. 各自 phasealign 完成(all_pligned)后,各通道数据写入 FIFO
// 2. 等待三通道都ready,统一开始读FIFO
// 3. 读指针对齐保证三路数据时间对齐
// GTP_FIFO18K_E1 原语,因位宽不能为10,用了 channel_fifo_10to10(自定义FIFO)
4.5 TMDS 解码(decoder)
// 消隐期:识别CTRL TOKEN → 输出 HS/VS,pvde=0
// 有效期:反 TMDS 解码
// bit[7:0] = (bit[9]=1) ? ~data[7:0] : data[7:0] // 反转还原
// 反差分解码:(bit[8]=1)? XOR还原 : XNOR还原 // 差分解码
// 输出:8bit 像素数据 + pvde + hs + vs
五、时钟架构总览
sys_clk (50MHz)
├── pll_sys → clk_200m (200MHz)
│ 用途:① phasealign 超时计时 ② 热插拔恢复计数器
│
└── video_pll → pix_clk (74.25MHz) + pix_clk_5x (371.25MHz)
[仅A板使用,B板已移除]
HDMI RX CLK 输入 (74.25MHz)
└── pll_5x → tmds_clk_1x (74.25MHz) + tmds_clk_5x (371.25MHz)
用途:① ISERDES 采样时钟
② B板 TX 编码器时钟(与RX同源,无需CDC)
③ LED 计数器时钟(指示RX锁定状态)
六、跨时钟域(CDC)设计要点
6.1 单信号跨域:2-flip同步器
// 将 clk_200m 域的信号同步到 rx_pix_clk 域
reg [1:0] sync_ff;
always @(posedge rx_pix_clk or negedge async_rst) begin
if (async_rst) sync_ff < 2'b00;
else sync_ff < {sync_ff[0], signal_200m};
end
wire signal_pix sync_ff[1];
注意:若目标时钟(
rx_pix_clk)可能停振(如 PLL 失锁),必须将导致时钟停止的信号加入 async reset sensitivity list,否则同步器会冻结,无法正确复位。
6.2 本工程中的 CDC 场景
| 信号 | 源域 | 目标域 | 方式 |
|---|---|---|---|
timeout_max |
clk_200m |
pix_clk |
2-flop 同步 |
timeout_rst |
pix_clk |
clk_200m |
2-flop 同步 |
rx_recovery_done |
clk_200m |
rx_pix_clk |
2-flop + async rst(含 !rx_tmds_locked) |
七、关键 FPGA 原语说明
| 原语 | 作用 | 本工程参数 |
|---|---|---|
GTP_INBUFGDS |
差分输入→全局时钟缓冲 | CLK通道 |
GTP_INBUFDS |
差分输入→单端 | DATA通道,无时钟网络 |
GTP_CLKBUFG |
全局时钟缓冲 | CLK通道,进全局时钟网 |
GTP_IODELAY_E2 |
输入延迟,5ps/step | DELAY_STEP_SEL="PARAMETER",动态控制 |
GTP_ISERDES_E2 |
串并转换,1:10,DDR | MASTER+SLAVE级联,BITSLIP使能 |
GTP_OSERDES_E2 |
并串转换,10:1,DDR | MASTER+SLAVE级联,DDR10TO1模式 |
GTP_OUTBUFDS |
单端→差分输出 | TMDS模式,LVDS25 |
| PLL原语 | 时钟频率/相位合成 | video_pll/pll_sys/pll_5x |
八、IO 约束要点
使用紫光同创 PDS 工具的 .fdc 约束文件:
# 创建时钟约束
create_clock -name {sys_clk} [get_ports {sys_clk}] -period {20.000}
# IO 属性约束
define_attribute {p:tmds_data_p[2]} {PAP_IO_STANDARD} {LVDS25}
define_attribute {p:tmds_data_p[2]} {PAP_IO_LOC} {K19}
define_attribute {p:tmds_data_p[2]} {PAP_IO_VCCIO} {2.5}
| LVDS TX 引脚 | IO标准 | VCCIO |
|---|---|---|
tmds_data/clk _p/n |
LVDS25 |
2.5V |
| LVDS RX 引脚 | IO标准 | 额外设置 |
|---|---|---|
i_rx_tmds_data/clk_p/n |
LVDS25 |
BUS_KEEPER=NONE,DIFF_IN_TERM_MODE=OFF |
九、调试手段
9.1 在线逻辑分析仪(PAP_MARK_DEBUG)
紫光同创 PDS 支持类似 Vivado ILA 的在线调试,在需要观测的信号上添加属性:
wire [9:0] data_10bit_ori; /* synthesis PAP_MARK_DEBUG="true" */
综合后在 PDS 中配置抓取条件,可在 FPGA 运行时捕获内部信号波形,对 phasealign 调试非常有用。
9.2 LED 状态指示
// LED 由 RX 恢复时钟(74.25MHz)驱动,闪烁频率约 0.7Hz
assign led pwm_cnt[29:25];
// LED 均匀闪烁 → RX 时钟正常
// LED 全亮/全灭 → pll_5x 未锁定或 clk 停振
十、设计要点与学习总结
| 序号 | 要点 |
|---|---|
| 1 | TMDS 编码是 DVI/HDMI 专用,不是标准 8b10b,消隐期发固定 CTRL TOKEN |
| 2 | RX 时钟恢复=先用 INBUFGDS 接收差分时钟,再用 pll_5x 生成 5×采样时钟 |
| 3 | ISERDES 解串后数据有位反转,需用 generate 语句对 10bit 做逐位翻转 |
| 4 | IDELAY 调细采样点(5ps级),BITSLIP 调字对齐(1bit级),两者配合完成对齐 |
| 5 | phasealign 用 CTRL TOKEN 作为”锚点”检测对齐,需保证每个延迟点的等待时间>一个消隐区间 |
| 6 | B板透传:TX 时钟必须与 RX 恢复时钟同源,避免引入跨时钟域问题 |
| 7 | 热插拔复位:包含 pll_5x 失锁的复位信号,必须进入 async reset sensitivity list,防止时钟停振后寄存器冻结 |
| 8 | RX 恢复计数器应使用始终稳定的时钟(200MHz),不应用可能停振的 rx_pix_clk |
| 9 | 三通道独立对齐后,需 FIFO 做通道间时延补偿,再统一释放数据 |
| 10 |


![表情[baoquan]-逻辑矩阵技术社区](https://szlogicmatrix.com/wp-content/themes/zibll/img/smilies/baoquan.gif)
![表情[qiang]-逻辑矩阵技术社区](https://szlogicmatrix.com/wp-content/themes/zibll/img/smilies/qiang.gif)
