7. vga显示器驱动设计与验证

图像显示设备在日常生活中随处可见,例如家庭电视机、计算机显示屏幕等,这些设备之所以能够显示我们需要的数据图像信息,归功于视频传输接口。常见的视频传输接口有三种:VGA接口、DVI接口和HDMI接口,目前的显示设备都配有这三种视频传输接口。

三类视频接口的发展历程为VGA→DVI→HDMI。其中VGA接口出现最早,只能传输模拟图像信号; 随后出现的DVI接口又分为三类:DVI-A、DVI-D、DVI-I,分别可传输纯模拟图像信号、纯数字图像信号和兼容模拟、数字图像信号;最后的HDMI在传输数字图像信号的基础上又可以传输音频信号。

因为FPGA在图像传输、处理方面有不可或缺的作用,所以学习掌握视频传输的相关知识是的非常有必要的,本章节我们就从最简单的VGA接口开始着手学习,了解掌握VGA接口的相关知识,为后续其他视频接口的学习做铺垫。

本章节读者要学习掌握VGA视频接口的基本知识和概念,了解掌握VGA接口时序。根据所学知识设计一个VGA显示控制器,并在VGA显示器上进行多色彩条显示。

7.1. 理论学习

实战之前的理论学习是必不可少的,在本小结中,我们针对VGA的基本知识和概念做一个系统性的介绍,希望读者能够理解掌握,这对后面的实战大有裨益。

7.1.1. VGA简介

VGA,英文全称“Video Graphics Array”,译为视频图形阵列,是一种使用模拟信号进行视频传输的标准协议,由IBM公司于1987年推出,因其分辨率高、显示速度快、颜色丰富等优点,广泛应用于彩色显示器领域。由于VGA接口体积较大,与追求小巧便携的笔记本电脑背道而驰,在笔记本电脑领域,V GA接口已被逐渐淘汰,但对于体积较大的台式机,这种情况并未发生,虽然VGA标准在当前个人电脑市场中已经过时,但因其在显示标准中的重要性和良好的兼容性,VGA仍然是最多制造商所共同支持的一个标准,个人电脑在加载自己独特驱动程序之前,都必须支持VGA的标准。

早期的CRT显示器只能接收模拟信号,不能接收数字信号,计算机内部显卡将数字信号转换成模拟信号,通过VGA接口传给VGA显示器,虽然现如今许多种类的显示器可以直接接收数字信号,但为了兼容显卡的VGA接口,大都支持VGA标准。

7.1.2. VGA接口及引脚定义

在最初的应用中,VGA接口常用于计算机与VGA显示器之间的图像传输,在台式计算机、旧式笔记本电脑和VGA显示器上一般会有标准的VGA接口。VGA接口,具体见图 36‑1。

VGA002

图 36‑1 VGA接口

VGA接口中以针式引出信号线的称为公头,以孔式引出信号线的称为母头。在计算机和VGA显示器上一般引出母头接口,使用两头均为公头的VGA连接线将计算机与VGA显示器连接起来,两者图像传输时,使用的是VGA图像传输标准,该标准的具体内容在后面小节会详细说明。VGA公头、母头接口和VGA连接线,具体见图 36‑2及图 36‑3。

VGA003

图 36‑2 VGA接口 (左侧为母头、右侧为公头)

VGA004

图 36‑3 VGA连接线

虽然已经见识过VGA接口的外观,但对接口各引脚功能并没有进一步的认识,下面,我们结合VGA接口引脚图和各引脚定义表格,对VGA接口各引脚做一下简单介绍,具体见图 36‑4及表格 36‑1。

VGA005

图 36‑4 VGA接口管脚图

表格 36‑1 VGA引脚定义

引脚

定义

引脚

定义

1

红基色(RED)

9

保留(各厂家定义不同)

2

绿基色(GREEN)

10

数字地(GND)

3

蓝基色(BLUE)

11

地址码0(ID BIT0)

4

地址码2(ID BIT2)

12

地址码1(ID BIT1)

5

自测试(各厂家定义不同)

13

行同步(HSYNC)

6

红色地(RGND)

14

场同步(VSYNC)

7

绿色地(GGND)

15

地址码3(ID BIT3)

8

蓝色地(BGND)

结合图 36‑4和表格 36‑1, VGA接口引脚简介如下:

由图可知,VGA接口共有15个引脚,分为3排,每排各5个, 按照自上而下、从左向右的顺序排列。其中第一排的引脚1、2、3和第三排的引脚13、14最为重要。

VGA使用工业界通用的RGB色彩模式作为色彩显示标准,这种色彩显示标准是根据三原色中红色、绿色、蓝色所占比例多少及三原色之间的相互叠加得到各式各样的颜色。引脚1红基色(RED)、引脚2绿基色(GREEN)、引脚3蓝基色(BLUE)就是VGA接口中负责传输三原色的传输通道。要注意的是,这3个引脚传输的 是模拟信号。

引脚13行同步信号(HSYNC)、引脚14场同步信号(VSYNC),这两个信号,是在VGA显示图像时,负责同步图像色彩信息的同步信号。在后面小节中,我们会对这两个信号进行详细讲解。

引脚5、9:这两个引脚分别是VGA接口的自测试和预留接口,不过不同生产厂家对这两个接口定义不同,在接线时,两引脚可悬空不接。

引脚4、11、12、15:这四个是VGA接口的地址码,可以悬空不接。

引脚6、7、8、10:这四个引脚接地,无需解释。

7.1.3. VGA显示原理

VGA显示器显示图像,并不是直接让图像在显示器上显示出来,而是采用扫描的方式,将构成图像的像素点,在行同步信号和场同步信号的同步下,按照从上到下、由左到右的顺序扫描到显示屏上。VGA显示器扫描方式,具体见图 36‑5。

VGA006

图 36‑5 VGA显示器扫描方式示意图

结合VGA显示器扫描方式示意图,我们简要说明一下VGA显示器的扫描规律。

  1. 在行、场同步信号的同步作用下,扫描坐标定位到左上角第一个像素点坐标;

  2. 自左上角(第一行)第一个像素点坐标,逐个像素点向右扫描(图中第一个水平方向箭头);

  3. 扫描到第一行最后一个数据,一行图像扫描完成,进行图像消隐,扫描坐标自第一行行尾转移到第二行行首(图中第一条虚线);

  4. 重复若干次扫描至最后一行行尾,一帧图像扫描完成,进行图像消隐,扫描坐标跳转回到左上角第一行行首(图中对角线箭头),开始下一帧图像的扫描。

