用Xilinx的FPGA实现HDMI(DVI)接收器
1. 问题-HDMI接收器
1.1 ADV7511
一般来说,如果要使用HDMI作为视频收发协议的话,会配置关于HDMI的编解码芯片。常见的有ADV7511(HDMI发送器)和ADV7611(HDMI接收器)。这样开发者关于HDMI的设计部分可以转化为与HDMI接收或者发送芯片的数据交互。利用FPGA进行设计时,有的FPGA有HDMI接口,却没有HDMI编解码芯片。这个时候要如何使用HDMI接口呢?
一种方案是通过FMC接口外置HDMI模块子卡,这样就可以使用上HDMi编解码芯片。另外一种方案,可以使用FPGA内置的HDMi的IP。接下来我将介绍利用Xilinx的IP实现HDMI接收器。
对于HDMI发送器的部分,当然也可以利用Xilinx的IP实现。
2. HDMI(DVI)接收器
2.1 IP的设置
本文使用的是digilent公司的genesys2开发板,使用的是digilent公司提供的IP。这里需要注意的是当你安装vivado的时候,digilent公司的IP不会集成在vivado的IP中,需要开发者自己手动下载,并添加到vivado中。
2.2 IP设置如下
首先要设置TMDS的工作频率。最重要的是要使能Enable DDC ROM,它会设置DVI接收端可以接受的分辨率,与DVI发送端连接时,发送端会自动从接收端读取接收端可以处理的分辨率。按照这个分辨率发送数据。如果不使能Enable DDC ROM,发送端将无法检测到HDMI接收端,无法发送数据。
3. HDMI转VGA
下面代码是一个简易的HDMI—VGA转换器。FPGA设置好后,连接到PC端,再将FPGA连接到一个VGA显示器,图片信息就会从PC端发出,经由FPGA,显示在VGA显示器上。
```handlebars
module hdmi_input(
input clk_in1_n,
input clk_in1_p,
input sys_rst, //高电平复位
//dvi接口
input TMDS_Clk_p,
input TMDS_Clk_n ,
input [2:0]TMDS_Data_p ,
input [2:0]TMDS_Data_n ,
inout DDC_0_scl_io,
inout DDC_0_sda_io,
output hpa,
output led1 ,
output vga_hsync,
output vga_vsync,
output[4:0] vga_r,
output[5:0] vga_g,
output[4:0] vga_b
);
wire rst;
wire clk_200m;
wire locked;
assign hpa = 1;
wire SDA_I ;
wire SDA_O ;
wire SDA_T ;
wire SCL_I ;
wire SCL_O ;
wire SCL_T ;
wire [23:0]vid_pData;
wire vid_pVDE;
wire vid_pHSync;
wire vid_pVSync;
wire PixelClk;
wire aPixelClkLckd;
reg pRst;
reg [10:0] hcnt;
reg [9:0] ycnt;
sys_rst_hdmi u_sys_rst(
.rst (rst),
.sys_rst (!locked & sys_rst),
.clk (clk_200m)
);
clk_hdmi u_clk_hdmi(
.clk_200m (clk_200m) ,
.reset (sys_rst) ,
.locked (locked) ,
.clk_in1_p (clk_in1_p) ,
.clk_in1_n (clk_in1_n)
);
IOBUF DDC_0_scl_iobuf
(.I(SCL_O),
.IO(DDC_0_scl_io),
.O(SCL_I),
.T(SCL_T));
IOBUF DDC_0_sda_iobuf
(.I(SDA_O),
.IO(DDC_0_sda_io),
.O(SDA_I),
.T(SDA_T));
dvi2rgb_0 u_dvi2rgb(
.TMDS_Clk_p (TMDS_Clk_p),
.TMDS_Clk_n (TMDS_Clk_n),
.TMDS_Data_p (TMDS_Data_p),
.TMDS_Data_n (TMDS_Data_n),
.RefClk (clk_200m),
.aRst (rst),
.vid_pData (vid_pData), //输出数据
.vid_pVDE (vid_pVDE), //数据有效使能信号
.vid_pHSync (vid_pHSync),
.vid_pVSync (vid_pVSync),
.PixelClk (PixelClk),
.aPixelClkLckd (aPixelClkLckd),
.SDA_I (SDA_I),
.SDA_O (SDA_O),
.SDA_T (SDA_T),
.SCL_I (SCL_I),
.SCL_O (SCL_O),
.SCL_T (SCL_T),
.pRst (pRst)
);
always@(posedge PixelClk)
begin
pRst <= rst;
end
assign vga_hsync = vid_pHSync;
assign vga_vsync = vid_pVSync;
assign vga_r = vid_pData[23:19];
assign vga_g = vid_pData[15:10];
assign vga_b = vid_pData[7:3];
endmodule