【连载】【FPGA黑金开发板】Verilog HDL那些事儿--VGA(二十)

声明:本文为原创作品,版权归akuei2及黑金动力社区(http://www.heijin.org)共同所有,如需转载,请注明出处http://www.cnblogs.com/kingst/

2

5.6 实验十九:VGA封装

在笔者还没有开始写这本笔记之前,笔者和大众的新手一样,都喜欢在网络上找资料。

有一篇论文“基于FPGAVGA接口”中的实验,笔者很感兴趣,但是论文始终是论文,论文的东西都是用来毕业,瞎了笔者的狗眼。笔者就在那个时候开始突发奇想:“有没有什么的办法,以最小的条件,来实验该论文中的内容呢?

在此刻,阅读这章笔记的时候,读者是否对“封装”或者“接口”有一个概念了吧?

同样的事实,VGA模块也需要封装成为VGA接口。

clip_image002

 

上图是组合模块 vga_interface.v ,里面包含了“同步模块”(用于配置显示标准,和驱动 VGA ),“ VGA 控制模块 ”(用于控制图像信息),还有一个双向 RAM 模块。是不是觉得很疑惑:为什么多了一个 RAM 模块出来。

 

在实验九中, VGA 控制模块读取的图片信息是来自 ROM 模块。相反的实验十九的图像信息是来自 RAM 。在完成 VGA 接口之前,我们必须设定一些参数。

图像分辨率

16 x 16

图像颜色

点阵

图像显示位置

X = 3 Y = 2

显示标准

800 x 600 x 60Hz

 

显示标准,关于这个参数,在 3.4 章中有详细的介绍,这里就重复了。图像分辨率,说简单点就是一副图像信息的大小。图像颜色,点阵的意思就是黑和白。图像显示位置,是指一副图信息开始显示的位置, X = 3 Y = 2 ,表示图像在屏幕的坐标( 3, 2 )显示。

sync_module.v

clip_image004


clip_image006

sync_module.v 是支持 800 x 600 x 60Hz 的显示标准(需要40Mhz的时钟源)。

vga_control_module.v

clip_image008


clip_image009

29行的if条件,就是表示开始显示位置 Y 39行的开始显示位置 X

我们知道图像信息是16 x 16。所以,29行的if条件成立范围是在 Row_Addr_Sig > 1 ~ Row_Addr_Sig < 17。同样的在39行的if条件成立范围在 Column_Addr_Sig > 2 ~ Column_Addr_Sig < 19

 

24 行和 34 行的寄存器 m n ,是用来列寻址和行寻址。所以它们必须从“开始显示位置”开始计数。

 

46~54 行的 isSize 标志寄存器是用来确定“一副图像的显示框”,亦即“图像显示有效范围”。在 51~52 行的 if 条件指定了该 isSize 表示寄存器被拉高的时候,也就是说在 Row_Addr_Sig > 1 ~ Row_Addr_Sig < 17 Column_Addr_Sig > 2 ~ Column_Addr_Sig < 19 ,分辨率为 16 x 16 的图像时“显示有效”的。

 

59 行表示 m 行寻址 等价于 Ram_Addr 地址。

 

61~63 行,是列寻址,同是点阵操作。由于该 VGA 接口的颜色支持参数是“黑白”的缘故,所以 61~63 行都是同样的点阵操作。

ram_module.v

 

clip_image011

 

RAM 是什么,有电子背景的同学都知道它是什么。 RAM ROM 不同的是, RAM 支持访问(读和写操作),然而 ROM 只支持读操作。一般上 RAM 有分为单端口,双向端口,三向端口。双向端口,有为分为真双向端口( True ),和假双向端口( Simple ),真双向端口有写入时钟和读取时钟,然而假双向端口读写共用一个时钟。为了方便 vga_interface.v 的建模,在这里我们使用假双向端口 RAM

在这里,我们先要考虑 vga_interface.v 支持的图像分辨率,亦即 16 x 16 。所以RAM所需要的储存空间是 16Bits x 16 WordsRAM FIFO一样,要访问RAM的时候都需要拉高 xx_En_Sig 信号。由于RAM 包含 16 Bits 所以 Write_Data Read_Data, 皆是16位的位宽。当然,16 Words 表示了 xx_Addr_Sig 4位的位宽。

 

一个普遍存在与双向端口 RAM 的问题是“同时读写冲突”。一般的物理双向端口 RAM 都内置仲裁逻辑。“仲裁逻辑”的设计方法是比较复杂,我们使用另一种方法,就是“访问优先级”。

 

在这里,我们可以这样定义:写操作的优先级高于读操作。

 

所以呀,使用 QuartusII 自建的双向端口 RAM 不怎么适合。换一句话,我们必须手动创建包含“访问优先级”的“假双向端口 RAM ”。

clip_image013


clip_image014

1~11行是RAM模块的输入输出口。在15行,声明了 16Bits x 16 Words 的储存器。

如果以AlteraFPGA为例,尝试回想一下,FPGA都内置了偏上资源 m4k。当我声明储存器的时候,我们可以指定它由 m4k 组成。

* ram_tyle = m4k *

当然你也可以指定储存器由逻辑资源组成:

* ram_tyle = logic *

在前面,我已经说过:“双向端口的RAM存在访问冲突的问题”。当QuartusII 在综合的时候,由于 m4k 资源本身的特性,并不适合“写时读”(read-during-write),亦即“访问冲突”。虽然,我们手动为RAM模块添加了访问优先级,可以避免“访问冲突”的问题。但是Quartus II 的综合器是一个大笨蛋,你没有提示它:“不用关心m4k资源的访问冲突问题”,综合器是不知道的。因此:

* ram_style = no_rw_check *

还有一点就是关于储存器初始化的问题:

还记得在建立ROM的时候,笔者都为ROM建立一个 .mif ,然后对ROM初始化。同样的道理,RAM储存器在创建的时候也必须初始化。该RAM模块初始化的信息,是实验十之五之中的“第一副小绿人”。

* ram_init_file = ram_initial_file.mif *

21~27行是RAM模块的访问优先级逻辑。在24行表示了写操作比读操作拥有更高的优先级。当 Write_En_Sig 拉高的时候,对RAM储存器执行写操作。一旦 Write_En_Sig 被拉低 读操作作为RAM储存器的默认状态。

有一重点必须注意就是rData寄存器是用来暂存读数据。为了避免“当写操作执行时Read_Data 失去驱动源”。

vga_interface.v

clip_image016


clip_image017

 

VGA 接口的时钟源是由全局时钟源经过倍频后输入的( 9 行)。

实验十九说明:

读者是不是觉得实验十九和实验九相比,简直是莫名其妙对吧?在这里笔者稍微区分一下实验九和实验十九的不同。实验九顾名思义就是VGA显示模块,它所使用的显示方法是同步的。换句话说,也就是图片信息处理和VGA显示驱动都是在同样的时间下。当然也可以这样想,图片信息是又VGA模块本身提供的,又或者图片信息早已固定存在。

 

实验十九的 VGA 接口 , 恰好是与实验九的 VGA 显示模块相反。它所使用的显示方法是异步的。也就是说,图像信息处理和 VGA 显示驱动是在不同的时间下完成。看得简单点就是,图像信息是由外部提供。

 

在实验十九中的 VGA 接口,图像信息是暂存在 RAM 模块里,而且 RAM 模块里边的图像信息是由上一层模块写入。读者可能会产生这样一个问题:“假设 vga_control_module.v 在读取 RAM ,地址 0 的信息的时候,生一层模块同时对 RAM ,地址 0 执行写操作 ... ”。

事实上,由于访问优先级逻辑的关系,当发生“访问冲突”的时候,vga_control_module.v读取的是 上一次的rData信息。

 

读者可能又会问:“当发生访问冲突的时候, rData 暂存的数据当然不是当前的显示数据,图像显示既不是出现错误? ”。 你知道吗 ? LCD 显示技术为了消除 LCD 显示残影的问题,在指定间隔时的间里,都会插入诺干“黑帧”(全黑图像信息)。如果 LCD 插入“黑帧”,已不是屏幕忽然间全黑,然后又恢复,又全黑,又恢复 .... 呵呵!事实上,人体的视觉是很蛋疼和迟钝的,这些“短暂”的“黑帧”人眼是察觉不出来。这也使得 LCD 消除残影的方法。

 

同样的道理,以 800 x 600 x 60Hz 为显示标准。如果在 1 秒内出现 1~16 个残缺的帧,人眼是不会察觉到,因为该显示标准时每秒 60 帧图像。用动画的话来说,每秒 8 帧产生拖尾效果,每秒 24 帧产生专业动画效果,每秒 40 帧人眼是“瞬间”的效果。

 

完成后的扩展图:

clip_image002

 

实验十九结论:

实验九和实验十九最大的差别就是图像信息处理的方法。前者是由模块内部提供的,后者是由上一层模块写入。此外实验十九当 vga_control_module.v ram_module.v 读取信息的时候,如果在同一个时间,上一层模块对 vga_interface.v ram_module.v 执行写操作,故会发生“访问冲突”。为了避免这个问题,笔者对 ram_module.v 加入了访问优先级逻辑,访问优先级定义为:写操作优先级高于读操作。

 

还有有关“实验十九说明”中提及种种“显示问题”会在“实验十九演示”中演示。

实验十九演示:小绿人请加油

clip_image004

 

上图的 vga_interface_demo.v 组合模块表示了,控制程序从 ROM 模块读取图片信息,然后写入 VGA 接口。该 ROM 模块是基于实验九之五的 greenman_rom_module.v ,里边包含了 6 16 x 16 的图片信息。控制程序,每隔 250ms 写入不同的信息至 VGA 接口。所以在屏幕的显示结果上,会出现小绿人的动画。

vga_interface_demo.v

clip_image006


clip_image007

 

clip_image008

 

16~20 行实例化了 pll 模块, pll 模块将全局时钟倍频至 40Mhz 24 行是 1ms 常量的声明,然而 28~50 行建立了 1ms 定时器( 28~38 行)和 ms 级计数器( 42~50 行)。 54~69 行表示了 6 副图像信息在 ROM 模块的起始地址。在 73~104 行就是该组合模块的核心功能,在 93~95 行,表示了 - 当步骤为 0 2 4 6 8 10 时,对 vga_interface.v RAM 模块写入不同的图像信息。在 97~99 行是 250ms 的延迟,亦即每一副图像信息的停留时间。

 

109~116 行实例化了 greenman_rom_module.v 。在 120~132 行实例化了 vga_interface.v

在一开始的时候 vga_interface.v 内部的RAM模块会执行初始化该储存信息,亦即作为默认图像信息。当 vga_interface_demo.v 进入步骤0,在同一时间,在62行会对 Y寄存器赋值与ROM模块的第一副图像信息的起始地址,亦即地址0。在94~95 isWrite被拉高,以示对vga_interface.v RAM模块写入使能(123行)。

 

Y 寄存器作为图像信息在 ROM 模块的起始地址, X 寄存器作为每一副图像信息的行寻址地址,然而 rAddr 作为 x 寄存器和 y 寄存器的总和,同时也是作为 ROM 模块的地址信号( 114 行)。

 

94 行中, x 会递增至 0~15 ,已对一副图像信息的行寻址( Addr 寄存器的 4 [3..0] ,同时作为 vga_interface.v 的写入地址 -124 行)。还有一点必须注意的是, vga_interface.v 的写入数据是由 ROM 模块的 Rom_Data 驱动( 125 行)。直到 x 等于 16 95 行) , 亦即一幅图像的行寻址已经结束, rAddr , X , isWrite 寄存器被赋予 0 值。 i 递增以示下一个步骤。