在扫描的过程中会对每一个像素点进行单独赋值,使每个像素点显示对应色彩信息,当一帧图像扫描结束后,开始下一帧图像的扫描,循环往复,当扫描速度足够快,加之人眼的视觉暂留特性,我们会看到一幅完整的图片,而不是一个个闪烁的像素点。这就是VGA显示的原理。

7.1.4. VGA时序标准

为了适应匹配不同厂家的VGA显示器,VGA视频传输接口有自己的一套VGA时序标准,只有遵循VGA的时序标准,才能正确的进行图像信息的显示。在这里我们以VESA VGA时序标准为例,为大家讲解一下VGA时序标准,具体见图 36‑6。

VGA007

图 36‑6 VESA VGA时序标准图

由VESA VGA时序标准图可知,VGA时序由两部分构成,行同步时序与场同步时序,为了方便读者理解,我们将行同步时序与场同步时序分开讲解。

  1. 行同步时序,具体见图 36‑7。

VGA008

图 36‑7 VESA标准下的行同步时序图

除去我们不需要关心的参数,我们对行同步时序图进行了精简,以便读者更好地理解,如图 36‑7所示。

图中Video代表传输的图像信息,HSync表示行同步信号。HSync自上升沿起到下一个上升沿止为一个完整周期,我们称之为行扫描周期。

一个完整的行扫描周期,包含6部分:Sync(同步)、Back Porch(后沿)、Left Border(左边框)、“Addressable” Video(有效图像)、Right Border(右边框)、Front Porch(前沿),这6部分的基本单位是pixel(像素),即一个像素时钟周期。

在一个完整的行扫描周期中,Video图像信息在HSync行同步信号的同步下完成一行图像的扫描显示,Video图像信息只有在“Addressable” Video(有效图像)阶段,图像信息有效,其他阶段图像信息无效。

HSync行同步信号在Sync(同步)阶段,维持高电平,其他阶段均保持低电平,在下一个行扫描周期的Sync(同步)阶段,HSync行扫描信号会再次拉高,其他阶段拉低,周而复始。

  1. 场同步时序,具体见图 36‑8。

VGA009

图 36‑8 VESA标准下的场同步时序图

理解了行同步时序,场同步时序就更容易理解了,两者相类似,如图 36‑8所示,图中Video代表传输的图像信息,VSync表示场同步信号,VSync自上升沿起到下一个上升沿止为一个完整周期,我们称之为场扫描周期。

一个完整的场扫描周期,也包含6部分:Sync(同步)、Back Porch(后沿)、Top Border(上边框)、“Addressable” Video(有效图像)、Bottom Border(底边框)、Front Porch(前沿),与行同步信号不同的是,这6部分的基本单位是line(行),即一个完整的行扫描周期。

在一个完整的场扫描周期中,Video图像信息在HSync(行同步信号)和VSync(场同步信号)的共同作用下完成一帧图像的显示,Video图像信息只有在“Addressable” Video(有效图像)阶段,图像信息有效,其他阶段图像信息无效。

VSync行同步信号在Sync(同步)阶段,维持高电平,其他阶段均保持低电平,完成一个场扫描周期后,进入下一帧图像的扫描。

综上所述,将行同步时序图与场同步时序图结合起来就构成了VGA时序图,具体见图 36‑9。

VGA010

图 36‑9 VGA时序图

图中的红色区域表示在一个完整的行扫描周期中,Video图像信息只在此区域有效,黄色区域表示在一个完整的场扫描周期中,Video图像信息只在此区域有效,两者相交的橙色区域,就是VGA图像的最终显示区域。

以上就是对VGA时序的讲解,读者务必理解掌握,这对接下来的学习至关重要。

7.1.5. VGA显示模式及相关参数

行同步时序可分为6个阶段,对于这6个阶段的参数是有严格定义的,参数配置不正确,VGA不能正常显示。VGA显示器可支持多种分辨率,不同分辨率对应个阶段的参数是不同的,常用VGA分辨率时序参数,具体见图 36‑10。

VGA011

图 36‑10 VGA不同分辨率相关参数

下面我们以经典VGA显示模式640x480@60为例,为读者讲解一下VGA显示的相关参数。

  1. 显示模式:640x480@60

640x480是指VGA的分辨率,640是指有效显示图像每一行有640个像素点,480是指每一帧图像有480行,640 * 480 = 307200 ≈ 300000,每一帧图片包含约30万个像素点,之前某品牌手机广告上所说的30万像素指的就是这个;@60是指VGA显示图像的刷新频率,60就是指VGA显示器每秒刷新图像60次,即每秒钟需要显示60帧图像。

  1. 时钟(MHz):25.175MHz

这是VGA显示的工作时钟,像素点扫描频率。

  1. 行同步信号时序(像素)、场同步信号时序(行数)

行同步信号时序分为6段,Sync(同步)、Back Porch(后沿)、Left Border(左边框)、“Addressable” Video(有效图像)、Right Border(右边框)、Front Porch(前沿),这6段构成一个行扫描周期,单位为像素时钟周期。

同步阶段,参数为96,指在行时序的同步阶段,行同步信号需要保持96个像素时钟周期的高电平, 其他几个阶段与此相似。

场同步信号时序与其类似,只是单位不再是像素时钟周期,而是一个完整的行扫描周期,在此不再赘述。

在这里,我们看回图 36‑10,由图可知,即使VGA显示分辨率相同,但刷新频率不同的话,相关参数也存在差异,如640x480@60、640x480@75,这两个显示模式虽然具有相同的分辨率,但是640x480@75的刷新频率更快,所以像素时钟更快,时序参数也有区别。

下面我们以显示模式640x480@60、640x480@75为例,学习一下时钟频率的计算方法。

行扫描周期 * 场扫描周期 * 刷新频率 = 时钟频率

640x480@60

行扫描周期:800(像素),场扫描周期:525(行扫描周期) 刷新频率:60Hz

800 * 525 * 60 = 25,200,000 ≈ 25.175MHz (误差忽略不计)

640x480@75

行扫描周期:840(像素) 场扫描周期:500(行扫描周期) 刷新频率:75Hz

840 * 500 * 75 = 31,500,000 = 31.5MHz

在计算时钟频率时,读者要谨记一点,要使用行扫描周期和场扫描周期的参数进行计算,不能使用有效图像的参数进行计算,虽然在有效图像外的其他阶段图像信息均无效,但图像无效阶段的扫描也花费了扫描时间。

以上就是对VGA显示标准中分辨率相关参数的讲解,在编写VGA驱动时,我们要根据VGA显示模式的不同调整相关参数,只有这样VGA图像才能正常显示。

