第六章 图像显示处理,经典再现
15.VGA显示八种颜色的彩条
图像和视频处理可以说是FPGA中又一个经典地应用,使用FPGA做图像处理最核心的优势就在于:FPGA能进行实时流水线运算,从而达到更高的实时性,围绕着图像处理又有很多常用算法例如插值、翻转、变换、滤波、拼接等。VGA和HDMI是两个常见的视频传输接口,在这一章节中我们去熟悉VGA和HDMI成像的时序逻辑,并结合例程从入门到提高,循循渐进,带大家走进FPGA图像处理的世界!

VGA即视频图形阵列,是IBM于1987年提出的一个使用模拟信号的电脑显示标准,VGA接口即电脑采用VGA标准输出数据的专用接口。VGA接口一共有15针,分成3排,每排5个孔,作为显卡上应用最为广泛的接口类型,绝大多数显卡都带有这种接口,它传输红、绿、蓝模拟信号和同步信号(水平和垂直信号)。因为VGA接口具有成本低、结构简单、应用灵活的优点,所以广泛应用于超市、车站、飞机场等公共场所的广告宣传和提示信息显示,也可以应用于工厂车间生产过程中的操作信息显示,还能以多媒体形式应用于日常生活。
如图1所示是VGA接口的引脚定义,VGA接口是一种D型接口,采用非对称分布的 15针连接方式,一般在VGA接头上,通常会有1、5、6、10、11、15等标明每个接口的编号。VGA接口15根针,其对应接口定义如下:
1.红基色
2.绿基色
3.蓝基色
4.地址码 ID2显示器标示位2
5.自测试 一般为GND
6.红地
7.绿地
8.蓝地
9.保留
10. 数字地
11.地址码 ID0显示器标示位0
12.地址码 ID1显示器标示位1
13.行同步
14.场同步
15.地址码 ID3显示器标示位3

图1 VGA接口引脚定义
其实对于FPGA逻辑设计来说,我们关注更多的信号种类是红基色、绿基色、蓝基色、行同步和场同步信号,其他信号则是原理图和PCB设计时应该去关心的,通过控制红基色、绿基色、蓝基色、行同步和场同步信号这5个接口,即可以让显示器显示丰富多彩的颜色和各种各样的图像。
在中学的物理课中我们可能做过棱镜的试验,白光通过棱镜后被分解成多种颜色逐渐过渡的色谱,色依次为红、橙、黄、绿、青、蓝、紫,这就是可见光谱。其中人眼对红、绿、蓝最为敏感,人的眼睛就像一个三色接收器的体系,大多数的颜色可以通过红、绿、蓝三色按照不同的比例合成产生,同样绝大多数单色光也可以分解成红绿蓝三种色光,这也就是三基色的原理。三种基色是相互独立的,任何一种基色都不能由其它两种颜色合成。红绿蓝是三基色,这三种颜色合成的颜色范围最为广泛,红绿蓝三基色按照不同的比例相加合成混色称为相加混色。
颜色 |
黑 |
蓝 |
红 |
紫 |
绿 |
青 |
黄 |
白 |
R |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
G |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
B |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
表1 三基色的颜色编码
如表1所示是三基色的颜色编码,从数学上的排列组合学来说RBG一共有8组合,也就是可以产生8种颜色,但显示器显示的色彩却是非常丰富,显然要远多于8种颜色。原因便是对于显示器来说,RGB三个信号其实是模拟信号,利用电压的高低,即可以表示颜色的深浅,于是根据这个原理我们就能产生丰富的色彩。比如R=3.3V,G=0V,B=0V,则显示器会示相当鲜艳的红色。如果G和B仍然是0V,而R改为1.8V,则显示器会显示比较浅的红色。R、G、B的电压范围控制从0~3.3V,而这种任意组合就可以表示非常多的颜色了。
通过控制红绿蓝三基色,就可以控制1个像素的颜色,一幅图像是由非常多的像素组成的。举个例子对于640*480分辨率的图像,是由一行有640个且一共480行,这么多像素组合起来显示的图像,为了让显示器显示这么一幅图像,那么就要控制显示器的扫描枪一个一个像素地将颜色显示起来,像素变化的时间非常快,从而使人眼误认为所有像素是一起显示的。

