ZYNQ基础系列(二) IO口模拟HDMI

IO口直接驱动HDMI接口

HDMI主要用于给高清显示设备传输视频和音频数据,除了使用专门的HDMI芯片外,当然还可以用ZYNQ的PL部分产生相应的时序,本文就是用FPGA的IO口与HDMI显示设备直接进行通信
本文的工程rgb2dvi的IP核都上传到了这里

一、原理图

本文采用的是米联客的Mi701开发板,可以看到IO口是直接连到接口上的,只加了一些简单的上拉增加一下驱动能力,IIC也是经过了5V的电平转换,HDMI的5V供电由使能引脚控制
ZYNQ基础系列(二) IO口模拟HDMI_第1张图片
ZYNQ基础系列(二) IO口模拟HDMI_第2张图片

二、RGB数据转DVI的IP核(不重要)

现在暂时不自己去写这个IP核的底层,直接找到例程里的文件,并自己重新封装一下IP核,文件包括:

DVITransmitter.vhd
hdmi_tx.vhd
SerializerN_1.vhd
TMDSEncoder.vhd

  • 1.新建IP工程,命名为rgb2dvi,设置器件型号
  • 2.将上述四个文件添加到工程中,工程自动识别顶层
  • 3.设置相关信息
    ZYNQ基础系列(二) IO口模拟HDMI_第3张图片

  • 4.Tools菜单中,新建IP核,一路默认即可

  • 5.在弹出的窗口中,修改IP信息,添加总线(用于连接其他IP模块)等
    ZYNQ基础系列(二) IO口模拟HDMI_第4张图片
    弹出的界面的第一页,设置总线类型、名称等
    ZYNQ基础系列(二) IO口模拟HDMI_第5张图片
    在第二页中,把自己的线和系统预定的线进行一个匹配,匹配的结果如下:
    ZYNQ基础系列(二) IO口模拟HDMI_第6张图片
    如图创建VGA总线,创建完成后预览IP核
    ZYNQ基础系列(二) IO口模拟HDMI_第7张图片

  • 6.最后把IP打包即可

三、工程文件

创建工程,并在setting中加载IP核的路径后,即可在IP核搜索器中搜索到rgb2dvi模块,现在创建这个工程还需要四步

创建一个rgb2dvi的IP,然后准备用这个IP在工程中创建实例
创建一个Clock Wizard的IP,准备用于产生时钟
创建一个.v文件,用于产生显示所需的时序
创建顶层.v文件
引脚约束

  • 1.VGA相关基础
    时序图,以及消隐的概念,还有不同分辨率时,各个区域的参数
    ZYNQ基础系列(二) IO口模拟HDMI_第8张图片
    ZYNQ基础系列(二) IO口模拟HDMI_第9张图片

  • 2.时钟管理模块
    由于我的屏幕分辨率为800*600,所以,时钟管理模块,CLK1输出为40M,CLK2是CLK1的5倍200M,选择MMCM模式

  • 3.rgb2dvi模块
    直接在IP拾取器中,创建IP

  • 4.时序产生模块
    此模块针对800*600的屏幕,产生一个彩色的网格,如需更改为其他分辨率,相关的参数见上表

