离线
TA的每日心情 奋斗 2022-6-21 08:23
签到天数: 2 天
[LV.1]
有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 塞巴斯蒂安 于 2021-12-11 22:18 编辑
基于FPGA的720P HDMI显示
1.4.1 HDMI 硬件电路分析
本次设计采用了 IO 模拟的方式实现 HDMI 的功能。与采用专用 HDMI 芯片相比,此方案具有成本更低、效果不输于采用专用芯片的效果、经过测试,兼容性方面也要比专用芯片要好、最大输出图像分辨率 1080P、图像传输稳定等显著的优势。
具体硬件电路上面已经提到过了,这里简单分析一下。
图1 32 HDMI 硬件电路
从图中可以看到, HDMI 接口设计全由 IO 模拟方式实现, HDMI 的信号线 D0~D2 其实是一个差分信号,在我们程序当中体现为 TMDS 类型,因此其输入信号为串行的数字信号,内部实际上是将输入的 RGB 信号进行编码,转换为 HDMI 数据(实际我们称其为 DVI)进行输出,因此在设计中通常可以将 RGB 信号单独引出,作为 RGB 输出,用来作为双显输出使用。下表是 HDMI 接口信号的功能定义。
表1 5 HDMI 接口信号的功能定义
图1 33 HDMI 视频输出时序
1.4.2 工程文件设计
HDMI 采用和 DVI 相同癿传输原理——TMDS(Transition Minimized Differential signal),最小化传输差分信号。
TMDS 传输系统分为两个部分:发送端和接收端。 TMDS 发送端收到HDMI 接口传来的表示 RGB 信号的24 位并行数据(TMDS 对每个像素的 RGB 三原色分别按 8bit 编码,即 R信号有 8 位,G 信号有 8 位,B 信号有 8 位),然后对这些数据进行编码和并/串转换,再将表示 3 个 RGB 信号的数据分别分配到独立的传输通道发送出去。接收端接收来自发送端的串行信号,对其进行解码和串/并转换,然后发送到显示器的控制端。与此同时也接收时钟信号,以实现同步。
TMDS的原理
每一个 TMDS 链路都包括 3 个传输 RGB 信号的数据通道和 1 个传输时钟信号的通道。每一个数据通道都通过编码算法,将 8 位的视、音频数据转换成最小化传输、直流平衡的 10 位数据。这使得数据的传输和恢复更加可靠。最小化传输差分信号是通过异或及异或非等逡、逻辑算法将原始 8 位信号数据转换成 10 位,前 8 为数据由原始信号经运算后获得,第 9 位指示运算的方式,第 10 位用来对应直流平衡。
一般来说,HDMI 传输癿编码格式中要包含视频数据、控制数据和数据包(数据包中包吨音频数据和附加信息数据,例如纠错码等)。 TMDS 每个通道在传输时要包含一个 2bit 的控制数据、 8bit 的视频数据或者 4bit 的数据包即可。在 HDMI 信息传输过程中,可以分为三个阶段:视频数据传输周期、控制数据传输周期和数据岛传输周期,分别对应上述的三种数据类型。
下面介绍 TMDS 中采用的技术:
1. 传输最小化
8 位数据经过编码和直流平衡得到 10 位最小化数据,这仿佛增加了冗余位,对传输链路的带宽要求更高,但事实上,通过这种算法得到的 10 位数据在更长的同轴电缆中传输的可靠性增强了。下图是一个例子,说明对一个 8 位的并行 RED 数据编码、并/串转换。
图1 34 一个 8 位的并行 RED 数据编码、并/串转换
第一步:将 8 位并行 RED 数据发送到 TMDS 収送端;
第二步:并/串转换;
第三步:进行最小化传输处理,加上第 9 位,即编码过程。第 9 位数据称为编码位。
2. 直流平衡
直流平衡(DC-balanced)就是指在编码过程中保证信道中直流偏移为零。方法是在原来的 9 位数据癿后面加上第 10 位数据,返样,传输的数据趋于直流平衡,使信号对传输线的电磁干扰减少,提高信号传输的可靠性。
3. 差分信号
TMDS差分传动技术是一种利用2个引脚间电压差来传送信号的技术。传输数据的数值(“0”或者“1”)由两脚间电压正负极性和大小决定。即,采用 2 根线来传输信号,一根线上传输原来的信号,另一根线上传输与原来信号相反的信号。这样接收端就可以通过让一根线上的信号减去另一根线上的信号的方式来屏蔽电磁干扰,从而得到正确的信号。
图1 35 差分信号
另外,还有一个显示数据通道(DDC),是用于读取表示接收端显示器的清晰度等显示能力的扩展显示标识数据(EDID)的信号线。搭载 HDCP(High-bandwidth Digital Content Protection,高带宽数字内容保护技术)的发送、接收设备之间也利用 DDC 线进行密码键的认证。
接下来是电路设计部分,HDMI驱动部分追寻原始出处应该是迪芝伦官方,该部分代码用VHDL语言描述,为了方便移植,我将该部分代码封装成自定义IP Core,由上文可知,我们需要产生RGB888三路数据,输入给该模块,然后经过解码、串/并转换,差分输出。还需要两个时钟输入,一个是当前显示分辨率的像素时钟,一个是当前显示分辨率的像素时钟的五倍。还有一个行同步信号和场同步信号,这两个信号的产生方法和VGA是一样的,简单来说就是先产生VGA的信号,行同步信号、场同步信号RGB888的数据输入给HDMI驱动模块就可以显示了,我们要修改显示的数据,还是只需要修改VGA时序即可。
图1 36 HDMI IP核结构框图
从上面的分析可以知道,IO模拟IP,主要有两部分组成,一是VGA时序产生,另一个是HDMI IP,整个系统结构图如下:
图1 37 基于FPGA的HDMI显示结构图
核心操作就是产生VGA时序及产生需要显示的视频数据,本次设计共产生几种图像(格子、纯黑、纯白、纯蓝等),可以通过按键来进行切换显示的模式,用 LED 来指示处于何种模式,方便我们调试时分析与处理问题。
本次设计产生一个720P 的图像,故其像素时钟输入应该为H_TotalV_TotalFPS=165075060HZ=74.25MHZ。这一部分程序的编写参考的是 VGA 时序,VGA 的时序是一种 RGB传输时序,其时序图如下图所示:
图1 38 VGA时序
首先看到有 3 个矩形,第 1 个矩形是 VGA 驱动的最大部分,里面包括所有的信息,在此基础之上有 2 个同步信号,即 HSYNC 和 VSYNC(行同步和场同步), HSYNC 可以确定一行的开始和结束, VSYNC 可以确定一场的开始和结束,但是同步信号也有时间,因此就引出 Hor Sync 和 Ver Sync(行同步时间和场同步时间)。接下来就是H Back Proch 和 V Back Porch(行消隐和场消隐),消隐存在主要是为了兼容电子管屏幕设计的。
然后是第 2 个矩形,这是 Hor” Active” Video 和 Ver“Active” Video(行视频有效和场视频有效),在这个区域中是显示视频的地方。最后就是 H Front Porch 和 V Front Porch(行前肩和场前肩)。到此,一场完整视频就显示完毕了。在这里说一下第 3 个矩形,有 4 个参数 H Left Border、 H Right Border、 V Top Border 和 V Bottom Border,在不同分辨率中这4 个参数不同,在 800x600 及其以上的分辨率中这 4 个参数为 0。
在此给出一个简化的时序图,如下图所示。一行数据包括: Hor Sync(行同步)、Hor Back Porch(行消隐)、 Hor Active Video(行视频有效)和 Hor Front Porch(行前肩);一场数据包括: Ver Sync(场同步)、 Ver Back Porch(场消隐)、 Ver Active Video(场视频有效)和 Ver Front Porch(场前肩)。
图1 39 VGA时序
VGA 时序主要分为行时序和场时序,行时序是以像素为单位的,场时序是以行为单位的。 VGA 行时序对行同步时间、消隐时间、行视频有效时间和行前肩时间有特定要求,列时序也是如此,如果其中一部分时序出现问题就会造成显示出现问题。常用 VGA 分辨率时序参数如下表所示。
表1 6 VGA 常用分辨率时序参数
在这里说一下时钟频率计算,就是上文提到的第 1 个矩形和场频率有关,思考一下,很简单的。时钟频率=行最大值 x 列最大值 x 扫描频率。
代码1 1 HDMI数据产生模块
下载过程下载完成后按中间的按键显示器会切换一次显示的图像,这些都是我们在程序部分定义的图像。
1. //****************************************************************************//
2. //# @Author: RISC-V单片机中文网
3. //# @Date: 2019-11-25 21:58:59
4. //# @Last Modified by: zlk
5. //# @WeChat Official Account: OpenFPGA
6. //# @Last Modified time: 2019-12-11 20:26:10
7. //# Description:
8. //# @Modification History: 2019-10-09 22:17:36
9. //# Date By Version Change Description:
10. //# ========================================================================= #
11. //# 2019-10-09 22:17:36
12. //# ========================================================================= #
13. //# | | #
14. //# | OpenFPGA | #
15. //****************************************************************************//
16.
17. `timescale 1ns / 1ps
18.
19. //
20. module HDMI_display_Demon(
21. input clk_100M,
22. input KEY,
23.
24. output HDMI1_CLK_P,
25. output HDMI1_CLK_N,
26. output HDMI1_D2_P,
27. output HDMI1_D2_N,
28. output HDMI1_D1_P,
29. output HDMI1_D1_N,
30. output HDMI1_D0_P,
31. output HDMI1_D0_N,
32.
33. output HDMI2_CLK_P,
34. output HDMI2_CLK_N,
35. output HDMI2_D2_P,
36. output HDMI2_D2_N,
37. output HDMI2_D1_P,
38. output HDMI2_D1_N,
39. output HDMI2_D0_P,
40. output HDMI2_D0_N,
41.
42. output [3:0] LED
43. );
44.
45. wire pixclk;
46. wire[7:0] R,G,B;
47. wire HS,VS,DE;
48. assign VGA_HS = HS;
49. assign VGA_VS = VS;
50. assign VGA_D = {R[7:4],G[7:2],B[7:4]};
51. hdmi_data_gen u0_hdmi_data_gen
52. (
53. .pix_clk (pixclk),
54. .turn_mode (KEY),
55. .VGA_R (R),
56. .VGA_G (G),
57. .VGA_B (B),
58. .VGA_HS (HS),
59. .VGA_VS (VS),
60. .VGA_DE (DE),
61. .mode (LED)
62. );
63.
64. wire pixclk_X5;
65. //wire i2c_clk;
66. wire lock;
67. wire[23:0] RGB;
68. assign RGB={R,G,B};
69. hdmi_display_0 u1_hdmi_display_0
70. (
71. // .i2c_clk (i2c_clk),
72. .PXLCLK_I (pixclk),
73. .PXLCLK_5X_I (pixclk_X5),
74. .LOCKED_I (lock),
75. .RST_N (lock),
76. .VGA_RGB (RGB),
77. .VGA_HS (HS),
78. .VGA_VS (VS),
79. .VGA_DE (DE),
80. .HDMI_CLK_P (HDMI1_CLK_P),
81. .HDMI_CLK_N (HDMI1_CLK_N),
82. .HDMI_D2_P (HDMI1_D2_P),
83. .HDMI_D2_N (HDMI1_D2_N),
84. .HDMI_D1_P (HDMI1_D1_P),
85. .HDMI_D1_N (HDMI1_D1_N),
86. .HDMI_D0_P (HDMI1_D0_P),
87. .HDMI_D0_N (HDMI1_D0_N)
88. );
89.
90. hdmi_display_0 u2_hdmi_display_1
91. (
92. // .i2c_clk (i2c_clk),
93. .PXLCLK_I (pixclk),
94. .PXLCLK_5X_I (pixclk_X5),
95. .LOCKED_I (lock),
96. .RST_N (lock),
97. .VGA_RGB (RGB),
98. .VGA_HS (HS),
99. .VGA_VS (VS),
100. .VGA_DE (DE),
101. .HDMI_CLK_P (HDMI2_CLK_P),
102. .HDMI_CLK_N (HDMI2_CLK_N),
103. .HDMI_D2_P (HDMI2_D2_P),
104. .HDMI_D2_N (HDMI2_D2_N),
105. .HDMI_D1_P (HDMI2_D1_P),
106. .HDMI_D1_N (HDMI2_D1_N),
107. .HDMI_D0_P (HDMI2_D0_P),
108. .HDMI_D0_N (HDMI2_D0_N)
109. );
110.
111. clk_wiz_0 u3_clk
112. (
113. .clk_in1 (clk_100M),
114. .resetn (1'b1),
115. .clk_out1 (pixclk),
116. .clk_out2 (pixclk_X5),
117. // .clk_out3 (i2c_clk),
118. .locked (lock)
119. );
120. endmodule 复制代码 下载过程下载完成后按中间的按键显示器会切换一次显示的图像,这些都是我们在程序部分定义的图像。
图1 40 实验结果
完
上一篇:
优秀的 Verilog/FPGA开源项目介绍(八)- HDMI 下一篇:
Xilinx 7系列FPGA入门级图像处理-完整版V1
RISCV作者优文