7.2. 实战演练

在上一小节中,我们对VGA接口及接口定义、VGA显示原理、时序标准、显示模式及相关参数做了详细讲解,望读者认真揣摩,理解掌握,这些理论基础对后面的实战至关重要,纸上谈兵之后,我们进入实战演练,在实战中加深对概念的理解。

7.2.1. 实验目标

实验目标:编写VGA驱动,使用FPGA开发板驱动VGA显示器显示十色等宽彩条, VGA显示模式为640x480@60。

实验效果,具体见图 36‑11。

VGA012

图 36‑11 VGA彩条实验效果图

7.2.2. 硬件资源

在前文中我们提到,VGA只能识别模拟信号,而FPGA输出的图像信息为数字信号,在VGA的图像显示中,想要将数字图像信号转换为VGA能够识别的模拟信号有两种方法。其一,使用专业的转换芯片,如常用的转换芯片AD7123,这种方式更为稳定,但成本稍高;其二,使用权电阻网络实现数模转换,这种方式可以有效降低 成本,征途Pro就是使用这种方法。

征途Pro开发板VGA部分原理图,如图 36‑12所示。

VGA013

图 36‑12 VGA部分原理图

由图可知,征途Pro使用的RGB565图像模式,位宽为16bit,高5位表示红色,低5位表示蓝色,中间6位表示绿色。根据位宽不同,RGB图形格式还包括RGB232、RGB888等,数据位宽越大,表示颜色种类越多,显示图像越细腻。

VGA_D[15:0]表示FPGA传入权电阻网络的数字图像信号,经过权电阻网络的数模转换,生成能够被VGA识别的模拟图像信号VGA_R、VGA_G、VGA_B。

这三路模拟信号的电压范围为0V ~ 0.714V,0V代表无色,0.714V代表满色,电压高低由输入的数字信号决定。输入的R、G、B数字信号不同,输出的三原色红、绿、蓝电压不同,颜色深浅不同,三原色相结合可以产生多种颜色。

7.2.3. 程序设计

硬件资源介绍完毕,我们开始实验工程的程序设计。在本小节,我们采用先整体概括,再局部说明的方式对实验工程的各个模块进行讲解,详细内容如下。

7.2.3.1. 整体说明

注:本实验选用经典VGA显示模式640x480@60,理论时钟频率应为25.175MHz,为了便于时钟生成,我们使用25MHz的时钟代替25.175MHz的时钟,不会对实验造成影响,读者无需担心;接下来讲解中的相关参数与此显示模式相对应,事先告知,后续不再声明。

在本小节,我们先要对整个实验工程有一个整体认识,首先来看一下VGA彩条显示实验工程的整体框图,具体见图 36‑13。

VGA014

图 36‑13 VGA彩条显示实验整体框图

由上图可知,本实验工程包括4个模块,各模块简介,具体见表格 36‑2。

表格 36‑2 VGA彩条显示工程模块简介

模块名称

功能描述

vga_colorbar

顶层模块

clk_gen

时钟生成模块,生成VGA驱动时钟

vga_ctrl

VGA时序控制模块,驱动VGA图像显示

vga_pic

图像数据生成模块,生成VGA待显示图像

结合图 36‑13和表格 36‑2,我们来说一下VGA彩条显示工程的工作流程。

  1. 系统上电后,板卡传入系统时钟(sys_clk)和复位信号(sys_rst_n)到顶层模块;

  2. 系统时钟由顶层模块传入时钟生成模块(clk_gen),分频产生VGA工作时钟(vga_clk),作为图像数据生成模块(vga_pic)和VGA时序控制模块(vga_ctrl)的工作时钟;

  3. 图像数据生成模块以VGA时序控制模块传入的像素点坐标(pix_x,pix_y)为约束条件,生成待显示彩条图像的色彩信息(pix_data);

  4. 图像数据生成模块生成的彩条图像色彩信息传入VGA时序控制模块,在模块内部使用使能信号滤除掉非图像显示有效区域的图像数据,产生RGB色彩信息(rgb),在行、场同步信号(hsync、vsync)的同步作用下,将RGB色彩信息扫描显示到VGA显示器,显示出彩条图像。

本小节以全局视角,对整个实验工程进行了概括,对各子功能模块做了简单介绍,简要说明了实验工程的工作流程,相信读者对实验工程有了整体了解。在后文中,我们将采取分述的方式,从设计、实现、仿真验证等方面,对各子功能模块进行详细介绍。

在此给读者留下一个思考问题:

思考题:实验工程中图像数据生成模块vga_pic,接收VGA时序控制模块vga_ctrl传入的像素点坐标(pix_x,pix_y)信号,并以此为约束条件产生并回传像素点色彩信息pix_data,为何VGA时序控制模块不直接在内部生成pix_data信号,而要多此一举,设计独立模块产生pix_data 信号?

读者请先独立思考该问题,在后文中我们会对该问题进行讲解。

7.2.3.2. 时钟生成模块

本小节先来介绍一下时钟生成模块(clk_gen)。

由上文可知,本次实验工程中,VGA显示模式为640*480@60,时钟频率为25MHz,而板卡晶振传入时钟频率为50MHz。时钟生成模块的作用就是将50MHz晶振时钟分频为25MHz的VGA工作时钟。

实现时钟分频有两种方法;一是使用IP核,可通过配置相关参数分频或倍频产生多种频率的时钟信号;二是编写逻辑代码 实现时钟分频。这两种方法在前面章节均有详细介绍,读者若有遗忘,可返回查阅。

本模块采用第一种方法,调用IP核 实现时钟分频。时钟生成模块框图,具体见图 36‑14。

VGA015

图 36‑14 时钟生成模块框图

由图可知,本模块包括2路输入信号和2路输出信号。对模块输入输出信号的功能描述,具体见表格 36‑3。

表格 36‑3 时钟生成模块输入输出信号功能描述

信号

位宽

类型

功能描述

areset

1Bit

Input

复位信号,高电平有效

inclk0

1Bit

Input

50MHz晶振时钟输入

c0

1Bit

Output

输出分频后25MHzVGA工作时钟

locked

1Bit

Output

输出稳定时钟信号的指示信号

四路输入输出信号中,需要重点强调的信号有两路,输入复位信号areset和输出时钟锁定信号locked。

输入复位信号areset为整个PLL IP核的复位信号,要注意的是,该复位信号为高电平有效,故将系统复位信号sys_rst_n取反输入;

