本帖最后由 UT发布 于 2025-3-25 18:58 编辑
TMDS(Transition Minimized Differential Signaling)是一种广泛应用于数字视频传输的编解码技术,尤其在HDMI和DVI接口中占据核心地位。以下从技术定义、编解码原理、应用场景及与同类技术的对比等方面进行详细介绍。
1 TMDS的技术定义与背景TMDS全称为最小化传输差分信号,由Silicon Image公司于1999年提出,旨在通过差分信号传输和智能编码算法减少电磁干扰(EMI),提高数据传输的可靠性和速度。其核心特点包括: 差分信号机制:采用双绞线传输电压相反的信号,接收端通过电压差值判断逻辑状态(0或1),显著提升抗干扰能力。 8B/10B编码:将8位数据转换为10位编码字符,通过减少信号跳变次数(Transition Minimization)和直流平衡(DC Balancing)优化传输效率。 多通道架构:典型应用中包含3个数据通道(传输RGB分量)和1个时钟通道,支持高分辨率视频传输。 2 TMDS编解码原理2.1 编码过程TMDS编码分为两个阶段: 阶段一:跳变最小化 输入8位像素数据后,通过异或(XOR)或同或(XNOR)运算生成9位中间数据,选择跳变次数更少的操作方式(第9位标记操作类型)。 例如:若前8位通过同或运算生成,则第9位为0;若通过异或运算生成,则为1。 阶段二:直流平衡 统计中间数据中0和1的数量差,若0较多则反转前8位并标记第10位为1,反之标记为0,以确保整体0-1数量接近平衡。 直流平衡的作用:避免因长时间传输单一电平导致交流耦合电容充放电失衡,从而引发信号失真。 2.2.控制信号与同步控制数据编码:在视频消隐期(非有效像素传输期),TMDS传输控制信号(如行场同步HSync/VSync),其编码后的10位字符跳变次数≥7次,便于接收端识别同步边界。 时钟恢复:接收端通过TMDS时钟通道锁定发送端频率,并利用数据流中的跳变特性恢复位同步。 2.3 解码过程接收端通过以下步骤还原原始数据: 字符边界同步:利用控制数据的高跳变特性定位10位字符的起始位置。 逆操作处理:根据第9位和第10位的标记,反向执行异或/同或运算及电平反转操作,恢复8位像素数据。 3 TMDS的应用场景1.HDMI/DVI接口:作为物理层编码标准,支持最高225MHz时钟频率,可传输4K@60Hz等高分辨率视频。 2.FPGA与显示驱动:FPGA通过集成TMDS编码器实现视频输出,常用于数字广告牌、医疗显示器等场景。 3.双链路扩展:当单通道带宽不足时,采用双TMDS链路(6个数据通道)提升传输能力,支持更高刷新率或色深。 4.车载与工业显示:在电润湿电子屏等特殊显示技术中,TMDS用于高可靠性的实时视频传输。 4 TMDS编解码在HDMI传输中的应用
 HDMI通过四组差分通道(3个数据通道+1个时钟通道)实现并行传输: 1、数据通道分配 通道0-2:分别传输红(R)、绿(G)、蓝(B)分量或YCrCb编码的像素数据。 音频与辅助数据:在数据岛周期(Data Island Period)中,音频包通过绿、红通道传输,使用TERC4编码。 2、时钟通道 传输与像素时钟同步的参考信号(如148.5MHz对应1080p@60Hz),接收端依此恢复数据时序。 3、传输周期划分 视频数据周期:有效像素传输阶段,编码RGB/YCrCB数据。 控制周期:消隐期内传输行场同步(HSync/VSync)等控制信号,编码后跳变次数≥7次以便同步识别。 数据岛周期:传输音频、元数据(如HDR参数)及辅助包,采用TERC4编码确保容错。 上面是完整的TMDS编码在HDMI通道传输的通道架构与数据传输模式。本讲我们主要解决的是TMDS编解码的问题,暂时先不考虑音频的问题,所以我们先不考虑数据岛周期内容。
