445|1

10

帖子

0

资源

一粒金砂(中级)

【国产FPGA 正点原子DFPGL22G开发板】三、HDMI输出实验【硬件设计篇和程序设计篇】 [复制链接]

本帖最后由 yyliu 于 2023-1-15 18:08 编辑

声明:1.本帖有对引用其他网站资源,均附上了网址,如HDMI原理图章节等,针对本帖中可能出现的侵权行为,请及时联系本人修改或删除。

2.未经本人允许,请勿转载。若本帖存在错误或不足之处,烦请指正,本人会及时修改。


 

0.说明


1.测评第二期和第三期主要是基于正点原子的学习资源,学习、分析、复现以太网模块和HDMI模块。由于有一定的难度,自己发挥的空间有限,且更多的是倾向于对新协议、新算法的学习,通过自己的讲解让大家更容易理解。为了让大家对紫光FPGA更熟悉,后面几期,着重通过FPGA内部的资源如FIFO、RAM等,自己设计小实验并完成代码实现和仿真。

2.第三期将介绍HDMI的驱动设计,HDMI控制原理、FPGA和显示器内部EEPROM的EDID通信过程等。本帖包括硬件设计篇和程序设计篇。

3.硬件设计篇主要FPGA实现HDMI模块的硬件方案,以及一些硬件设计细节;程序设计篇主要介绍HDMI控制原理、HDMI驱动程序设计、FPGA和显示器内部EEPROM的EDID通信过程等。

4.本帖特别指出HDMI在硬件设计上的缺陷,以及程序设计不符合常规HDMI通信流程之处。

 

1.HDMI模块硬件框图


输出HDMI信号的叫做HDMI源端,终端叫做显示器,HDMI的TYPE A引脚主要包括:

1.TMDS引脚:包括TMDS CLOCK、TMDS DATA[2:0],用于传输RGB数字信号、音频信号等;

2.SCL、SDA引脚:主要用于HDMI源端(本帖指FPGA)获取显示器的EDID信息。EDID是一种数据规范,通常存储在显示器内部的EEPROM中,用于告诉源端显示器的厂家、型号、音频格式、支持的分辨率等。以便源端能够选择最佳的分辨率与显示器进行数据传输。

3.HOT PLUG引脚:该引脚主要用于显示器通知主机是否插好,若插好,即使显示器未上电。主机也可以获取显示器的EDID信息。

CEC:消费电子控制引脚,一般不使用。

4.+5V POWER。一般由源端提供给显示器,即使显示器未上电,也可以给显示器内部的EEPROM供电,通过SCL/SDA获取显示器信息。

 

本帖的HDMI模块框图如下,FPGA模拟HDMI通信的源端,通过HDMI连接线连接到显示器,输出数据并显示。需要注意,TMDS CLOCK、TMDS DATA[2:0]传输差分信号,需要连到FPGA的差分数据引脚,其他引脚可以连到差分引脚,也可以连到普通的IO口。

image.png

 

2.HDMI模块原理图设计


下面几张图都是正点原子设计的HDMI模块原理图,本节对原理图进行分析。 image.png HDMI_FCLK_P/N连到了FPGA的PLL5,可以方便的通过锁相环IP核输出各种时钟,传输给显示器。

HDMI_FD[2:0]P/N连到了FPGA的差分引脚。

FPGA用于HDMI接口的引脚分配如下图:

image.png  

由于HDMI接口需要经常插拔,因此需要增加ESD防护器件。

TVS管AZ1045-0F的静电防护等级入下:

IEC 61000-4-2(ESD)±15kV(air),±10kV(contact)

IEC 61000-4-5(Lightning)3.5A(8/20us)

另外,AZ1045-0F具有0.5pF的结电容,对于高速信号的传输来说,会影响信号传输质量,在PCB LAYOUT需要加以补偿。

关于TVS管AZ1045-0F参数选型较为简单,不再阐述。

image.png 下图是TMDS差分传输示意图:在显示器一端,内部有50欧姆的电阻上拉到3.3V电源,源端为恒流源。

image.png 在显示器终端接收到的单端信号和差分信号摆幅如下图:

image.png 发送端的信号摆幅要求在0.4V-0.6V之间。

image.png  接收端差分信号符合要求的范围在0.15V-1.2V之间。

image.png  

下图是主板端TYPE-A接口的设计,需要指出四点设计问题。
image.png 1.VCC5用于给显示器内部供电,显示器端的规范要求不能超过50mAD的负载电流。但是检测认证对主板端的供电接口电流输出能力有限制,即安规LPS要求。所以,应该给VCC5增加PPTC或者限流芯片,避免VCC5输出功率过大。

2.SCL和SDA引脚(准确的说是DDC接口)需要连到显示器内部,获取EDID新信息。但实际设计上,并未将这两个引脚连接到FPGA的IO,因此,FPGA就无法获取显示器的EDID信息。

