IT6802是宝岛台湾联阳半导体设计生产的HDMI接受芯片,数据手册有49页,编程手册79页,想要看懂并操作还是有难度的,所以直接上干货。
开发板:Kintex7板子;
开发环境:vivado2019.1;
输入:IT6802解码的HDMI视频流;
输出:HDMI;
提供两套工程:
第一套:IT6802采集后直接环出显示;
第二套:IT6802采集后经DDR3缓存三帧后输出显示;
芯片架构如下:
视频接受处理流程如下:
视频输出时钟如下:根据不同的输入分辨率选择约束不同的时钟。
我用电脑主机的1080P@60hz输出给板子接收,所以IT6802输出给FPGA的像素时钟就是148.5M,在XDC的输入时钟约束就应如下:
根据时序图,FPGA应该在上升沿采集数据,如下:
根据官方手册,上电后,复位引脚应至少保持10ms的低电平,如下:
代码中给了20ms的低电平复位时间。
IT6802的输出位宽一共36位,根据不同的视频格式自行选择输出引脚的原理图设计,我的板子选择的是RGB24位宽视频输入,数据手册参考部分如下:
对应的原理图设计就应如下:
RGB4:4:4模式下的视频输入时许如下:
i2c配置:
器件地址由PCADR引脚决定,如下:
我的板子是拉低,所以期间地址为0x90,如下:
IT6802的期间地址是7位,寄存器地址是8位,数据位是8位;
IT6802有上百个寄存器(具体见编程手册),但由于本次实验制作视频采集,所以只需配置3个寄存器即可,如下:
第一套:IT6802采集后直接环出显示;
工程代码结构如下:
直接给出顶层代码,如下:
module it6802_rx_top(
input sys_clk_27m ,
input i_it6802_clk ,
input i_it6802_hs ,
input i_it6802_vs ,
input i_it6802_de ,
input [23:0] i_it6802_rgb,
output o_it6802_sck ,
inout o_it6802_sda ,
output o_it6802_rstn ,
output o_hdmi_cc_p ,
output o_hdmi_cc_n ,
output o_hdmi_d0_p ,
output o_hdmi_d0_n ,
output o_hdmi_d1_p ,
output o_hdmi_d1_n ,
output o_hdmi_d2_p ,
output o_hdmi_d2_n
);
localparam TM6802_RSTN_20MS=20_000_000/1000/100-1;
wire i_it6802_clk_bufg;
wire clk_100m;
wire rst_n;
wire init_done;
reg [1:0] r_i_it6802_hs ;
reg [1:0] r_i_it6802_vs ;
reg [1:0] r_i_it6802_de ;
reg [47:0]r_i_it6802_rgb;
reg [20:0] it6802_rstn_cnt;
assign o_it6802_rstn=(it6802_rstn_cnt==TM6802_RSTN_20MS);
BUFG u_BUFG (
.O(i_it6802_clk_bufg), // 1-bit output: Clock output
.I(i_it6802_clk) // 1-bit input: Clock input
);
clk_wiz_0 u_clk_wiz_0
(
// Clock out ports
.clk_out1(clk_100m), // output clk_100m
// Status and control signals
.locked(rst_n), // output locked
// Clock in ports
.clk_in1(sys_clk_27m)); // input clk_in1
i2c_it6802_cfg #(
.CLK_FREQ (100_000_000), //?????????
.I2C_FREQ (250000 ) //IIC_SCL?????
)
u_i2c_it6802_cfg(
.ADV_CLK (clk_100m ),
.ADV_RSTN (rst_n ),//?????
.ADV_SCLK (o_it6802_sck),
.ADV_SDAT (o_it6802_sda),
.init_done(init_done )
);
always @(posedge clk_100m) begin
if(~init_done) it6802_rstn_cnt<='d0;
else if(it6802_rstn_cnt==TM6802_RSTN_20MS) it6802_rstn_cnt<=TM6802_RSTN_20MS;
else it6802_rstn_cnt<=it6802_rstn_cnt+'d1;
end
always @(posedge i_it6802_clk_bufg) begin
if(~init_done) begin
r_i_it6802_hs <='d0;
r_i_it6802_vs <='d0;
r_i_it6802_de <='d0;
r_i_it6802_rgb<='d0;
end
else begin
r_i_it6802_hs <={r_i_it6802_hs [0], i_it6802_hs };
r_i_it6802_vs <={r_i_it6802_vs [0], i_it6802_vs };
r_i_it6802_de <={r_i_it6802_de [0], i_it6802_de };
r_i_it6802_rgb<={r_i_it6802_rgb[23:0],i_it6802_rgb};
end
end
dvi_transmitter_top helai_hdmi_out(
.ref_clk (i_it6802_clk_bufg ),
.i_vga_hs (r_i_it6802_hs [1] ),
.i_vga_vs (r_i_it6802_vs [1] ),
.i_vga_de (r_i_it6802_de [1] ),
.i_vga_rgb (r_i_it6802_rgb[47:24]),
.tmds_clk_p (o_hdmi_cc_p ),
.tmds_clk_n (o_hdmi_cc_n ),
.tmds_data0b_p(o_hdmi_d0_p ),
.tmds_data0b_n(o_hdmi_d0_n ),
.tmds_data1g_p(o_hdmi_d1_p ),
.tmds_data1g_n(o_hdmi_d1_n ),
.tmds_data2r_p(o_hdmi_d2_p ),
.tmds_data2r_n(o_hdmi_d2_n ),
.o_vga_rclk (),
.o_vga_hs (),
.o_vga_vs (),
.o_vga_de (),
.o_x_pos (),
.o_y_pos ()
);
endmodule
第二套:IT6802采集后经DDR3缓存三帧后输出显示;
BD工程如下:
BD工程搭建了一个DDR三帧缓存的架构;
工程代码结构如下:
直接给出顶层代码,如下:
module it6802_rx_ddr3_hdmi_top(
input sys_clk_27m ,
input i_it6802_clk ,
input i_it6802_hs ,
input i_it6802_vs ,
input i_it6802_de ,
input [23:0] i_it6802_rgb ,
output o_it6802_sck ,
inout o_it6802_sda ,
output o_it6802_rstn ,
output o_hdmi_cc_p ,
output o_hdmi_cc_n ,
output o_hdmi_d0_p ,
output o_hdmi_d0_n ,
output o_hdmi_d1_p ,
output o_hdmi_d1_n ,
output o_hdmi_d2_p ,
output o_hdmi_d2_n ,
// DDR3
output [12:0]DDR3_0_addr ,
output [2:0] DDR3_0_ba ,
output DDR3_0_cas_n ,
output [0:0] DDR3_0_ck_n ,
output [0:0] DDR3_0_ck_p ,
output [0:0] DDR3_0_cke ,
output [3:0] DDR3_0_dm ,
inout [31:0] DDR3_0_dq ,
inout [3:0] DDR3_0_dqs_n ,
inout [3:0] DDR3_0_dqs_p ,
output [0:0] DDR3_0_odt ,
output DDR3_0_ras_n ,
output DDR3_0_reset_n,
output DDR3_0_we_n ,
output ddr3_ok
);
localparam TM6802_RSTN_20MS=20_000_000/1000/100-1;
wire i_it6802_clk_bufg;
wire clk_100m;
wire rst_n;
wire init_done;
reg [1:0] r_i_it6802_vs ;
reg [1:0] r_i_it6802_de ;
reg [47:0]r_i_it6802_rgb;
reg [20:0] it6802_rstn_cnt;
assign o_it6802_rstn=(it6802_rstn_cnt==TM6802_RSTN_20MS);
BUFG u_BUFG (
.O(i_it6802_clk_bufg), // 1-bit output: Clock output
.I(i_it6802_clk) // 1-bit input: Clock input
);
i2c_it6802_cfg #(
.CLK_FREQ (100_000_000), //?????????
.I2C_FREQ (250000 ) //IIC_SCL?????
)
u_i2c_it6802_cfg(
.ADV_CLK (clk_100m ),
.ADV_RSTN (rst_n ),//?????
.ADV_SCLK (o_it6802_sck),
.ADV_SDAT (o_it6802_sda),
.init_done(init_done )
);
always @(posedge clk_100m) begin
if(~init_done) it6802_rstn_cnt<='d0;
else if(it6802_rstn_cnt==TM6802_RSTN_20MS) it6802_rstn_cnt<=TM6802_RSTN_20MS;
else it6802_rstn_cnt<=it6802_rstn_cnt+'d1;
end
always @(posedge i_it6802_clk_bufg) begin
if(~init_done) begin
r_i_it6802_vs <='d0;
r_i_it6802_de <='d0;
r_i_it6802_rgb<='d0;
end
else begin
r_i_it6802_vs <={r_i_it6802_vs [0], i_it6802_vs };
r_i_it6802_de <={r_i_it6802_de [0], i_it6802_de };
r_i_it6802_rgb<={r_i_it6802_rgb[23:0],i_it6802_rgb};
end
end
wire [31:0] fdma_raddr_0 ;
wire fdma_rareq_0 ;
wire fdma_rbusy_0 ;
wire [127:0]fdma_rdata_0 ;
wire fdma_rready_0;
wire [15:0] fdma_rsize_0 ;
wire fdma_rvalid_0;
wire [31:0] fdma_waddr_0 ;
wire fdma_wareq_0 ;
wire fdma_wbusy_0 ;
wire [127:0] fdma_wdata_0 ;
wire fdma_wready_0;
wire [15:0] fdma_wsize_0 ;
wire fdma_wvalid_0;
wire ui_clk_200m ;
wire rst_n ;
design_1 u_design_1
(
.DDR3_0_addr (DDR3_0_addr ),
.DDR3_0_ba (DDR3_0_ba ),
.DDR3_0_cas_n (DDR3_0_cas_n ),
.DDR3_0_ck_n (DDR3_0_ck_n ),
.DDR3_0_ck_p (DDR3_0_ck_p ),
.DDR3_0_cke (DDR3_0_cke ),
.DDR3_0_dm (DDR3_0_dm ),
.DDR3_0_dq (DDR3_0_dq ),
.DDR3_0_dqs_n (DDR3_0_dqs_n ),
.DDR3_0_dqs_p (DDR3_0_dqs_p ),
.DDR3_0_odt (DDR3_0_odt ),
.DDR3_0_ras_n (DDR3_0_ras_n ),
.DDR3_0_reset_n(DDR3_0_reset_n),
.DDR3_0_we_n (DDR3_0_we_n ),
.clk_in1_0 (sys_clk_27m ),
.ddr3_ok (ddr3_ok ),
.fdma_raddr_0 (fdma_raddr_0 ),
.fdma_rareq_0 (fdma_rareq_0 ),
.fdma_rbusy_0 (fdma_rbusy_0 ),
.fdma_rdata_0 (fdma_rdata_0 ),
.fdma_rready_0 (fdma_rready_0 ),
.fdma_rsize_0 (fdma_rsize_0 ),
.fdma_rvalid_0 (fdma_rvalid_0 ),
.fdma_waddr_0 (fdma_waddr_0 ),
.fdma_wareq_0 (fdma_wareq_0 ),
.fdma_wbusy_0 (fdma_wbusy_0 ),
.fdma_wdata_0 (fdma_wdata_0 ),
.fdma_wready_0 (fdma_wready_0 ),
.fdma_wsize_0 (fdma_wsize_0 ),
.fdma_wvalid_0 (fdma_wvalid_0 ),
.ui_clk_0 (ui_clk_200m ),
.rst_n (rst_n ),
.clk_100m (clk_100m )
);
fdma_contrl #(
.VIDEO_H_SRTI_W (1920 ),
.VIDEO_H_SIZE_W (1920 ), //输入图像行分辨率
.VIDEO_V_SIZE_W (1080 ), //输入图像场分辨率
.VIDEO_H_SRTI_R (1920 ),
.VIDEO_H_SIZE_R (1920 ), //输入图像行分辨率
.VIDEO_V_SIZE_R (1080 ), //输入图像场分辨率
.VIDEO_DAAR_0 (32'h80000000), //第1帧图像缓存基地址
.VIDEO_DAAR_1 (32'h81000000), //第2帧图像缓存基地址
.VIDEO_DAAR_2 (32'h82000000), //第3帧图像缓存基地址
.FDMA_TRANS_DIV (2 ), //一行图像分2次FDMA突发写传输
.FDMA_FRAME_NUM (3 ) //缓存3帧
)
helai_fdma_contrl(
.ui_clk_200m (ui_clk_200m ),
.rst_n (rst_n ),
.cmos_pclk (i_it6802_clk_bufg ),
.senser_vs (r_i_it6802_vs [1] ),
.senser_de (r_i_it6802_de [1] ),
.senser_rgb (r_i_it6802_rgb[47:24]),
.vga_clk (vga_clk ),
.vga_vs (vga_vs ),
.vga_de (vga_de ),
.o_vga_rgb (vga_data ),
.fdma_waddr_0 (fdma_waddr_0 ),
.fdma_wareq_0 (fdma_wareq_0 ),
.fdma_wbusy_0 (fdma_wbusy_0 ),
.fdma_wdata_0 (fdma_wdata_0 ),
.fdma_wready_0(fdma_wready_0 ),
.fdma_wsize_0 (fdma_wsize_0 ),
.fdma_wvalid_0(fdma_wvalid_0 ),
.fdma_raddr_0 (fdma_raddr_0 ),
.fdma_rareq_0 (fdma_rareq_0 ),
.fdma_rbusy_0 (fdma_rbusy_0 ),
.fdma_rdata_0 (fdma_rdata_0 ),
.fdma_rready_0(fdma_rready_0 ),
.fdma_rsize_0 (fdma_rsize_0 ),
.fdma_rvalid_0(fdma_rvalid_0 )
);
wire vga_clk;
wire vga_hs;
wire vga_vs;
wire vga_de;
wire [23:0] vga_data;
dvi_transmitter_top helai_hdmi_out(
.ref_clk (ui_clk_200m),
.i_vga_hs (vga_hs ),
.i_vga_vs (vga_vs ),
.i_vga_de (vga_de ),
.i_vga_rgb (vga_data ),
.tmds_clk_p (o_hdmi_cc_p),
.tmds_clk_n (o_hdmi_cc_n),
.tmds_data0b_p(o_hdmi_d0_p),
.tmds_data0b_n(o_hdmi_d0_n),
.tmds_data1g_p(o_hdmi_d1_p),
.tmds_data1g_n(o_hdmi_d1_n),
.tmds_data2r_p(o_hdmi_d2_p),
.tmds_data2r_n(o_hdmi_d2_n),
.o_vga_rclk (vga_clk ),
.o_vga_hs (vga_hs ),
.o_vga_vs (vga_vs ),
.o_vga_de (vga_de ),
.o_x_pos (),
.o_y_pos ()
);
endmodule
上班调试结果:
硬件连接:
输出结果:
福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
也可以直接下载工程源码,下载链接:
点击下载工程源码
网盘资料如下: