FPGA强化-VGA显示设计与验证

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。

图 36‑1 VGA接口

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

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

图 36‑3 VGA连接线

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

图 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。

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

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

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

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

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

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

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

7.1.4. VGA时序标准

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

图 36‑6 VESA VGA时序标准图

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

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

图 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。

图 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。

图 36‑9 VGA时序图

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

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

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

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

图 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。

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

7.2.2. 硬件资源

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

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

图 36‑12 VGA部分原理图

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

VGA_D15: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。

图 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。

图 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。

图 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。

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

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

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

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

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

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

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

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

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

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

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

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

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

图 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信号为约束条件控制生成,三路信号绘制波形图如下:

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

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

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

图 36‑21 rgb信号波形图

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

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

代码编写

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

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

|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | 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)

|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | \`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对参考代码进行仿真,仿真结果如下。

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

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

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

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

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

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

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

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

图 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。

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

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

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

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

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

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

图 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。

图 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。

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

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

代码编写

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

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

|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | 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)

|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | 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。

图 36‑37 实验工程RTL视图

7.2.3.6. 仿真验证

仿真代码编写

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

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

|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | \`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模块的相关信号,仿真结果如下。

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

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

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

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

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

图 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 场同步信号
rgb15 Output A5 RGB色彩信息(红)
rgb14 Output E6 RGB色彩信息(红)
rgb13 Output E7 RGB色彩信息(红)
rgb12 Output B8 RGB色彩信息(红)
rgb11 Output A8 RGB色彩信息(红)
rgb10 Output F8 RGB色彩信息(绿)
rgb9 Output E8 RGB色彩信息(绿)
rgb8 Output B7 RGB色彩信息(绿)
rgb7 Output A7 RGB色彩信息(绿)
rgb6 Output F7 RGB色彩信息(绿)
rgb5 Output F6 RGB色彩信息(绿)
rgb4 Output B6 RGB色彩信息(蓝)
rgb3 Output A6 RGB色彩信息(蓝)
rgb2 Output B5 RGB色彩信息(蓝)
rgb1 Output A2 RGB色彩信息(蓝)
rgb0 Output B4 RGB色彩信息(蓝)

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

图 36‑43 管脚分配

7.3.1.1. 结果验证

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

图 36‑44 程序下载连线图

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

图 36‑45 程序下载窗口

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

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

7.4. 章末总结

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

7.5. 拓展训练

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

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

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

相关推荐
chenlance15 小时前
基于FPGA的激光器多通道数据采集与波形控制系统设计
fpga开发
9527华安17 小时前
FPGA实现GTP高速收发器2路视频传输,基于aurora 8b10b编解码架构,提供4套工程源码和技术支持
图像处理·fpga开发·aurora·高速收发器·8b10b·derdes
cjie22118 小时前
lanczos插值引起的振铃现象
计算机视觉·fpga开发
liuluyang53018 小时前
Verilog 中 wire 与 wor 的区别详解
fpga开发·verilog
GateWorld2 天前
LCD显示技术完全指南:原理·制造·驱动·FPGA实现之点屏五 miniLVDS
fpga开发·lcd显示·fpga点亮屏幕·minilvds
nuoxin1142 天前
WILX1200HC-5TG144I替代 LCMXO2-1200HC-5TG144I(富利威)
人工智能·嵌入式硬件·fpga开发·电脑·硬件工程·dsp开发
Bahair_2 天前
【FPGA】使用fdatool设计滤波器系数,使用FIR Compiler导入系数联合滤波
fpga开发
qq_411262422 天前
硬件是ESP32-P4连接LAN8720A,正常初始化之后,设备DHCP失败
stm32·单片机·fpga开发
第二层皮-合肥3 天前
【数据采集专栏】时钟同步(有时钟卡方案)
fpga开发
XINVRY-FPGA3 天前
XCKU035-2FBVA676I AMD Xilinx Kintex UltraScale FPGA
arm开发·嵌入式硬件·网络安全·fpga开发·硬件工程·信号处理·fpga