输出时钟锁定信号locked,作为输出稳定时钟信号的指示信号,因为IP核分频产生的分频时钟在信号初始位置会出现震荡,在时钟震荡过程中,locked保持低电平;震荡结束,分频时钟稳定后,locked信号赋值高电平,表示输出时钟稳定且可被其他模块使用。

因为本模块是调用内部IP核生成,无需进行波形图绘制和仿真验证。

7.2.3.3. VGA时序控制模块

本小节中我们开始VGA时序控制模块(vga_ctrl)的介绍,接下来我们会通过模块框图、波形图绘制、代码编写、仿真分析这几个部分,对本模块的设计、实现、仿真验证过程做一下详细介绍。

模块框图

VGA时序控制模块,作用是驱动VGA显示器,将输入模块的彩条图形像素点信息,按照VGA时序扫描显示到VGA显示器上。模块框图,具体见图 36‑15。

VGA016

图 36‑15 VGA时序控制模块框图

由图 36‑15可知,VGA时序控制模块包含3路输入、5路输出,共8路信号,输入输出信号简介,具体见表格 36‑4。

表格 36‑4 VGA时序控制模块输入输出信号信号功能描述

信号

位宽

类型

功能描述

vga_clk

1Bit

Input

工作时钟,频率25MHz

sys_rst_n

1Bit

Input

复位信号,低电平有效

pi_data

16Bit

Input

彩条图像像素点色彩信息

pix_x

10Bit

Output

VGA有效显示区域像素点X轴坐标

pix_y

10Bit

Output

VGA有效显示区域像素点Y轴坐标

hsync

1Bit

Output

行同步信号

vsync

1Bit

Output

场同步信号

rgb

16Bit

Output

RGB图像色彩信息

输入信号中,时钟信号vga_clk,频率为25MHz,为VGA显示器工作时钟,由分频模块产生并输入;复位信号sys_rst_n为顶层模块的rst_n信号输入,低电平有效;pix_data为彩条图像像素点色彩信息,由图像数据生成模块产生并传入,在VGA有效图像显示区域赋值给信号RGB图像色彩信息(rg b)。

输出信号(pix_x,pix_y)为VGA有效显示区域像素点坐标,由VGA时序控制模块生成并传入图像数据生成模块;hsync、vsync为VGA行、场同步信号 ,通过VGA接口传输给VGA显示器;rgb为显示器要显示的图像色彩信息,传输给VGA显示器。

波形图绘制

在模块框图部分,我们对VGA时序控制模块的具体功能做了说明,对输入输出信号做了简单介绍,那么如何利用模块输入信号实现模块功能,输出我们想要得到的数据信号呢?在波形图绘制部分,我们会通过绘制波形图,对各信号做详细讲解,带领读者学习掌握模块功能的实现方法。

VGA时序控制模块参考波形图,具体见图 36‑16。

VGA017

图 36‑16 VGA时序控制模块参考波形图

图 36‑16是我们最终绘制生成的VGA时序控制模块参考波形图,下面我们分部分讲解一下波形图绘制的具体思路。

第一部分:行同步信号(hsync)、场同步信号(vsync)的波形绘制思路

VGA显示器想要正确显示图像,行、场同步信号必不可少,前面小节我们对行、场同步信号的时序进行了详细讲解,由时序图可知,行同步信号为周期性信号,信号变化周期为完整的行扫描周期,信号在同步阶段保持高电平,在其他阶段保持低电平,那么如何实现行同步信号的周期性变化呢?

我们想到了前文学过的计数器,因为一个完整行扫描周期为800个像素时钟周期(640*480@60),我们可以利用计数器以像素时钟周期进行计数,每一个像素时钟周期自加1,计数范围为0-799,共计数800次,与完整行扫描周期数相吻合。只要在行同步阶段(计数范围0-95)赋值hsync信号为高电平,其他阶 段为低电平,就可以实现符合时序要求的行同步信号hsync。根据此设计思路,声明并绘制行扫描周期计数器cnt_h、行同步信号hsync信号波形如下:

VGA018

图 36‑17 cnt_h、hsync信号波形图

同理,参考行同步信号波形的绘制思路,我们可以进行场同步信号波形的绘制,不过读者要注意的是,场扫描周期单位不是像素时钟周期,而是完整的行扫描周期, 所以要添加场扫描周期计数器对行扫描周期进行计数,声明并绘制场扫描周期计数器cnt_v、场同步信号vsync信号波形如下:

VGA019

图 36‑18 cnt_v、vsync信号波形图

第二部分:图像显示有效信号(rgb_valid)波形绘制思路

由上文可知,VGA只有在有效的显示区域内送入图像数据,图像才会被正确显示,那么在什么时候可以送入图像数据呢?

我们可以声明一个有效信号,在图像有效显示区域赋值高电平,在非图像有效显示区域赋值低电平,以此信号为约束条件,控制图像信号的正确输入,定义此信号为图像显示有效信号(rgb_valid)。

信号已经声明,那么问题来了,如何控制其电平变化,实现预期波形呢?

这里我们可以利用上一部分声明的cnt_h、cnt_v两个计数器,以其为约束条件,当两个计数器计数到图像有效显示区域时,rgb_valid赋值高电平,否则赋值低电平。绘制图像显示有效信号(rgb_valid)波形如下:

VGA020

图 36‑19 rgb_valid信号波形图

第三部分:图像信息请求信号(pix_data_req)、VGA有效显示区域像素点坐标(pix_x,pix_y)波形绘制思路

在前面小节,我们为读者留下一个思考题,在此我们对问题进行解答。

思考题:实验工程中图像数据生成模块vga_pic,接收VGA时序控制模块vga_ctrl传入的像素点坐标(pix_x,pix_y)信号,并以此为约束条件产生并回传像素点色彩信息pix_data,为何VGA时序控制模块不直接在内部生成pix_data信号,而要多此一举,设计独立模块产生pix_data 信号?

因为我们在对功能模块进行设计时,不仅要考虑到模块功能的实现,模块的复用性也是考虑内容之一。在本实验工程中,如果VGA时序控制模块直接在内部生成pix_data信号,那么VGA时序控制模块只能显示彩条图像,想要显示其他图像需要重新编写代码或做较大改动,模块复用性大大降低,如果将图像数据生成功能独立出来 ,当想要显示其他图像时,只需要将要显示图像数据直接输入VGA时序控制模块即可,模块改动较小或不需要改动,模块复用性提高。

为了提高模块复用性,我们将图像数据生成功能独立出来,设计为图像数据生成模块vga_pic,虽然模块复用性提高,但这样就产生一个问题,怎样保证pix_data传输的图像数据与VGA时序相吻合呢?

