一、 概况
之前已经讲述了如何用时钟的动态偏移来实现数据的自动校准。本章节来说明时钟的动态偏移的使用情况,和HDMI数据接收的处理流程。
二、 HDMI接收处理
处理流程:
1、差分时钟接收与动态相位调整
2、串并转换(ser2par模块)
3、TMDS 解码(decode模块)
4、像素信息统计(pixel_message子模块)
hdmi_in模块接收处理HDMI的输入信号,先通过时钟的相位偏移实现数据的自动校正,再通过decode模块进行信号的10bit到8bit转换,算出RGB信号和行场同步及de信号。再由行场同步及de信号可以算出每一帧图像里,行同步有多少,场同步有多少,这就是接收到的视频的像素值。接口连接如图1:

hdmi_in模块接口列表:

module hdmi_in(
input wire clk ,//50M
input wire rst_n ,
input wire clk_200 ,
input wire tmds_clk_p ,
input wire tmds_clk_n ,
input wire tmds_r_p ,
input wire tmds_r_n ,
input wire tmds_g_p ,
input wire tmds_g_n ,
input wire tmds_b_p ,
input wire tmds_b_n ,
output clk_1x ,
output 7:0 r_pixel ,
output 7:0 g_pixel ,
output 7:0 b_pixel ,
output h_sync ,
output v_sync ,
output vga_de ,
output wire r_hdmi_en
);
wire h_sync_r ;
wire v_sync_r ;
wire vga_de_r ;
wire11:0 h_pixel_num ;
wire11:0 v_pixel_num ;
wire pixel_clk ;
wire clk_5x ;
wire9:0 r_10bit ;
wire9:0 g_10bit ;
wire9:0 b_10bit ;
reg9:0 b_10bit_reg ;
wire locked ;
reg hdmi_calib_done ;
parameter CTRL0 = 10'h354;//h_sync = 0,v_sync = 0,vga_de = 0
parameter CTRL1 = 10'h0ab;//h_sync = 1,v_sync = 0,vga_de = 0
parameter CTRL2 = 10'h154;//h_sync = 0,v_sync = 1,vga_de = 0
parameter CTRL3 = 10'h2ab;//h_sync = 1,v_sync = 1,vga_de = 0
reg1:0 cnt_num ;
reg psen;
wire psincdec;
reg 10:0 cnt_psen;
reg 4:0 cnt_psclk;
assign r_hdmi_en = 1'b1 ;
//pixel_10bit_reg
always@(posedge clk_1x)
if(locked==1'b0)
b_10bit_reg <= 10'b0;
else
b_10bit_reg <= b_10bit;
//cnt_num
always@(posedge clk_1x)
if(locked1'b0)
cnt_num <= 2'b0;
else if(b_10bitb_10bit_reg)
cnt_num <= cnt_num;
else if(b_10bitCTRL1&&b_10bit_regCTRL0)
cnt_num <= cnt_num+1'b1;
else if(b_10bitCTRL0&&b_10bit_regCTRL1)
cnt_num <= cnt_num+1'b1;
else if((b_10bit!=CTRL0)&&(b_10bit!=CTRL1))
cnt_num <= 2'b0;
//hdmi_calib_done
always@(posedge clk_1x)
if(locked1'b0)
hdmi_calib_done <= 1'b0;
else if(cnt_num2)
hdmi_calib_done <= 1'b1;
always @(posedge clk_200 ) begin
if(!rst_n) begin
cnt_psclk <= 0;
end
else if (hdmi_calib_done == 1 ) begin
cnt_psclk <= 0;
end
else if (hdmi_calib_done == 0)begin
cnt_psclk <= cnt_psclk +1;
end
end
always @(posedge clk_200 ) begin
if(!rst_n) begin
cnt_psen <= 0;
end
else if (psen == 1) begin
cnt_psen <= cnt_psen +1;
end
end
always @(posedge clk_200 ) begin
if(!rst_n) begin
psen <= 0;
end
else if(cnt_psclk == 'd31)begin
psen <= 1;
end
else begin
psen <= 0;
end
end
IBUFDS #(
.DIFF_TERM("FALSE"), // Differential Termination
.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
) IBUFDS_inst (
.O(pixel_clk), // Buffer output
.I(tmds_clk_p), // Diff_p buffer input (connect directly to top-level port)
.IB(tmds_clk_n) // Diff_n buffer input (connect directly to top-level port)
);
clk_wiz_5x clk_wiz_5x_inst
(
// Clock out ports
.clk_1x(clk_1x), // output clk_1x
.clk_5x(clk_5x), // output clk_5x
// Dynamic phase shift ports
.psclk(clk_200), // input psclk //clk for psen
.psen(psen), // input psen //start flag
.psincdec(0), // input psincdec //1+,0-.
.psdone(psdone), // output psdone //finish flag
// Status and control signals
.reset(!rst_n), // input reset
.locked(locked), // output locked
// Clock in ports
.clk_in1(pixel_clk)); // input clk_in1
//r
ser2par ser2par_r_inst(
.pixel_clk (clk_1x ),
.pixel_clk_5x (clk_5x ),
.rst_n (locked ),
.ser_dat_p (tmds_r_p ),
.ser_dat_n (tmds_r_n ),
.pixel_10bit (r_10bit )
);
//decode
decode decode_r(
.pixel_clk (clk_1x ),
.rst_n (locked ),
.i_par_dat (r_10bit ),
.de (),
.c0 (),
.c1 (),
.pixel_dat (r_pixel )
);
//g
ser2par ser2par_g_inst(
.pixel_clk (clk_1x ),
.pixel_clk_5x (clk_5x ),
.rst_n (locked ),
.ser_dat_p (tmds_g_p ),
.ser_dat_n (tmds_g_n ),
.pixel_10bit (g_10bit )
);
//decode
decode decode_g(
.pixel_clk (clk_1x ),
.rst_n (locked ),
.i_par_dat (g_10bit ),
.de (),
.c0 (),
.c1 (),
.pixel_dat (g_pixel )
);
//b
ser2par ser2par_b_inst(
.pixel_clk (clk_1x ),
.pixel_clk_5x (clk_5x ),
.rst_n (locked ),
.ser_dat_p (tmds_b_p ),
.ser_dat_n (tmds_b_n ),
.pixel_10bit (b_10bit )
);
//decode
decode decode_b(
.pixel_clk (clk_1x ),
.rst_n (locked ),
.i_par_dat (b_10bit ),
.de (vga_de ),
.c0 (h_sync ),
.c1 (v_sync ),
.pixel_dat (b_pixel )
);
assign h_sync_r=h_sync;
assign v_sync_r=v_sync;
assign vga_de_r=vga_de;
//pixel_message
pixel_message pixel_message_inst(
.pix_clk (clk_1x ),
.rst_n (locked ),
.h_sync (h_sync_r ),
.v_sync (v_sync_r ),
.de (vga_de_r ),
.o_h_cnt (h_pixel_num ),
.o_v_cnt (v_pixel_num )
);
endmodule
三、总结
本章节完整演示了HMDI接收链路的底层硬件实现,涵盖动态相位补偿技术,TMDS 解码算法,帧同步参数提取。
下一章节来讲述如何将10bit编码信号转换为8bit信号(TMDS 解码算法)。和通过获取HDMI数据信号计算像素的过程。
本文章由威三学社威三学院出品
对课程感兴趣可以私信联系