HDMI连接线采用数字信号传输,能够提供高质量的图像和声音效果。与传统的模拟连接方式不同,HDMI数字连接可以保证音视频信号不受干扰和质量损失,因此在现代多媒体设备之间的连接和传输中被广泛使用。HDMI连接还支持多种分辨率和音频格式,以适应不同的设备和需求。
以下是HDMI相对于VGA的优点:
-
高清传输:HDMI支持高清视频传输,包括1080p和4K分辨率,而VGA最高只支持720p分辨率。
-
音频传输:HDMI不仅可以传输视频信号,还可以传输音频信号,而VGA只能传输视频信号。
-
数字信号传输:HDMI是数字信号传输,不需要进行数字转换,可以避免信号的失真和干扰,从而提高视频和音频质量。而VGA是模拟信号传输,需要进行模拟转换,信号质量容易受到干扰和失真的影响。
-
多功能接口:HDMI接口还可以支持其他多种功能,如以太网、3D视频、ARC(音频返回通道)等。
除了以上优点,HDMI相对VGA还利用了其他技术,包括:
-
TMDS(Transition Minimized Differential Signaling)差分传输技术:HDMI使用TMDS技术传输数字信号,可以有效地减少电磁干扰和信号衰减,提高信号传输的质量和稳定性。
-
HDCP(High-bandwidth Digital Content Protection)高清数字版权保护技术:HDMI使用HDCP技术对数字内容进行保护,防止未经授权的复制和分发。
其中
TMDS差分传动技术是一种传输数据的方式,它使用一对差分信号来传输数字信号。这对信号被称为正向传输线和反向传输线,它们的电压差用于表示数字数据,也就是采用 2 根线来传输信号,一根线上传输原来的信号,另一根线上传输与原来信号相反的信号。接收端通过让一根线上的信号减去另一根线上的信号的方式来屏蔽电磁干扰,从而得到正确的信号。这种差分信号传输技术可以有效地减少电磁干扰和信号衰减,从而提高信号传输的质量和稳定性。
module TOP_HDMI(
input wire clk_sys ,
input wire rst_n_sys ,
output wire r_hdmi_n ,
output wire g_hdmi_n ,
output wire b_hdmi_n ,
output wire r_hdmi_p ,
output wire g_hdmi_p ,
output wire b_hdmi_p ,
output wire clk_n ,
output wire clk_p
);
wire hsync ;
wire vsync ;
wire [9:0]pix_x,pix_y ;
wire [15:0]pix_data ;
wire clk_vga ;
wire clk_E ;
wire [7:0]r_hdmi ;
wire [7:0]g_hdmi ;
wire [7:0]b_hdmi ;
wire rgb_vaild ;
wire [15:0]rgb ;
assign r_hdmi={rgb[15:11],3'b000} ;
assign g_hdmi={rgb[10:5],2'b00} ;
assign b_hdmi={rgb[4:0],3'b000} ;
vga_pic vga_pic1(
.clk_vga (clk_vga),
.rst_n_sys (rst_n_sys),
.pix_x (pix_x),
.pix_y (pix_y),
.pix_data (pix_data)
);
vga_ctrl vga_c(
.clk_vga (clk_vga) ,
.rst_n_sys (rst_n_sys) ,
.pix_data (pix_data),
.rgb (rgb),
.pix_x (pix_x) ,
.pix_y (pix_y) ,
.hsync (hsync) ,
.vsync (vsync) ,
.rgb_vaild (rgb_vaild)
);
clk_gen_t gen_t_inst (
.areset ( ~rst_n_sys ) ,
.inclk0 ( clk_sys ) ,
.c0 ( clk_vga ) ,
.c1 ( clk_E )
);
hdmi_ctrl hdmi_c(
.clk_vga (clk_vga ) ,
.rst_n_sys (rst_n_sys ) ,
.r_hdmi (r_hdmi ) ,
.g_hdmi (g_hdmi ) ,
.b_hdmi (b_hdmi ) ,
.hsync (hsync ) ,
.vsync (vsync ) ,
.rgb_vaild (rgb_vaild ) ,
.clk_E (clk_E ) ,
.r_hdmi_n (r_hdmi_n ) ,
.g_hdmi_n (g_hdmi_n ) ,
.b_hdmi_n (b_hdmi_n ) ,
.r_hdmi_p (r_hdmi_p ) ,
.g_hdmi_p (g_hdmi_p ) ,
.b_hdmi_p (b_hdmi_p ) ,
.clk_n (clk_n ) ,
.clk_p (clk_p )
);
endmodule
module hdmi_ctrl(
input wire clk_vga ,
input wire rst_n_sys ,
input wire [7:0]r_hdmi ,
input wire [7:0]g_hdmi ,
input wire [7:0]b_hdmi ,
input wire hsync ,
input wire vsync ,
input wire rgb_vaild ,
input wire clk_E ,
output wire r_hdmi_n ,
output wire g_hdmi_n ,
output wire b_hdmi_n ,
output wire r_hdmi_p ,
output wire g_hdmi_p ,
output wire b_hdmi_p ,
output wire clk_n ,
output wire clk_p
);
wire [29:0]data_out ;
//1
par_to_ser p_red(
.data_out (data_out[9:0]),
.clk_E (clk_E) ,
.ser_n (r_hdmi_n) ,
.ser_p (r_hdmi_p)
);
encode e_red(
.clk_vga (clk_vga) ,
.rst_n_sys (rst_n_sys) ,
.data_in (r_hdmi) ,
.hsync (hsync) ,
.vsync (vsync) ,
.rgb_vaild (rgb_vaild) ,
.data_out (data_out[9:0])
);
//2
par_to_ser p_green(
.data_out (data_out[19:10]) ,
.clk_E (clk_E) ,
.ser_n (g_hdmi_n) ,
.ser_p (g_hdmi_p)
);
encode e_green(
.clk_vga (clk_vga) ,
.rst_n_sys (rst_n_sys) ,
.data_in (g_hdmi) ,
.hsync (hsync) ,
.vsync (vsync) ,
.rgb_vaild (rgb_vaild) ,
.data_out (data_out[19:10])
);
//3
par_to_ser p_blue(
.data_out (data_out[29:20]) ,
.clk_E (clk_E) ,
.ser_n (b_hdmi_n) ,
.ser_p (b_hdmi_p)
);
encode e_blue(
.clk_vga (clk_vga) ,
.rst_n_sys (rst_n_sys) ,
.data_in (b_hdmi) ,
.hsync (hsync) ,
.vsync (vsync) ,
.rgb_vaild (rgb_vaild) ,
.data_out (data_out[29:20])
);
par_to_ser p_clk(
.data_out (10'b11111_00000) ,
.clk_E (clk_E) ,
.ser_n (clk_n) ,
.ser_p (clk_p)
);
endmodule
编码模块:
编码模块规则:
编码模块就是为了完成 VGA 图像数据 8b 转 10b 的编码,使用编码模块可解决图像数据的编码问题。
module encode(
input wire clk_vga ,
input wire rst_n_sys ,
input wire [7:0]data_in,
input wire hsync ,
input wire vsync ,
input wire rgb_vaild ,
output reg [9:0]data_out
);
reg [4:0]q_m_n_zore,q_m_n_one,reg_q_m_n_one,reg_q_m_n_zore ;
reg [8:0]q_m,reg_q_m ;
reg reg_de_one,reg_de_two ;
reg [4:0]cnt ;
reg c0,c1,reg_c0,reg_c1 ;
wire condition_one,condition_two,condition_three,condition_four,condition_five;
wire [4:0]sum_one ;
assign sum_one=data_in[7]+data_in[6]+data_in[5]+data_in[4]+data_in[3]+data_in[2]+data_in[1]+data_in[0];
always@(posedge clk_vga or negedge rst_n_sys)
if(~rst_n_sys)begin
q_m_n_one <=5'd0 ;
q_m_n_zore <=5'd0 ;
end
else
begin
q_m_n_one <=sum_one ;
q_m_n_zore <=5'd8-sum_one ;
end
assign condition_one=(q_m_n_one>5'd4 || (q_m_n_one==5'd4 && data_in[0]==0))?1'b1:1'd0;
always@(posedge clk_vga or negedge rst_n_sys)
if(~rst_n_sys)
q_m<=9'd0 ;
else if(condition_one==1'b1)begin
q_m[8]<= 1'b1 ;
q_m[7]<= q_m[6]^~data_in[7];
q_m[6]<= q_m[5]^~data_in[6];
q_m[5]<= q_m[4]^~data_in[5];
q_m[4]<= q_m[3]^~data_in[4];
q_m[3]<= q_m[4]^~data_in[5];
q_m[4]<= q_m[3]^~data_in[4];
q_m[3]<= q_m[2]^~data_in[3];
q_m[2]<= q_m[1]^~data_in[2];
q_m[1]<= q_m[0]^~data_in[1];
q_m[0]<= data_in[0] ;
end
else begin
q_m[8]<= 1'b0 ;
q_m[7]<= q_m[6]^data_in[7] ;
q_m[6]<= q_m[5]^data_in[6] ;
q_m[5]<= q_m[4]^data_in[5] ;
q_m[4]<= q_m[3]^data_in[4] ;
q_m[3]<= q_m[4]^data_in[5] ;
q_m[4]<= q_m[3]^data_in[4] ;
q_m[3]<= q_m[2]^data_in[3] ;
q_m[2]<= q_m[1]^data_in[2] ;
q_m[1]<= q_m[0]^data_in[1] ;
q_m[0]<= data_in[0] ;
end
assign condition_two =reg_de_two ;
assign condition_three=((cnt>5'd0 && reg_q_m_n_one>reg_q_m_n_zore)||(cnt<5'd0 && reg_q_m_n_zore>q_m_n_one))?1'b1:1'b0 ;
assign condition_four =((cnt>=5'd0 && reg_q_m_n_one>reg_q_m_n_zore) ||(cnt<0&®_q_m_n_zore>reg_q_m_n_one))?1'b1:1'b0 ;
assign condition_five =~reg_q_m[8] ;
always@(posedge clk_vga or negedge rst_n_sys)
if(~rst_n_sys)begin
reg_de_one <=1'b0;
reg_de_two <=1'b0;
reg_q_m_n_one <=1'b0;
reg_q_m_n_zore <=1'b0;
c0 <=1'b0;
reg_c0 <=1'b0;
c1 <=1'b0;
reg_c1 <=1'b0;
reg_q_m <=1'b0;
end
else
begin
reg_de_one <=rgb_vaild ;
reg_de_two <=reg_de_one ;
reg_q_m_n_one <=q_m_n_one ;
reg_q_m_n_zore <=q_m_n_zore ;
c0 <=hsync ;
reg_c0 <=c0 ;
c1 <=vsync ;
reg_c1 <=c1 ;
reg_q_m <=q_m ;
end
always@(posedge clk_vga or negedge rst_n_sys)
if(~rst_n_sys)begin
cnt<=1'b0 ;
data_out<=10'd0 ;
end
else if(condition_two==1'b0)begin
cnt<=1'b0 ;
case({reg_c1,reg_c0})
2'b00:data_out[9:0]<=10'b1101_010_100;
2'b01:data_out[9:0]<=10'b0010_101_011;
2'b10:data_out[9:0]<=10'b0101_010_100;
2'b11:data_out[9:0]<=10'b1010_101_011;
default:data_out<=10'd99 ;
endcase
end
else
if (condition_three==1'b0)
if(condition_four==1'b0)begin
data_out<={1'b0,reg_q_m[8],reg_q_m[7:0]} ;
cnt<=cnt-2'd2*(~reg_q_m[8])+reg_q_m_n_one-reg_q_m_n_zore ;
end
else begin
data_out<={1'b1,reg_q_m[8],(~reg_q_m[7:0])} ;
cnt<=cnt+2'd2*reg_q_m[8]-reg_q_m_n_one+reg_q_m_n_zore ;
end
else begin
data_out<={~reg_q_m[8],reg_q_m[8],(reg_q_m[8]?reg_q_m[7:0]:~reg_q_m[7:0])};
if(condition_five)
cnt<=cnt+reg_q_m_n_zore-reg_q_m_n_one;
else
cnt<=cnt-reg_q_m_n_zore+reg_q_m_n_one;
end
endmodule
并行转串行模块的主要功能就是实现并行串行转换、单端信号转差分信号、单沿采样转双沿采样。
module par_to_ser(
input wire [9:0]data_out ,
input wire clk_E ,
output wire ser_n ,
output wire ser_p
);
wire [4:0]fall_data,rise_data ;
reg [4:0]fall_data_s,rise_data_s ;
reg [2:0]cnt=3'd0 ;
assign fall_data={data_out[9],data_out[7],data_out[5],data_out[3],data_out[1]};
assign rise_data={data_out[8],data_out[6],data_out[4],data_out[2],data_out[0]};
always@(posedge clk_E)
if (cnt[2]==1'b1)begin
fall_data_s<=fall_data ;
rise_data_s<=rise_data ;
cnt<=3'b0 ;
end
else begin
fall_data_s<=fall_data_s>>1 ;
rise_data_s<=rise_data_s>>1 ;
cnt<=cnt+1'b1 ;
end
ddio_out ddio_out_inst_p (
.datain_h ( rise_data_s[0] ),
.datain_l ( fall_data_s[0] ),
.outclock ( ~clk_E ),
.dataout ( ser_p)
);
ddio_out ddio_out_inst_n (
.datain_h ( ~rise_data_s[0] ),
.datain_l ( ~fall_data_s[0] ),
.outclock ( ~clk_E ),
.dataout ( ser_n)
);
endmodule
ddio配置如图:
vga模块不给出代码,
总结:信号处理是实现HDMI功能的关键。在HDMI协议中,涉及到了很多信号处理的技术,比如时钟同步、分辨率转换、色彩空间转换等。这些技术都需要用verilog实现,并且需要尽可能地优化,以确保HDMI信号的稳定和高质量。