结合之前学习的知识,我们知道只有在VGA有效显示区域,pix_data传输的图像数据才会传输给VGA显示器,那么我们可以只在VGA有效显示区域对pix_data进行赋值,如何实现这一想法呢?

我们可以使用cnt_h、cnt_v信号来确定VGA有效显示区域,将有效显示区域使用坐标法表示,针对不同坐标点对pix_data进行赋值,所以我们声明VGA有效显示区域像素点坐标(pix_x,pix_y)。

上面两个问题解决了,新的问题又来了,VGA有效显示区域为640*480,如何使像素点坐标(pix_x,pix_y)实现(0,0) – (640,480)的坐标计数?

读者可能会想到使用已经声明的图像显示有效信号(rgb_valid),但在此处不能使用该信号。

因为本次实验是VGA多色彩条的显示,图像数据生成模块vga_pic需要以坐标(pix_x,pix_y)为约束条件对pix_data信号进行赋值,只能使用时序逻辑的赋值方式,那么pix_data的赋值时刻会滞后条件满足时刻一个时钟周期,显示图像会出现问题。

为了解决这一问题,我们需要声明新的图像数据请求信号pix_data_req,该信号要超前图像显示有效信号(rgb_valid)一个时钟周期,以抵消pix_data时序逻辑赋值带来的问题。

综上所述,我们需要声明图像信息请求信号pix_data_req、VGA有效显示区域像素点坐标(pix_x,pix_y)这三路信号来解决之前提到的若干问题。对于pix_data_req信号的电平控制可参考rgb_valid信号的控制方式,以cnt_h、cnt_v信号为约束条件;坐标(pix_x,pix _y)则以新声明的pix_data_req信号为约束条件控制生成,三路信号绘制波形图如下:

VGA021

图 36‑20 pix_data_req、 pix_x、pix_y信号波形图

第四部分:RGB色彩信息(rgb)波形绘制思路

这一部分就比较简单了,VGA图像显示是在行、场同步信号的作用下,将图像色彩信息以扫描显示的方式显示出来,所以RGB色彩信息必不可少,只要在有效显示区域写入正确图像数据即可。信号rgb绘制波形如下:

VGA022

图 36‑21 rgb信号波形图

各信号波形绘制思路讲解完毕,将所有信号整合后,就是本小节开始部分展示的模块波形图。

本设计思路只做参考,并非唯一方法,读者可利用所学知识,按照自己思路进行设计。

代码编写

参照绘制波形图,编写模块参考代码。模块参考代码,具体见代码清单 36‑1。