3.HOT PLUG引脚直接上拉到VCC3.3,这是不合理的。因为显示器端的该引脚上拉到+5V,主板端使用下拉电阻连到GND。当显示器插入时,将HOT PLUG信号拉高通知FPGA有显示器插入,可以开始EDID通信。否则,拔插显示器时也都无法重新获取显示器的EDID信息。

4.除了增肌TVS防止ESD以外,为了通过EMC测试,TMDS一般需要串接共模电感(也可和电阻叠焊盘)。

由于硬件设计原因,从程序设计来看,正点原子本实验只是固定输出一个分辨率和信号给显示器。

 

3.HDMI通信原理


HDMI通信原理其实前面也有提及,本节再进行简单梳理。

 3.1 传输信号

本小节主要参考:https://blog.csdn.net/weixin_44820005/article/details/108851434

image.png

4对TMDS差分信号:1对时钟+3对数据;
HDMI把视频信号分为R、G、B、H、V五种信号用TMDS技术编码。
TMDS: 这三个通道传输R、G、B三原色,HV编码在B信号通道里面传输,R、G的多余位置用来传输音频信号。
TMDS通道0传输B信号,同时H信号和V信号也嵌入该通道
TMDS通道1传输G信号
TMDS通道2传输R信号,R和G通道的多余位置用来传输音频信号

CEC:消费电子控制通道,通过这条通道可以控制视听设备的工作。

DDC:就是I²C信号,主要是获取显示器的基本信息(比如EDID信息);即显示数据通道,用来向视频接收装置发送配置信息和数据格式信息,接收装置读取这些E-EDID(增强扩展显示识别数据)的信息。

HPD:(Hotplug)热插拔信号,该信号比较重要,当HPD引脚大于2V,TMDS才会输出。

 

3.2 TMDS编码和传输原理

理解下图对理解本帖程序的编写非常有帮助。

image.png

3.3 HDMI像素时钟和传输带宽的计算

本小节主要参考:http://meekdai.com/Learn-HDMI.html

串行接口带宽 = 系统时钟频率 X 数据量;这是一个适用于所有串口传输接口带宽计算的公式。

每一个标准的HDMI连接,都具备4个channel,分别是3个channel传输数据和1个channel传输时钟。在每一个时钟周期内,每个TMDS数据通道都可以传送10bit数据。HDMI 电路中的时钟频率,在最初制定时范围从25MHz-165MHz 之间,也就是说一个 TMDS 通道每秒最多能传输165MHz*10bit=1.65Gbit 的数据,3 个 TMDS 通道一秒就可以传输1.65*3=4.95Gbit 的数据,再加上控制数据,用标准方法表示就是4.96Gbps 的带宽。而如果用像素点来表示,那就是一秒可以传输显示1.65G 个像素点(一个完整的像素点信息由 R/G/B 三原色信息构成)所需要的数据量。

我们常见到像素时钟和位时钟,位时钟=像素时钟x每个像素位数。

在数字音频方面,HDMI 灵活的支持符合 IEC60985 L-PCM 标准的 32kHz、44.1kHz 和 48kHz、16bit 量化的立体声数字音频信号和 IEC 61937 标准的采样率为 192KHz,24bit 量化的单路无压缩 PCM 数字音频信号,或者 8 路 96kHz 的声音数据流。此外,在家庭影院中常用的 DolbyDigital5.1 和 DTS 数字音频格式也能通过 HDMI 直接传输。

HDMI速率计算

传输背景:HDMI 1080p 60FPS 48bit
最大分辨率是 1920*1080,所以每一帧图像有 1920*1080=2073600 个像素,另外,HDMI 的图像还需要预留百分之 20 的空白像素,所以直实的一帧图像的像素是:2073600*1.2=2488320 个像素。我们每个像素用 3 个 16bit 表示,则总共需要的 bit 数是 2488320*3*(16+4)=149299200 个 bit(注意每 8bit 要加 2 个控制 bit,即 8b10b 编码), 每秒刷新 60 次,即 60Hz,那么每秒传输的位数是:149299200*60=8.9580e+009,化成以 Gbps 为单位,则总速率为:8.958Gbps,每路的速率为:8.958/3= 2.9860Gbps

 

4.关键代码分析


HDMI彩条实验只需要显示图像,不需要识别显示器是否插入,不需要识别显示器的EDID数据,此时可以将HDMI当作DVI接口去驱动。正点原子给出的实验框图如下:

image.png RGB2DVI模块,将RGB888格式的视频图像转换成TMDS数据输出。

在顶层模块中,video_display模块负责产生RGB888格式的彩条图案,然后在video_driver模块的驱动下按照工业标准的VGA显示时序输出视频信号、行场同步信号以及视频有效信号。这些信号作为RGB2DVI模块的输入,最终转换成DVI/HDMI接口标准的TMDS串行数据输出到HDMI接口。

 

