????????一种数字音视频接口标准,提供高质量的数字音视频传输,同时支持多通道音频、高分辨率视频和其他数据传输功能。提供更高的数据传输带宽(带宽:1s内传输多少比特数据)
数字传输: HDMI是一种全数字接口,通过数字信号传输音频和视频数据。这有助于防止信号损失,并提供更高的图像和音频质量。
高清晰度视频: HDMI支持高分辨率视频,包括标准高清晰度(HD)和超高清晰度(UHD)分辨率。常见的分辨率包括720p、1080p、4K等。
多通道音频: HDMI支持多通道音频传输,包括立体声和环绕声格式。这允许用户在一个单一的HDMI连接上传输高质量音频。
双向通信: HDMI不仅能够从源设备(如电脑、蓝光播放器)发送信号到显示设备,还能够支持反向通信,使得显示设备可以发送控制信号到源设备。
支持色彩深度和色域: HDMI支持不同的色彩深度(比如8位、10位、12位)和广色域,有助于提供更丰富的颜色和更高的图像质量。
多功能: HDMI接口除了传输音视频信号外,还可以支持一些其他功能,如以太网传输(HDMI with Ethernet)、ARC(Audio Return Channel,音频回传通道)等。
????????HDMI 向下兼容 DVI。DVI (数字视频接口)只能用来传输视频,而不能同时传输音频;
????????与 RGB(红绿蓝)不同,YUV 将颜色信息分成亮度(Y,代表亮度)和色度(U、V,代表色度)两部分。YUV 表示的基本思想是,人眼对亮度变化更为敏感,而对色度变化相对不敏感。因此,通过将颜色信息分离,可以更有效地压缩和传输图像。RGB与YUV的转换如下:
?????????最小化传输差分信号 Transition Minimized Differential Signaling
?????????DVI 和 HDMI 接口协议在物理层均使用 TMDS 标准传输音视频数据。
差分信号传输: TMDS使用差分信号传输方式,使用两个引脚来传输一路信号,利用这两个引脚间的电压差的正负极性和大小来决定传输数据的数值( 0 或 1 )。这种方式可以减小电磁辐射和抗干扰性更强。
过渡最小化编码: TMDS采用过渡最小化编码(Transition Minimized Coding,TMC)技术,以减小信号的过渡时间。这有助于减小电磁干扰,特别是对于高频率的数字信号而言。
数据通道: TMDS协议通常使用三个数据通道,分别用于红色(R)、绿色(G)和蓝色(B)的视频信息传输。此外,还有一个时钟通道用于同步数据。
TMDS时钟: TMDS时钟通道是一个单独的差分信号通道,用于同步数据通道的传输。它的频率通常是数据通道的两倍。
数据帧: 数据在TMDS中以数据帧的形式传输,其中包括视频和音频信息。数据帧由特定的同步和控制信息组成。
带宽和分辨率: TMDS协议的带宽和分辨率直接关联,带宽的增加通常支持更高分辨率的视频传输。不同版本的HDMI和DVI标准支持不同的带宽和分辨率。
? ? ? ? 当VDE被拉高时,传输视频有效像素;当ADE被拉高时,传输音频有效数据。
???????这种算法可以减小传输信号过程的上冲和下冲;而 DC 平衡使信号对传输线的电磁干扰减少;可以用低成本的专用电缆实现长距离、高质量的数字信号传输。
?????????TMDS 连接从逻辑功能上可以划分成两个阶段:编码和并串转换
????????编码阶段算法流程图如下:
每个通道 8-bit 的像素数据都将被转换成 460 个特定 10-bit 字符中的一个。
这个编码机制大致上实现了传输过程中的直流平衡,即一段时间内传输的高电平(数字“ 1” )的个
数大致等于低电平(数字“ 0” )的个数。
每个编码后的 10-bit 字符中状态跳转(“由 1 到 0” 或者“由 0 到 1” )的次数将被限制在五次以内。
每个通道 2-bit 控制信号的状态也要进行编码,编码后分别对应四个不同的 10-bit 控制字
符,分别是 10'b1101010100 , 10'b0010101011 , 10'b0101010100 ,和10'b1010101011 。
每个控制字符都有七次以上的状态跳转。
视频字符和控制字符状态跳转次数的不同将会被用于发送和接收设备的同步。
? ? ? ? 使用HDMI接口,显示彩条
`timescale 1 ps / 1ps
module dvi_encoder (
input clkin, // pixel clock input
input rstin, // async. reset input (active high)
input [7:0] din, // data inputs: expect registered
input c0, // c0 input
input c1, // c1 input
input de, // de input
output reg [9:0] dout // data outputs
);
// Counting number of 1s and 0s for each incoming pixel
// component. Pipe line the result.
// Register Data Input so it matches the pipe lined adder
// output
reg [3:0] n1d; //number of 1s in din
reg [7:0] din_q;
//计算像素数据中“1”的个数
always @ (posedge clkin) begin
n1d <=#1 din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + din[6] + din[7];
din_q <=#1 din;
end
///
// Stage 1: 8 bit -> 9 bit
// Refer to DVI 1.0 Specification, page 29, Figure 3-5
///
wire decision1;
assign decision1 = (n1d > 4'h4) | ((n1d == 4'h4) & (din_q[0] == 1'b0));
wire [8:0] q_m;
assign q_m[0] = din_q[0];
assign q_m[1] = (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]);
assign q_m[2] = (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]);
assign q_m[3] = (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]);
assign q_m[4] = (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]);
assign q_m[5] = (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]);
assign q_m[6] = (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]);
assign q_m[7] = (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]);
assign q_m[8] = (decision1) ? 1'b0 : 1'b1;
/
// Stage 2: 9 bit -> 10 bit
// Refer to DVI 1.0 Specification, page 29, Figure 3-5
/
reg [3:0] n1q_m, n0q_m; // number of 1s and 0s for q_m
always @ (posedge clkin) begin
n1q_m <=#1 q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7];
n0q_m <=#1 4'h8 - (q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]);
end
parameter CTRLTOKEN0 = 10'b1101010100;
parameter CTRLTOKEN1 = 10'b0010101011;
parameter CTRLTOKEN2 = 10'b0101010100;
parameter CTRLTOKEN3 = 10'b1010101011;
reg [4:0] cnt; //disparity counter, MSB is the sign bit
wire decision2, decision3;
assign decision2 = (cnt == 5'h0) | (n1q_m == n0q_m);
/
// [(cnt > 0) and (N1q_m > N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)]
/
assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m));
// pipe line alignment
reg de_q, de_reg;
reg c0_q, c1_q;
reg c0_reg, c1_reg;
reg [8:0] q_m_reg;
always @ (posedge clkin) begin
de_q <=#1 de;
de_reg <=#1 de_q;
c0_q <=#1 c0;
c0_reg <=#1 c0_q;
c1_q <=#1 c1;
c1_reg <=#1 c1_q;
q_m_reg <=#1 q_m;
end
///
// 10-bit out
// disparity counter
///
always @ (posedge clkin or posedge rstin) begin
if(rstin) begin
dout <= 10'h0;
cnt <= 5'h0;
end else begin
if (de_reg) begin
if(decision2) begin
dout[9] <=#1 ~q_m_reg[8];
dout[8] <=#1 q_m_reg[8];
dout[7:0] <=#1 (q_m_reg[8]) ? q_m_reg[7:0] : ~q_m_reg[7:0];
cnt <=#1 (~q_m_reg[8]) ? (cnt + n0q_m - n1q_m) : (cnt + n1q_m - n0q_m);
end else begin
if(decision3) begin
dout[9] <=#1 1'b1;
dout[8] <=#1 q_m_reg[8];
dout[7:0] <=#1 ~q_m_reg[7:0];
cnt <=#1 cnt + {q_m_reg[8], 1'b0} + (n0q_m - n1q_m);
end else begin
dout[9] <=#1 1'b0;
dout[8] <=#1 q_m_reg[8];
dout[7:0] <=#1 q_m_reg[7:0];
cnt <=#1 cnt - {~q_m_reg[8], 1'b0} + (n1q_m - n0q_m);
end
end
end else begin
case ({c1_reg, c0_reg})
2'b00: dout <=#1 CTRLTOKEN0;
2'b01: dout <=#1 CTRLTOKEN1;
2'b10: dout <=#1 CTRLTOKEN2;
default: dout <=#1 CTRLTOKEN3;
endcase
cnt <=#1 5'h0;
end
end
end
endmodule
`timescale 1ns / 1ps
module serializer_10_to_1(
input serial_clk_5x, // 输入串行数据时钟
input [9:0] paralell_data, // 输入并行数据
output serial_data_p, // 输出串行差分数据P
output serial_data_n // 输出串行差分数据N
);
//reg define
reg [2:0] bit_cnt = 0;
reg [4:0] datain_rise_shift = 0;
reg [4:0] datain_fall_shift = 0;
//wire define
wire [4:0] datain_rise;
wire [4:0] datain_fall;
//*****************************************************
//** main code
//*****************************************************
//上升沿发送Bit[8]/Bit[6]/Bit[4]/Bit[2]/Bit[0]
assign datain_rise = {paralell_data[8],paralell_data[6],paralell_data[4],
paralell_data[2],paralell_data[0]};
//下降沿发送Bit[9]/Bit[7]/Bit[5]/Bit[3]/Bit[1]
assign datain_fall = {paralell_data[9],paralell_data[7],paralell_data[5],
paralell_data[3],paralell_data[1]};
//位计数器赋值
always @(posedge serial_clk_5x) begin
if(bit_cnt == 3'd4)
bit_cnt <= 1'b0;
else
bit_cnt <= bit_cnt + 1'b1;
end
//移位赋值,发送并行数据的每一位
always @(posedge serial_clk_5x) begin
if(bit_cnt == 3'd4) begin
datain_rise_shift <= datain_rise;
datain_fall_shift <= datain_fall;
end
else begin
datain_rise_shift <= datain_rise_shift[4:1];
datain_fall_shift <= datain_fall_shift[4:1];
end
end
//例化DDIO_OUT IP核
ddio_out u_ddio_out_p(
.datain_h (datain_rise_shift[0]),
.datain_l (datain_fall_shift[0]),
.outclock (serial_clk_5x),
.dataout (serial_data_p)
);
//例化DDIO_OUT IP核
ddio_out u_ddio_out_n(
.datain_h (~datain_rise_shift[0]),
.datain_l (~datain_fall_shift[0]),
.outclock (serial_clk_5x),
.dataout (serial_data_n)
);
endmodule
//当方块移动到边界时,改变移动方向
always @(posedge pixel_clk ) begin
if (!sys_rst_n) begin
h_direct <= 1'b1; //方块初始水平向右移动
v_direct <= 1'b1; //方块初始竖直向下移动
end
else begin
if(block_x == SIDE_W - 1'b1) //到达左边界时,水平向右
h_direct <= 1'b1;
else //到达右边界时,水平向左
if(block_x == H_DISP - SIDE_W - BLOCK_W)
h_direct <= 1'b0;
else
h_direct <= h_direct;
if(block_y == SIDE_W - 1'b1) //到达上边界时,竖直向下
v_direct <= 1'b1;
else //到达下边界时,竖直向上
if(block_y == V_DISP - SIDE_W - BLOCK_W)
v_direct <= 1'b0;
else
v_direct <= v_direct;
end
end
//根据方块移动方向,改变其纵横坐标
always @(posedge pixel_clk ) begin
if (!sys_rst_n) begin
block_x <= SIDE_W; //方块初始位置横坐标
block_y <= SIDE_W; //方块初始位置纵坐标
end
else if(move_en) begin
if(h_direct)
block_x <= block_x + 1'b1; //方块向右移动
else
block_x <= block_x - 1'b1; //方块向左移动
if(v_direct)
block_y <= block_y + 1'b1; //方块向下移动
else
block_y <= block_y - 1'b1; //方块向上移动
end
else begin
block_x <= block_x;
block_y <= block_y;
end
end
###本文参考正点原子视频,仅用于自己学习复习,如有侵权,请联系删除。