97~99行,步骤 1, 3, 5, 7, 9, 11 是延迟250ms的操作。rTimes 寄存作为言辞 ms 的计数值(98行),rTime 赋值与 250,亦即是延迟 250ms。当isCount被拉高的时候(99行),定时器和计数器都会开始工作(28~50行)。直到ms级的计数计数到250为止(98行),isCount被拉低, i递增以示下一个步骤。

 

上述步骤的执行大致如下:

(一)写入第0副图像信息至 vga_interface.v ,延迟250ms

(二)写入第1副图像信息至 vga_interface.v ,延迟250ms

(三)写入第2副图像信息至 vga_interface.v ,延迟250ms

(四)写入第3副图像信息至 vga_interface.v ,延迟250ms

(五)写入第4副图像信息至 vga_interface.v ,延迟250ms

(六)写入第5副图像信息至 vga_interface.v ,延迟250ms

(七)重复执行步骤1~6

实验十九演示说明:

 

在演示的显示效果中,你会看到小绿人的动画由六副图像信息,每隔 250ms 不停的循环和切换而产生。实际上,每秒 60 帧的图像信息中,有几幅图像是“崩坏”,由于人类的视觉迟钝的关系察觉不出来。

实验十九演示结论:

 

不知道读者还记得“接口的定义”吗?就是“最后的工程”和“独立性”。在实验十九演示中, VGA 接口是一个独立的个体,它以每秒显示 60 帧图像信息而工作。当我们对 VGA 接口调用的时候,我们不需要顾及 VGA 接口的内部是如何工作,反之我们只要关心如何对 VGA 接口 写入图像信息即可。如实验十九演示中那样,为了实现小绿人动画,我们在上一层模块中,每隔 250ms 写入不同的图像信息。

 

和在实验九之五不同的是,我们为了实现小绿人的动画效果,必须考虑由 sync_module.v 输出的 Frame_Sig 信号。以计数 Frame_Sig 信号的方式去实现小绿人动画。类似的方法大大的压缩了灵活性。

 

原理上, vga_interface.v 的工作原理,适合任何显示接口,因为人类的肉眼对画面的“切换速度”不敏感。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值