代码清单 36‑1 VGA时序控制模块参考代码(vga_ctrl.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
module vga_ctrl(
input wire vga_clk , //输入工作时钟,频率25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [15:0] pix_data , //输入像素点色彩信息

output wire [9:0] pix_x , //输出有效显示区域像素点X轴坐标
output wire [9:0] pix_y , //输出有效显示区域像素点Y轴坐标
output wire hsync , //输出行同步信号
output wire vsync , //输出场同步信号
 output wire [15:0] rgb //输出像素点色彩信息

 );

 ////
 //\* Parameter and Internal Signal \//
 ////

 //parameter define
 parameter H_SYNC = 10'd96 , //行同步
 H_BACK = 10'd40 , //行时序后沿
 H_LEFT = 10'd8 , //行时序左边框
 H_VALID = 10'd640 , //行有效数据
 H_RIGHT = 10'd8 , //行时序右边框
 H_FRONT = 10'd8 , //行时序前沿
 H_TOTAL = 10'd800 ; //行扫描周期
 parameter V_SYNC = 10'd2 , //场同步
 V_BACK = 10'd25 , //场时序后沿
 V_TOP = 10'd8 , //场时序上边框
 V_VALID = 10'd480 , //场有效数据
 V_BOTTOM = 10'd8 , //场时序下边框
 V_FRONT = 10'd2 , //场时序前沿
 V_TOTAL = 10'd525 ; //场扫描周期

 //wire define
 wire rgb_valid ; //VGA有效显示区域
 wire pix_data_req ; //像素点色彩信息请求信号

 //reg define
 reg [9:0] cnt_h ; //行同步信号计数器
 reg [9:0] cnt_v ; //场同步信号计数器

 ////
 //\* Main Code \//
 ////

 //cnt_h:行同步信号计数器
 always@(posedge vga_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_h <= 10'd0 ;
 else if(cnt_h == H_TOTAL - 1'd1)
 cnt_h <= 10'd0 ;
 else
 cnt_h <= cnt_h + 1'd1 ;

 //hsync:行同步信号
 assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;

 //cnt_v:场同步信号计数器
 always@(posedge vga_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_v <= 10'd0 ;
 else if((cnt_v == V_TOTAL - 1'd1) && (cnt_h == H_TOTAL-1'd1))
 cnt_v <= 10'd0 ;
 else if(cnt_h == H_TOTAL - 1'd1)
 cnt_v <= cnt_v + 1'd1 ;
 else
 cnt_v <= cnt_v ;

 //vsync:场同步信号
 assign vsync = (cnt_v <= V_SYNC - 1'd1) ? 1'b1 : 1'b0 ;

 //rgb_valid:VGA有效显示区域
 assign rgb_valid = (((cnt_h >= H_SYNC + H_BACK + H_LEFT)
 && (cnt_h < H_SYNC + H_BACK + H_LEFT + H_VALID))
 &&((cnt_v >= V_SYNC + V_BACK + V_TOP)
 && (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
 ? 1'b1 : 1'b0;

 //pix_data_req:像素点色彩信息请求信号,超前rgb_valid信号一个时钟周期
 assign pix_data_req = (((cnt_h >= H_SYNC + H_BACK + H_LEFT - 1'b1)
 && (cnt_h<H_SYNC + H_BACK + H_LEFT + H_VALID - 1'b1))
 &&((cnt_v >= V_SYNC + V_BACK + V_TOP)
 && (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
 ? 1'b1 : 1'b0;

 //pix_x,pix_y:VGA有效显示区域像素点坐标
 assign pix_x = (pix_data_req == 1'b1)
 ? (cnt_h - (H_SYNC + H_BACK + H_LEFT - 1'b1)) : 10'h3ff;
 assign pix_y = (pix_data_req == 1'b1)
 ? (cnt_v - (V_SYNC + V_BACK + V_TOP)) : 10'h3ff;

 //rgb:输出像素点色彩信息
 assign rgb = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;

 endmodule

模块参考代码是参照绘制波形图进行编写的,在波形图绘制小节已经对模块各信号有了详细的说明,本小节不再过多叙述。

仿真代码编写

编写仿真代码,对VGA时序控制模块参考代码进行仿真验证。仿真参考代码,具体见代码清单 36‑2。

代码清单 36‑2 VGA时序控制模块仿真参考代码(tb_vga_ctrl.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
\`timescale 1ns/1ns
module tb_vga_ctrl();
////
//\* Parameter and Internal Signal \//
////
//wire define
wire locked ;
wire rst_n ;
wire vga_clk ;

 //reg define
 reg sys_clk ;
 reg sys_rst_n ;
 reg [15:0] pix_data ;

 ////
 //\* Clk And Rst \//
 ////

 //sys_clk,sys_rst_n初始赋值
 initial
 begin
 sys_clk = 1'b1;
 sys_rst_n <= 1'b0;
 #200
 sys_rst_n <= 1'b1;
 end

 //sys_clk:产生时钟
 always #10 sys_clk = ~sys_clk;

 //rst_n:VGA模块复位信号
 assign rst_n = (sys_rst_n & locked);

 //pix_data:输入像素点色彩信息
 always@(posedge vga_clk or negedge rst_n)
 if(rst_n == 1'b0)
 pix_data <= 16'h0000;
 else
 pix_data <= 16'hffff;

 ////
 //\* Instantiation \//
 ////

 //------------- clk_gen_inst -------------
 clk_gen clk_gen_inst
 (
 .areset (~sys_rst_n ), //输入复位信号,高电平有效,1bit
 .inclk0 (sys_clk ), //输入50MHz晶振时钟,1bit
 .c0 (vga_clk ), //输出VGA工作时钟,频率25MHz,1bit
 .locked (locked ) //输出pll locked信号,1bit
 );

 //------------- vga_ctrl_inst -------------
 vga_ctrl vga_ctrl_inst
 (
 .vga_clk (vga_clk ), //输入工作时钟,频率25MHz,1bit
 .sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
 .pix_data (pix_data ), //输入像素点色彩信息,16bit

 .pix_x (pix_x ), //输出VGA有效显示区域像素点X轴坐标,10bit
 .pix_y (pix_y ), //输出VGA有效显示区域像素点Y轴坐标,10bit
 .hsync (hsync ), //输出行同步信号,1bit
 .vsync (vsync ), //输出场同步信号,1bit
 .rgb (rgb ) //输出像素点色彩信息,16bit
 );

 endmodule

仿真波形分析

配置好仿真文件,使用ModelSim对参考代码进行仿真,仿真结果如下。

VGA023

图 36‑22 VGA时序控制模块整体仿真波形图

图 36‑22为模块传输一帧图像的仿真波形图,因为信号线过于密集,不便讲解说明,我们将列出各信号局部截图进行讲解。

VGA024

图 36‑23 局部仿真波形图(一)

VGA025

图 36‑24 局部仿真波形图(二)

VGA026

图 36‑25 局部仿真波形图(三)

由图 36‑23、图 36‑24、图 36‑25可知,行扫描周期计数器cnt_h在计数范围0-799循环计数,计数周期为像素时钟周期;场扫描周期计数器在计数范围0-524循环计数,计数周期为完整的行扫描周期。

VGA027

图 36‑26 局部仿真波形图(四)

VGA028

图 36‑27 局部仿真波形图(五)

VGA029

图 36‑28 局部仿真波形图(六)

由图 36‑26、图 36‑27、图 36‑28可知,rgb_valid信号只有在图像显示有效区域保持高电平,其他区域为低电平;pix_data_req信号超前rgb_valid信号一个时钟周期;pix_x信号在图像显示有效区域循环计数,计数周期为像素时钟周期,计数范围0-639,计数640次,与图 像行显示有效区域参数一致;rgb信号在rgb_valid信号有效时,被赋值为pix_data,rgb_valid信号无效时,赋值为0。

VGA030

图 36‑29 局部仿真波形图(八)

VGA031

图 36‑30 局部仿真波形图(九)

由图 36‑29、图 36‑30可知,pix_y信号在图像显示有效区域循环计数,计数周期为完整的pix_x计数周期,计数范围0-479,计数480次。与图像显示场有效区域参数一致。

VGA032

图 36‑31 局部仿真波形图(十)

VGA033

图 36‑32 局部仿真波形图(十一)

VGA034

图 36‑33 局部仿真波形图(十二)

VGA035

图 36‑34 局部仿真波形图(十三)

由图 36‑31、图 36‑32、图 36‑33、图 36‑34可知,行同步信号只有在行同步阶段保持高电平,其他阶段均保持低电平;场同步信号只有在场同步阶段保持高电平,其他阶段均保持低电平。

由仿真波形图可知,各信号仿真波形与绘制波形一致,模块通过仿真验证。

7.2.3.4. 图像数据生成模块

本小节中我们开始图像数据生成模块(vga_pic)的介绍,接下来我们会通过模块框图、波形图绘制、代码编写、仿真分析这几个部分,对本模块的设计、实现、仿真验证过程做一下详细介绍。

模块框图

图像数据生成模块,设计本模块的目的是,以VGA时序控制模块传入的图像有效显示区域像素点坐标(pix_x,pix_y)为约束条件,产生VGA彩条图像像素点色彩信息并回传给VGA时序控制模块。模块框图,具体见图 36‑35。

VGA036

图 36‑35 图像数据生成模块框图

由图 36‑35可知,图像数据生成模块包含4路输入、1路输出,共5路信号,输入输出信号简介,具体见表格 36‑5。

表格 36‑5 图像数据生成模块输入输出端口功能描述

信号

位宽

类型

功能描述

vga_clk

1Bit

Input

工作时钟,频率25MHz

sys_rst_n

1Bit

Input

复位信号,低电平有效

pix_x

10Bit

Input

VGA有效显示区域像素点X轴坐标

pix_y

10Bit

Input

VGA有效显示区域像素点Y轴坐标

pix_data

16Bit

Output

彩条图像像素点色彩信息

输入信号中,时钟信号vga_clk,频率为25MHz,为VGA显示器工作时钟,由分频模块产生并输入;复位信号sys_rst_n为顶层模块的rst_n信号输入,低电平有效;(pix_x,pix_y)为VGA有效显示区域像素点坐标,由VGA时序控制模块生并输入。

输出信号pix_data为彩条图像像素点色彩信息,在VGA有效显示区域像素点坐标(pix_x,pix_y)约束下生成,传输到VGA时序控制模块。

波形图绘制

在模块框图部分,我们介绍了图像数据生成模块的具体功能,对输入输出信号做了简单介绍,那么如何利用模块输入信号实现模块功能,输出我们想要得到的数据信号呢?在波形图绘制部分,我们会通过绘制波形图,并对各信号做出讲解,带领读者学习掌握模块功能的实现方法。

图像数据生成模块波形图,具体见图 36‑36。

VGA037

图 36‑36 图像数据生成模块波形图

本模块设计较为简单,根据输入像素点坐标(pix_x,pix_y),在有效显示区域,将pix_x计数范围十等分,在不同的计数部分给pix_data赋值对应的色彩信息,因为采用时序逻辑的赋值方式,pix_data滞后pix_x、pix_y信号一个时钟周期。

代码编写

模块波形图绘制完毕后,参照绘制波形图进行参考代码的编写。模块参考代码,具体见代码清单 36‑3。

代码清单 36‑3 图像数据生成模块参考代码(vga_pic.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
module vga_pic(
input wire vga_clk , //输入工作时钟,频率25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [9:0] pix_x , //输入有效显示区域像素点X轴坐标
input wire [9:0] pix_y , //输入有效显示区域像素点Y轴坐标

output reg [15:0] pix_data //输出像素点色彩信息

);

 ////
 //\* Parameter and Internal Signal \//
 ////
 //parameter define
 parameter H_VALID = 10'd640 , //行有效数据
 V_VALID = 10'd480 ; //场有效数据

 parameter RED = 16'hF800, //红色
 ORANGE = 16'hFC00, //橙色
 YELLOW = 16'hFFE0, //黄色
 GREEN = 16'h07E0, //绿色
 CYAN = 16'h07FF, //青色
 BLUE = 16'h001F, //蓝色
 PURPPLE = 16'hF81F, //紫色
 BLACK = 16'h0000, //黑色
 WHITE = 16'hFFFF, //白色
 GRAY = 16'hD69A; //灰色

 ////
 //\* Main Code \//
 ////

 //pix_data:输出像素点色彩信息,根据当前像素点坐标指定当前像素点颜色数据
 always@(posedge vga_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 pix_data <= 16'd0;
 else if((pix_x >= 0) && (pix_x < (H_VALID/10)*1))
 pix_data <= RED;
 else if((pix_x >= (H_VALID/10)*1) && (pix_x < (H_VALID/10)*2))
 pix_data <= ORANGE;
 else if((pix_x >= (H_VALID/10)*2) && (pix_x < (H_VALID/10)*3))
 pix_data <= YELLOW;
 else if((pix_x >= (H_VALID/10)*3) && (pix_x < (H_VALID/10)*4))
 pix_data <= GREEN;
 else if((pix_x >= (H_VALID/10)*4) && (pix_x < (H_VALID/10)*5))
 pix_data <= CYAN;
 else if((pix_x >= (H_VALID/10)*5) && (pix_x < (H_VALID/10)*6))
 pix_data <= BLUE;
 else if((pix_x >= (H_VALID/10)*6) && (pix_x < (H_VALID/10)*7))
 pix_data <= PURPPLE;
 else if((pix_x >= (H_VALID/10)*7) && (pix_x < (H_VALID/10)*8))
 pix_data <= BLACK;
 else if((pix_x >= (H_VALID/10)*8) && (pix_x < (H_VALID/10)*9))
 pix_data <= WHITE;
 else if((pix_x >= (H_VALID/10)*9) && (pix_x < H_VALID))
 pix_data <= GRAY;
 else
 pix_data <= BLACK;

 endmodule

模块参考代码是参照绘制波形图进行编写的,在波形图绘制小节已经对模块各信号有了详细的说明,对各信号介绍不再过多叙述。

本模块不再单独仿真,在后文直接对实验工程整体进行仿真,届时再对本模块信号波形进行分析。

7.2.3.5. 顶层模块

代码编写

实验工程的各子功能模块均已讲解完毕,在本小节对顶层模块做一下介绍。vga_colorbar顶层模块主要是对各个子功能模块的实例化,以及对应信号的连接。代码编写较为容易,无需波形图的绘制。顶层参考代码,具体见代码清单 36‑4。

代码清单 36‑4 顶层模块参考代码(vga_colorbar.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
module vga_colorbar(
input wire sys_clk , //输入工作时钟,频率50MHz
input wire sys_rst_n , //输入复位信号,低电平有效

output wire hsync , //输出行同步信号
output wire vsync , //输出场同步信号
output wire [15:0] rgb //输出像素信息

);

 ////
 //\* Parameter and Internal Signal \//
 ////

 //wire define
 wire vga_clk ; //VGA工作时钟,频率25MHz
 wire locked ; //PLL locked信号
 wire rst_n ; //VGA模块复位信号
 wire [9:0] pix_x ; //VGA有效显示区域X轴坐标
 wire [9:0] pix_y ; //VGA有效显示区域Y轴坐标
 wire [15:0] pix_data; //VGA像素点色彩信息

 //rst_n:VGA模块复位信号
 assign rst_n = (sys_rst_n & locked);

 ////
 //\* Instantiation \//
 ////

 //------------- clk_gen_inst -------------
 clk_gen clk_gen_inst
 (
 .areset (~sys_rst_n ), //输入复位信号,高电平有效,1bit
 .inclk0 (sys_clk ), //输入50MHz晶振时钟,1bit

 .c0 (vga_clk ), //输出VGA工作时钟,频率25MHz,1bit
 .locked (locked ) //输出pll locked信号,1bit
 );

 //------------- vga_ctrl_inst -------------
 vga_ctrl vga_ctrl_inst
 (
 .vga_clk (vga_clk ), //输入工作时钟,频率25MHz,1bit
 .sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
 .pix_data (pix_data ), //输入像素点色彩信息,16bit

 .pix_x (pix_x ), //输出VGA有效显示区域像素点X轴坐标,10bit
 .pix_y (pix_y ), //输出VGA有效显示区域像素点Y轴坐标,10bit
 .hsync (hsync ), //输出行同步信号,1bit
 .vsync (vsync ), //输出场同步信号,1bit
 .rgb (rgb ) //输出像素点色彩信息,16bit
 );

 //------------- vga_pic_inst -------------
 vga_pic vga_pic_inst
 (
 .vga_clk (vga_clk ), //输入工作时钟,频率25MHz,1bit
 .sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
 .pix_x (pix_x ), //输入VGA有效显示区域像素点X轴坐标,10bit
 .pix_y (pix_y ), //输入VGA有效显示区域像素点Y轴坐标,10bit

 .pix_data (pix_data ) //输出像素点色彩信息,16bit

 );

 endmodule

顶层模块参考代码理解起来较为简单,在此不再过多叙述。但有一点需要重点说明,由代码可知,vga_ctrl模块和vga_pic模块的复位信号是由信号rst_n信号作为输入,这是为何?

原因在于,调用IP生成时钟,只有在locked信号为高电平时输出的才是稳定时钟,将板卡复位信号sys_rst_n和locked信号作为约束条件,产生新的复位信号rst_n作为功能模块复位信号的输入,是为了防止时钟不稳定状态对实验工程产生影响。

RTL视图

实验工程通过仿真验证后,使用Quartus软件对实验工程进行编译,编译完成后,我们查看一下RTL视图, RTL视图展示信息与顶层模块框图一致,各信号正确连接,具体见图 36‑37。

VGA038

图 36‑37 实验工程RTL视图

7.2.3.6. 仿真验证

仿真代码编写

顶层模块参考代码介绍完毕,开始对顶层模块进行仿真,对顶层模块的仿真就是对实验工程的整体仿真。顶层模块仿真参考代码,具体见代码清单 36‑5。

代码清单 36‑5 顶层模块仿真参考代码(tb_vga_colorbar.v)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
\`timescale 1ns/1ns
module tb_vga_colorbar();
////
//\* Parameter and Internal Signal \//
////
//wire define
wire hsync ;
wire [15:0] rgb ;
wire vsync ;

 //reg define
 reg sys_clk ;
 reg sys_rst_n ;

 ////
 //\* Clk And Rst \//
 ////

 //sys_clk,sys_rst_n初始赋值
 initial
 begin
 sys_clk = 1'b1;
 sys_rst_n <= 1'b0;
 #200
 sys_rst_n <= 1'b0;
 end

 //sys_clk:产生时钟
 always #10 sys_clk = ~sys_clk ;

 ////
 //\* Instantiation \//
 ////

 //------------- vga_colorbar_inst -------------
 vga_colorbar vga_colorbar_inst
 (
 .sys_clk (sys_clk ), //输入晶振时钟,频率50MHz,1bit
 .sys_rst_n (sys_rst_n ), //输入复位信号,低电平有效,1bit

 .hsync (hsync ), //输出行同步信号,1bit
 .vsync (vsync ), //输出场同步信号,1bit
 .rgb (rgb ) //输出RGB图像信息,16bit
 );

 endmodule

顶层模块仿真参考代码内部实例化各子功能模块,连接各子功能模块对应信号,模拟产生50MHz时钟信号和复位信号,理解较为容易,不再讲解。

仿真波形分析

使用ModelSim软件对代码进行仿真,vga_ctrl模块已经通过赋值验证,clk_gen为调用IP核,无需仿真,在顶层模块的仿真波形分析,我们只查看rst_n信号和vga_pic模块的相关信号,仿真结果如下。

VGA039

图 36‑38 rst_n信号仿真波形图

由图 36‑38可知,rst_n信号正确生成,仿真波形与代码描述一致。

VGA040

图 36‑39 vga_pic模块仿真波形图(一)

VGA041

图 36‑40 vga_pic模块仿真波形图(二)

VGA042

图 36‑41 vga_pic模块仿真波形图(三)

VGA043

图 36‑42 vga_pic模块仿真波形图(四)

由图 36‑39、图 36‑40、图 36‑41、图 36‑42可知,pix_x信号在图像有效显示区域的完整计数周期被均分为十等份,pix_data在pix_x不同的计数范围内赋值不同的颜色信息。

7.3. 上板验证

7.3.1. 引脚约束

仿真验证通过后,准备上板验证,上板验证之前先要进行引脚约束。工程中各输入输出信号与开发板引脚对应关系如表格 36‑6所示。

表格 36‑6 引脚分配表

信号名

信号类型

对应引脚

备注

sys_clk

Input

E1

输入系统时钟

sys_rst_n

Input

M15

复位信号

hsync

Output

C2

行同步信号

vsync

Output

D1

场同步信号

rgb[15]

Output

A5

RGB色彩信息(红)

rgb[14]

Output

E6

RGB色彩信息(红)

rgb[13]

Output

E7

RGB色彩信息(红)

rgb[12]

Output

B8

RGB色彩信息(红)

rgb[11]

Output

A8

RGB色彩信息(红)

rgb[10]

Output

F8

RGB色彩信息(绿)

rgb[9]

Output

E8

RGB色彩信息(绿)

rgb[8]

Output

B7

RGB色彩信息(绿)

rgb[7]

Output

A7

RGB色彩信息(绿)

rgb[6]

Output

F7

RGB色彩信息(绿)

rgb[5]

Output

F6

RGB色彩信息(绿)

rgb[4]

Output

B6

RGB色彩信息(蓝)

rgb[3]

Output

A6

RGB色彩信息(蓝)

rgb[2]

Output

B5

RGB色彩信息(蓝)

rgb[1]

Output

A2

RGB色彩信息(蓝)

rgb[0]

Output

B4

RGB色彩信息(蓝)

下面进行管脚分配,管脚的分配方法在前面章节已有所讲解,在此就不再过多叙述,管脚的分配如下图 36‑43所示。

VGA044

图 36‑43 管脚分配

7.3.1.1. 结果验证

如图 36‑44所示,开发板连接12V直流电源、USB-Blaster下载器JTAG端口以及VGA显示器。线路正确连接后,打开开关为板卡上电。

VGA045

图 36‑44 程序下载连线图

如图 36‑45所示,使用“Programmer”为开发板下载程序。

VGA046

图 36‑45 程序下载窗口

程序下载完成后,如图 36‑46所示,VGA显示器显示出十色彩条,和预期实验效果一致。

VGA047

图 36‑46 VGA彩条实验效果图

7.4. 章末总结

到这里,本章节讲解完毕,通过实验,相信读者对于VGA显示的基本知识和概念,以及FPGA与VGA显示器之间数据通信流程已经理解掌握,读者要注意的是,对于VGA时序,务必要认真理解并掌握。

7.5. 拓展训练

1、修改代码,使用rgb_valid信号作为pix_x、pix_y信号的约束条件,观察显示图像,找出图像存在问题。

2、本实验工程实现的是VGA纵向彩条显示,读者尝试修改代码实现VGA横向彩条显示。

3、以彩条显示为背景,在图像中间位置显示分辨率为100*100的静止白框。