一、基础理论
1.1 HDMI的发展(接口资源)
早期基于 FPGA 的开发板上,实现 HDMI 一般使用的是 HDMI 发送芯片,典型的例如ADV7513、sil9022、CH7301,使用这些芯片实现 HDMI 发送,本质上还是将 FPGA 输出的 24 位像素数据+3 位的控制信号(HSYNC、VSYNC、DE)接入这些芯片,然后由这些芯片完成数据的编码和串行发送。例如DE10_NANO_SOC 开发板上使用 ADV7513 实现的 HDMI发送电路,可以看到,除去用于音频传输的 I2S 相关信号,仅与视频数据传输相关的信号就高达 28 个。这在一些FPGA I/O 相对紧张的应用中,属于较大的浪费了。(浪费I/O口)
通过FPGA编程内部实现HDMI的接口:

1.2 HDMI与DVI的区别与联系
1.3 HDMI与VGA的图像传输数据流转换的区别与联系
- VGA :在使用 VGA 接口的传输方式中,图像数据从图形处理器(也就是常说的显卡芯片)输
出(此时的信号为数字信号),为了能够变成 VGA 接口传输所需的模拟信号,会使用一片数模转换器转换为模拟信号后再输出到 VGA 接口上。然后模拟信号通过 VGA 电缆传输到 LCD 液晶显示屏的 VGA 接口,由于 TFT 像素面板为数字显示屏,每一个像素的颜色是由一个 TFT 驱动器实时的扫描描绘的。TFT 驱动器的输入要求为数字信号,所以 TFT 驱动器和 VGA 接口之间使用了一片模数转换器将 VGA 接口上的模拟信号转换为数字信号后再送给TFT 驱动器使用。
数字信号 ——> 模拟信号 —— (线缆)——> 模拟信号————>数字信号
- HDMI:在使用 HDMI 接口的传输方式中,图像数据从图形处理器(也就是常说的显卡芯片)输
出(此时的信号为数字信号),为了能够将数字信号转换为 HDMI 标准的高速差分信号,会经过一个数据发送器。该数据发送器仅仅是改变了数据的传输方式,将原本的并行数据转换为高速串行数据输出,以符合 HDMI 协议标准,在 HDMI 接口上传输的内容实际还是数字信号。数字信号从显卡的 HDMI 接口经由 HDMI 线缆传输到 LCD 显示器的 HDMI 接口,再由LCD 显示器内的数据接收器将 HDMI 接口上的高速串行数字信号转换为并行数据,提供给TFT 驱动器使用。
数字信号 ——(数据发送器)并转串 ——> (线缆)——> (数据接收器)串转并——>数字信号
1.4 HDMI/DVI数据链路(TMDS编码)
1.4.1 链路框架
- 输入接口层: 输入接口层的信号格式为典型的 RGB 行场同步数字接口,该接口包括数据使能信号 DE(Data Enable)、24 位像素数据(Pixel Data)、6 位的控制数据(包括 HSYNC、VSYNC 和 空信号)和同步时钟信号。
- TMDS发送器:完成对输入接口层的数据和控制信号按照 TMDS 编码方式进行编码,再将编码的数据通过高速串行接口输出,最终将输入接口层的信号编码进 4 个TMDS 链路层中。
- TMDS接收器:将 链路上的高速串行数据接收,解串,TMDS 解码,得到与输入接口层相同的控制信号和数据。
- 输出接口层:将 TMDS 接收器解码得到的数据流和控制信号传递给最终的数据消费者(例如液晶显示器)
1.4.2 TMDS原理与实现(编码并串行化发送)
1.4.2.(a)数据的划分
TMDS 编码包含两个大的内容,传输控制信号的控制段和用来传输图像像素数据的数据段。
一个完整的图像传输TMDS模块包含三个相同的编码和发送模块。每个发模块包含8位的像素数据,对应24位像素数据中单个颜色的8位数据、2个控制信号,这两个控制信号可以分别接行同步、场同步信号,也可以空置接 0。另外还有一个数据有效信号 DE,该信号用来区分控制数据和像素数据。当 DE 信号为高电平的时候,表明当前数据有效,编码器对 8 位的 Data 数据进行编码。当 DE 信号为低电平的时候则对 2 位的控制信号进行编码。
这里,串行发送器使用的时钟信号频率为编码器的5倍。至于为什么是5倍,这是因为串行发送器在发送数据时候是采用双数据速率的方式传输数据的,一个时钟周期可以传输2位信号,所以只需要 5 倍的编码器的时钟即可完成10位数据的及时传输。
1.4.2.(b)TMDS 最小化传输编码原理
1.4.2.(c)TMDS 最小化传输实现原理
1.像素数据周期的编码方式
2.控制周期的编码方式
1.4.2.(d)TMDS 最小化传输编码实现
Verilog代码实现
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Description: TMDS编码
//////////////////////////////////////////////////////////////////////////////////
module encode(
clk ,
rst_n ,
din ,
c0 ,
c1 ,
de ,
dout
);
input clk ;//像素时钟输入
input rst_n ;
input [7:0] din ;//数据输入,需要寄存
input c0 ;
input c1 ;
input de ;//数据使能
output reg [9:0] dout ;//编码之后的10位数据
parameter CTL0 = 10'b1101010100;
parameter CTL1 = 10'b0010101011;
parameter CTL2 = 10'b0101010100;
parameter CTL3 = 10'b1010101011;
reg [3:0] n1d ; //统计输入的 8bit 数据中 1 的个数
reg [7:0] din_q ; //同步寄存输入的 8bit 数据(统计需要一拍时间)
reg [3:0] n1q_m ,
n0q_m ; // 统计 q_m 中 1 和 0 的个数
reg [4:0] cnt ; // 计数器差距统计:统计 1 和 0 是否过量发送,最高位(cnt[4])是符号位
// 流水线对齐(同步寄存器 2 拍)
reg [1:0] de_reg;
reg [1:0] c0_reg;
reg [1:0] c1_reg;
reg [8:0] q_m_reg;
wire [8:0] q_m;
wire decision1;
wire decision2;
wire decision3;
assign decision1 = ((n1d > 'd4)||((n1d == 'd4) && din_q == 1'b0)) ? 1'd1 : 1'd0;
assign decision2 = (cnt == 5'h0) || (n1q_m == n0q_m);
assign decision3 = (~cnt[4] && (n1q_m > n0q_m)) || (cnt[4] && (n0q_m > n1q_m));
// 统计每次输入的 8bit 数据中 1 和 0 的个数 流水线输出,同步寄存输入的 8 bit数据 判断条件为统计数据和输入信号的最低位,保持时序同步,所以对输入信号进行打拍
alwa