4.1TMDS编码4.1.1编码原理概述 上图来自于HDMI协议中的TMDS编码详细步骤,通过分析该流程图我们发现,TMDS编码通过两步编码实现: 1、数据压缩:将8bit像素转换为9bit中间码(q_m) 2、直流平衡:动态调整编码方式,确保传输链路的0/1均衡 4.1.2详细编码流程步骤1:输入预处理 接收8bit像素数据D[7:0]与控制信号 {C1,C0} 检测使能信号DE(高电平表示数据传输周期) 步骤2:编码方式决策
- // 计算数据中1的个数(N1)
- wire [3:0] N1 = D[7] + D[6] + D[5] + D[4] + D[3] + D[2] + D[1] + D[0];
-
- // 选择异或(XOR)/同或(XNOR)编码
- assign use_xnor = (N1 > 4) || (N1 ==4 && D[0]==0);
复制代码
步骤3:生成中间码q_m[8:0] - always @(*) begin
- q_m[0] = D[0];
- for(int i=1; i<8; i++)
- q_m[i] = use_xnor ? ~(q_m[i-1] ^ D[i]) : q_m[i-1] ^ D[i];
- q_m[8] = ~use_xnor; // 编码方式标识位
- end
复制代码
步骤4:直流平衡处理 - // 计算当前偏差
- wire signed [4:0] bias = (q_m[8] ? (N1*2 - 8) : (8 - N1*2));
-
- // 动态平衡决策
- if ((cnt_prev + bias) > 0 || cnt_prev == 0) begin
- q_out = {~q_m[8], ~q_m[7:0], 1'b1}; // 取反并标记终止符
- cnt_next = cnt_prev + (8 - 2*N1); // 更新偏差计数器
- end else {
- q_out = {q_m[8], q_m[7:0], 1'b0}; // 保持原数据
- cnt_next = cnt_prev + (2*N1 - 8);
- }
复制代码
步骤5:控制信号编码(DE=0时) - case({C1,C0})
- 2'b00: q_out = 10'b1101010100; // Video Blank
- 2'b01: q_out = 10'b0010101011; // H-Sync
- 2'b10: q_out = 10'b0101010100; // V-Sync
- 2'b11: q_out = 10'b1010101011; // Sync复合
- endcase
复制代码
4.2 TMDS解码TMDS解码协议如下所示,相比较编码,解码就简单很多,仅仅根据发送过来的数据的D[9]和D[8]位数据是0还是1进行不同的判断,对应处理即可:
4.2.1 TMDSDecoder10t8.v根据解码协议,解码代码如下 注:此时我们并不考虑音频传输,所以不考虑数据的部分数据编码内容
- module TMDSDecoder10t8 (
- input wire [9:0] I_raw_date, // 输入的10位原始TMDS数据流
- input wire pclk, // 像素时钟信号输入
- input wire rest_n, // 复位信号,低电平有效
- output wire [7:0] O_hdmi_date, // 输出解码后的8位HDMI数据
- output wire O_hs, // 输出水平同步信号
- output wire O_vs, // 输出垂直同步信号
- output wire O_de // 输出数据使能信号
- );
- wire [9:0] I_hdmi_date; // 转换后用于内部处理的10位HDMI数据
- wire [8:0] raw_data; // 解码过程中使用的临时变量
-
- // 将I_raw_date通过convert函数转换为I_hdmi_date,主要用于大小端转换
- assign I_hdmi_date = convert(I_raw_date);
-
- // 当I_hdmi_date为特定值时(表示控制周期),O_de设为0;否则为1,表示数据周期
- assign O_de = I_hdmi_date == 10'b1101010100 || I_hdmi_date == 10'b0010101011 || I_hdmi_date == 10'b0101010100 || I_hdmi_date == 10'b1010101011 ? 0 : 1;
-
- // 根据O_de和I_hdmi_date的状态生成水平同步信号O_hs
- assign O_hs = O_de ? 0 : I_hdmi_date == 10'b0010101011 || I_hdmi_date == 10'b1010101011 ? 1 : 0;
-
- // 根据O_de和I_hdmi_date的状态生成垂直同步信号O_vs
- assign O_vs = O_de ? 0 : I_hdmi_date == 10'b0101010100 || I_hdmi_date == 10'b1010101011 ? 1 : 0;
-
- // 当处于数据周期(O_de非0)时,根据I_hdmi_date[9]的值对raw_data进行相应处理
- assign raw_data = O_de == 0 ? 0 : I_hdmi_date[9] ? {I_hdmi_date[8], ~I_hdmi_date[7:0]} : I_hdmi_date[8:0];
-
- // 根据O_de和raw_data生成最终输出的8位HDMI数据
- assign O_hdmi_date[0] = O_de == 0 ? 0 : raw_data[0];
- assign O_hdmi_date[1] = O_de == 0 ? 0 : raw_data[8] ? raw_data[1] ^ raw_data[0] : raw_data[1] ~^ raw_data[0];
- assign O_hdmi_date[2] = O_de == 0 ? 0 : raw_data[8] ? raw_data[2] ^ raw_data[1] : raw_data[2] ~^ raw_data[1];
- assign O_hdmi_date[3] = O_de == 0 ? 0 : raw_data[8] ? raw_data[3] ^ raw_data[2] : raw_data[3] ~^ raw_data[2];
- assign O_hdmi_date[4] = O_de == 0 ? 0 : raw_data[8] ? raw_data[4] ^ raw_data[3] : raw_data[4] ~^ raw_data[3];
- assign O_hdmi_date[5] = O_de == 0 ? 0 : raw_data[8] ? raw_data[5] ^ raw_data[4] : raw_data[5] ~^ raw_data[4];
- assign O_hdmi_date[6] = O_de == 0 ? 0 : raw_data[8] ? raw_data[6] ^ raw_data[5] : raw_data[6] ~^ raw_data[5];
- assign O_hdmi_date[7] = O_de == 0 ? 0 : raw_data[8] ? raw_data[7] ^ raw_data[6] : raw_data[7] ~^ raw_data[6];
-
- // 定义一个函数用于实现大小端转换
- function [9:0] convert;
- input [9:0] data_in;
- integer i;
- for (i = 0; i < 10; i = i + 1) begin : converse
- // 对输入的数据进行位反转操作
- convert[i] = data_in[9-i];
- end
- endfunction
-
- endmodule
复制代码
4.2.2TMDSDecoder10t8.v的RTL仿真TMDSDecoder作为TMDS解码模块,主要的功能是将10位TMDS编码数据恢复成8位的RGB数据,同时恢复出对应的RGB时序。如下图所示:
|