HDMI顶层模块如下,除了TMDS引脚外,还包括系统时钟和复位引脚。

module  hdmi_colorbar_top(
    input        sys_clk,
    input        sys_rst_n,
    
    output       tmds_clk_p,    // TMDS 时钟通道
    output       tmds_clk_n,
    output [2:0] tmds_data_p,   // TMDS 数据通道
    output [2:0] tmds_data_n
);

 

4.1 pll_clk模块:该模块主要为了产生显示模块和驱动模块所需的时钟。

在硬件设计章节有提到,时钟管脚HDMI_FCLK_P/N连到了FPGA的PLL5,我们很方便的调用IP核产生需要的时钟:

//例化PLL IP核
pll_clk  u_pll_clk(
	.pll_rst        (~sys_rst_n),
	.clkin1         (sys_clk),
	.clkout0        (pixel_clk),      //像素时钟
	.clkout1        (pixel_clk_5x),   //5倍像素时钟
	.pll_lock       (clk_locked)
);

双击锁相环IP核,我们可以看到clkout0和clkout1的频率配置

image.png

下图可以看出IP核pll_clk的输入时钟以及输出时钟的频率。

image.png  

4.2 video_display模块:主要产生RGB888格式的彩条图案

该模块实现1280x720的分辨率。模块输入变量为像素点横纵坐标,来自于video_driver模块;根据像素坐标,输出该像素坐标的数据。

module  video_display(
    input                pixel_clk,
    input                sys_rst_n,
    
    input        [10:0]  pixel_xpos,  //像素点横坐标
    input        [10:0]  pixel_ypos,  //像素点纵坐标
    output  reg  [23:0]  pixel_data   //像素点数据
);

//parameter define
parameter  H_DISP = 11'd1280;                       //分辨率——行
parameter  V_DISP = 11'd720;                        //分辨率——列

localparam WHITE  = 24'b11111111_11111111_11111111;  //RGB888 白色
localparam BLACK  = 24'b00000000_00000000_00000000;  //RGB888 黑色
localparam RED    = 24'b11111111_00001100_00000000;  //RGB888 红色
localparam GREEN  = 24'b00000000_11111111_00000000;  //RGB888 绿色
localparam BLUE   = 24'b00000000_00000000_11111111;  //RGB888 蓝色
    
//*****************************************************
//**                    main code
//*****************************************************

//根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条
always @(posedge pixel_clk ) begin
    if (!sys_rst_n)
        pixel_data <= 16'd0;
    else begin
        if((pixel_xpos >= 0) && (pixel_xpos < (H_DISP/5)*1))
            pixel_data <= WHITE;
        else if((pixel_xpos >= (H_DISP/5)*1) && (pixel_xpos < (H_DISP/5)*2))
            pixel_data <= BLACK;  
        else if((pixel_xpos >= (H_DISP/5)*2) && (pixel_xpos < (H_DISP/5)*3))
            pixel_data <= RED;  
        else if((pixel_xpos >= (H_DISP/5)*3) && (pixel_xpos < (H_DISP/5)*4))
            pixel_data <= GREEN;
        else 
            pixel_data <= BLUE;
    end
end

endmodule

结合上述代码和下图,将横坐标分为5等分:

横坐标<H_DISP/5:显示白色;

H_DISP*1/5横坐标<H_DISP*2/5:显示黑色;

H_DISP*2/5横坐标<H_DISP*3/5:显示红色;

H_DISP*3/5横坐标<H_DISP*4/5:显示绿色;

H_DISP*4/5横坐标<H_DISP*5/5:显示蓝色;

按照上述逻辑赋值就可以产生下图所述数据。

image.png  

4.3 显示驱动video_driver模块:的驱动下按照工业标准的VGA显示时序输出视频信号、行场同步信号以及视频有效信号。

行场同步信号video_hs video_vs、数据使能信号video_de和RGB888颜色数据video_rgb发送给显示器,但是需要经过RGB转DVI模块,转化成HDMI接口TMDS数据格式要求。

pixel_data、pixel_xpos和pixel_ypos主要是与video_display模块进行信号交互。

module video_driver(
    input           pixel_clk,
    input           sys_rst_n,
    
    //RGB接口
    output          video_hs,     //行同步信号
    output          video_vs,     //场同步信号
    output          video_de,     //数据使能
    output  [23:0]  video_rgb,    //RGB888颜色数据
    
    input   [23:0]  pixel_data,   //像素点数据
    output  [10:0]  pixel_xpos,   //像素点横坐标
    output  [10:0]  pixel_ypos    //像素点纵坐标
);

//parameter define