`timescale 1ns / 1ps
module hdmi_data_gen (
    input           pix_clk,
    output [7:0]    VGA_R,
    output [7:0]    VGA_G,
    output [7:0]    VGA_B,
    output          VGA_HS,
    output          VGA_VS,
    output          VGA_DE
    );

//---------------------------------//
// 水平扫描参数的设定800*600  60HZ
//--------------------------------//
parameter H_Sync        =   128;
parameter H_Back        =   88;
parameter H_Active      =   800;
parameter H_Front       =   40;
parameter H_Start       =   H_Sync + H_Back;
parameter H_End     =   H_Start + H_Active;
parameter H_Total       =   H_End + H_Front;
//-------------------------------//
// 垂直扫描参数的设定800*600 60HZ    
//-------------------------------//
parameter V_Sync        =   4;
parameter V_Back        =   23;
parameter V_Active      =   600;
parameter V_Front       =   1;
parameter V_Start       =   V_Sync + V_Back;
parameter V_End     =   V_Start + V_Active;
parameter V_Total       =   V_End + V_Front;

reg[11:0]   x_cnt;
always @(posedge pix_clk)       //水平计数
begin
    if(x_cnt==H_Total)
      x_cnt <=  1;
    else
      x_cnt <=  x_cnt   +   1;
end

reg hsync_r;
reg hs_de;
always @(posedge pix_clk)
begin
    if(x_cnt==1)
      hsync_r   <=  1'b0;
    else if(x_cnt==H_Sync)
      hsync_r   <=  1'b1;

    if(x_cnt==H_Start)
      hs_de <=  1'b1;
    else if(x_cnt==H_End)
      hs_de <=  1'b0;
end

reg[11:0]   y_cnt;
always @(posedge pix_clk)
begin
    if(y_cnt==V_Total)
      y_cnt <=  1;
    else if(x_cnt==H_Total)
      y_cnt <=  y_cnt   +   1;
end

reg vsync_r;
reg vs_de;
always @(posedge pix_clk)
begin
    if(y_cnt==1)
      vsync_r   <=  1'b0;
    else if(y_cnt==V_Sync)
      vsync_r   <=  1'b1;

    if(y_cnt==V_Start)
      vs_de  <= 1'b1;
    else if(y_cnt==V_End)
      vs_de  <= 1'b0;
end

reg[7:0]    VGA_R_reg;
reg[7:0]    VGA_G_reg;
reg[7:0]    VGA_B_reg;
always @(posedge pix_clk)           //格子图像
begin
    if((x_cnt[4]==1'b1)^(y_cnt[4]==1'b1))
      VGA_R_reg <=  8'h00;
    else
      VGA_R_reg <=  8'hff;

    if((x_cnt[5]==1'b1)^(y_cnt[5]==1'b1))
      VGA_G_reg    <=    8'h00;
    else
      VGA_G_reg    <=    8'hff;

    if((x_cnt[6]==1'b1)^(y_cnt[6]==1'b1))
      VGA_B_reg    <=    8'h00;
    else
      VGA_B_reg    <=    8'hff;
end

assign VGA_HS   =   hsync_r;
assign VGA_VS   =   vsync_r;
assign VGA_DE   =   hs_de   &   vs_de;
assign VGA_R    =   VGA_DE ? VGA_R_reg : 8'h0;
assign VGA_G    =   VGA_DE ? VGA_G_reg : 8'h0;
assign VGA_B    =   VGA_DE ? VGA_B_reg : 8'h0;
endmodule
  • 5.顶层模块
    顶层也就是将三个模块连接在一起

  • 6.引脚约束
    引脚约束,需要注意的是差分线的约束,模式为TMDS_33,然后只需约束各个差分对的P脚即可

set_property IOSTANDARD TMDS_33 [get_ports HDMI_CLK_P]
set_property IOSTANDARD TMDS_33 [get_ports HDMI_D0_P]
set_property IOSTANDARD TMDS_33 [get_ports HDMI_D1_P]
set_property IOSTANDARD TMDS_33 [get_ports HDMI_D2_P]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_en]

set_property PACKAGE_PIN K17 [get_ports HDMI_CLK_P]
set_property PACKAGE_PIN L19 [get_ports HDMI_D0_P]
set_property PACKAGE_PIN M17 [get_ports HDMI_D1_P]
set_property PACKAGE_PIN L16 [get_ports HDMI_D2_P]
set_property PACKAGE_PIN D18 [get_ports hdmi_en]

四、实验现象

ZYNQ基础系列(二) IO口模拟HDMI_第10张图片
到此为止,对rgb2dvi的IP核的测试也就完成了,此例中的显示时序都是由PL中产生的,而且如果要换分辨率还是要改很多参数,很不方便,如果想用此种方式显示个图片,那估计就更麻烦了
所以之后会用xilinx自带的VTC的IP核,专门产生时序控制
之后将介绍视频通路的搭建

你可能感兴趣的:(ZYNQ,基础系列)