图2 VGA电子束的成像原理
如上图2所示即为VGA电子束的成像原理,显示器的扫描方式则是逐行扫描是扫描从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行,电子束再回到屏幕的左边下一行的起始位置,在这期间阴极射线管CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,即形成了一帧图像,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧图像的显示。
VGA 的行时序是以像素为单位的,场时序是以行为单位的,而VGA时序对同步时间、显示后沿时间、视频有效时间和显示前沿时间也有着特定要求,常用VGA 分辨率时序参数如下表2所示。
分辨率 |
时钟 |
行时序参数/像素 |
列时序参数/行 |
||||||||
同步脉冲 |
显示后沿 |
显示区域 |
显示前沿 |
行总时序 |
同步脉冲 |
显示后沿 |
显示区域 |
行总时序 |
列总时序 |
||
640*480 @60Hz |
25.175 Mhz |
96 |
48 |
640 |
16 |
800 |
2 |
33 |
480 |
10 |
525 |
800*600 @60Hz |
40 Mhz |
128 |
88 |
800 |
40 |
1056 |
4 |
23 |
600 |
1 |
623 |
1024*768 @60Hz |
65 Mhz |
136 |
160 |
1024 |
24 |
1344 |
6 |
29 |
768 |
3 |
806 |
1280*720 @60Hz |
74.25 Mhz |
40 |
220 |
1280 |
110 |
1650 |
5 |
20 |
720 |
5 |
750 |
1280*1024 @60Hz |
108 Mhz |
112 |
248 |
1280 |
48 |
1688 |
3 |
38 |
1024 |
1 |
1066 |
1920*1080 @60Hz |
148.5 Mhz |
44 |
148 |
1920 |
88 |
2200 |
5 |
36 |
1080 |
4 |
1125 |
表2 VGA常用分辨率时序参数
如图3所示是豌豆开发板Artix7上VGA电路,VGA接口常用的是RGB565数据输出,也就是16位的高彩色VGA显示,其中红色信号占5位,绿色信号占6位,蓝色信号占5位,PCB设计上通过电阻匹配网络实现RGB数字信号到模拟信号的转换。
图3 豌豆开发板Artix7上VGA电路
如图4和图5所示是VGA行时序和场时序的示意图,举例来说对于分辨率大小是640*480的图像,640*480的规格即显示屏幕上每行有640个像素且一共有480行。

图4 VGA行时序示意图

图5 VGA场时序示意图
但需要注意的是,虽然大家看到的屏幕大小是640*480的,但是它的实际大小并不只有那么大,或者更通俗点地说,VGA扫描的范围是包含了肉眼能看到的640*480这块区域的更大区域,它会在周围一圈你看不到的区域部分进行扫描,所以在程序设计上,我们在处理扫描信号的时候要注意只有扫描到有效区域的时候才能把像素点数据传给VGA显示,如图6所示形象地描述VGA成像的显示原理。

图6 VGA成像的显示原理
在这个例程中我们使用VGA接口实现一个基本的功能,即使用1024*768像素在每秒60帧图像分辨率的情况下,通过VGA接口连接屏幕从左到右依次显示白、黄、青、绿、紫、红、蓝、黑的8种颜色的彩条。
注意到原理图中,对于RGB565成像有5根红基色、6根绿基色、5根蓝基色、行同步和场同步信号与FPGA芯片相连,通过这些信号按照上面说明的行场时序逻辑即可完成通过VGA接口传输各种各样的图像信息,如表6-3所示是video_driver模块的信号列表,在这个模块中我们去实现VGA显示白、黄、青、绿、紫、红、蓝、黑的8种颜色的彩条时序逻辑,如图7所示是VGA驱动模块的代码设计。
信号列表 |
||
信号名 |
I/O |
位宽 |
pixel_clk |
I |
1 |
rst_n |
I |
1 |
video_hs |
O |
1 |
video_vs |
O |
1 |
video_rgb |
O |
16 |
表3 video_driver模块信号列表








图7 VGA驱动模块的代码设计
如图8所示则是VGA显示八种颜色的彩条顶层文件的例化,同样地在顶层模块中,我们通过例化VGA驱动模块即可实现8种颜色彩条显示的效果,需要注意的是这里我们需要用PLL IP核倍频一个65Mhz的时钟给VGA驱动模块作为模块时钟使用,感兴趣的同学也可以手工计算下1*109ns/1344/806/60=15.3856ns,即大约折合成65Mhz的驱动时钟,下载程序后通过VGA接口连接到屏幕即可看到如图9所示的八种颜色的彩条。

图8 VGA显示八种颜色的彩条顶层文件的例化
图9 VGA显示八种颜色的彩条