//1280*720 分辨率时序参数
parameter  H_SYNC   =  11'd40;   //行同步
parameter  H_BACK   =  11'd220;  //行显示后沿
parameter  H_DISP   =  11'd1280; //行有效数据
parameter  H_FRONT  =  11'd110;  //行显示前沿
parameter  H_TOTAL  =  11'd1650; //行扫描周期

parameter  V_SYNC   =  11'd5;    //场同步
parameter  V_BACK   =  11'd20;   //场显示后沿
parameter  V_DISP   =  11'd720;  //场有效数据
parameter  V_FRONT  =  11'd5;    //场显示前沿
parameter  V_TOTAL  =  11'd750;  //场扫描周期

//reg define
reg  [10:0] cnt_h;
reg  [10:0] cnt_v;

//wire define
wire       video_en;
wire       data_req;

//*****************************************************
//**                    main code
//*****************************************************

assign video_de  = video_en;

assign video_hs  = ( cnt_h < H_SYNC ) ? 1'b0 : 1'b1;  //行同步信号赋值
assign video_vs  = ( cnt_v < V_SYNC ) ? 1'b0 : 1'b1;  //场同步信号赋值

//使能RGB数据输出
assign video_en  = (((cnt_h >= H_SYNC+H_BACK) && (cnt_h < H_SYNC+H_BACK+H_DISP))
                 &&((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
                 ?  1'b1 : 1'b0;

//RGB888数据输出
assign video_rgb = video_en ? pixel_data : 24'd0;

//请求像素点颜色数据输入
assign data_req = (((cnt_h >= H_SYNC+H_BACK-1'b1) && 
                    (cnt_h < H_SYNC+H_BACK+H_DISP-1'b1))
                  && ((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
                  ?  1'b1 : 1'b0;

//像素点坐标
assign pixel_xpos = data_req ? (cnt_h - (H_SYNC + H_BACK - 1'b1)) : 11'd0;
assign pixel_ypos = data_req ? (cnt_v - (V_SYNC + V_BACK - 1'b1)) : 11'd0;

//行计数器对像素时钟计数
always @(posedge pixel_clk ) begin
    if (!sys_rst_n)
        cnt_h <= 11'd0;
    else begin
        if(cnt_h < H_TOTAL - 1'b1)
            cnt_h <= cnt_h + 1'b1;
        else 
            cnt_h <= 11'd0;
    end
end

//场计数器对行计数
always @(posedge pixel_clk ) begin
    if (!sys_rst_n)
        cnt_v <= 11'd0;
    else if(cnt_h == H_TOTAL - 1'b1) begin
        if(cnt_v < V_TOTAL - 1'b1)
            cnt_v <= cnt_v + 1'b1;
        else 
            cnt_v <= 11'd0;
    end
end

endmodule

行场同步信号需要注意行消隐区、场消隐区的时序,在消隐区时看不到图像的。行场同步信号与VGA视频显示的时序关系见下图(图出自 VESA Monitor Timing Specifications):

20150520102535436

20150520103022855

 

每种分辨率的abcde参数都是不同的。本实验的相关参数,见parameter定义。

image.png

//1280*720 分辨率时序参数
parameter  H_SYNC   =  11'd40;   //行同步
parameter  H_BACK   =  11'd220;  //行显示后沿
parameter  H_DISP   =  11'd1280; //行有效数据
parameter  H_FRONT  =  11'd110;  //行显示前沿
parameter  H_TOTAL  =  11'd1650; //行扫描周期

parameter  V_SYNC   =  11'd5;    //场同步
parameter  V_BACK   =  11'd20;   //场显示后沿
parameter  V_DISP   =  11'd720;  //场有效数据
parameter  V_FRONT  =  11'd5;    //场显示前沿
parameter  V_TOTAL  =  11'd750;  //场扫描周期

 

4.4 dvi_transmitter_top模块:RGB888信号作为RGB2DVI模块的输入,最终转换成DVI/HDMI接口标准的TMDS串行数据输出到HDMI接口。

正点原子对该模块介绍较为详细,大家可以自行查阅,本帖不再重复。

 

 

5.实物实验


由于硬件设计原因,无法通过FPGA开发板与显示器进行EDID通信,本实验提供的程序也是强制分辨率输出,因此暂不使用示波器抓取DDC通道的EDID数据进行分析。

正点原子给出了该实验的结果见下图,可以看出彩条占满显示器。

image.png  

 

思考:如果使用大于720P(1280x720)分辨率的显示器,如1080P(1920×1080),2k( 2560*1440),ULTRA HD 4K(3840*2160,熟称假4k),4K(4096×2160,熟称真4K)等,彩条会占满屏幕?还是显示在屏幕中的一部分?

image.png   


回复

2578

帖子

0

资源

版主

这HDMI的原理讲的是明明白白的。


回复
您需要登录后才可以回帖 登录 | 注册

相关帖子
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/5 下一条

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表