• 【连载】【FPGA黑金开发板】Verilog HDL那些事儿LCD(12864)封装(二十一)


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

    2

    5.7 实验二十:LCD12864)封装

    在这里笔者先提及一些重点。从5.1章开始,读者是否已经发觉到,笔者对封装建模,使用了许多第二章至第四章的建模基础。与其说,封建建模涉及了许多基础建模,还不如说建模基础是为了后期建模才存在。这一点笔者一开始就一直强调“低级建模”是为了后期的建模做好准备。当然“封装建模”也不是最后的建模。实际上“封装建模”也是“低级建模”的一环而已。因为“封装建模”一样也是为后期的建模在做准备。

    (那么下一个“后期”又是什么?读者先猜猜吧 ...

    5.6章后(VGA接口),这一篇同样是有关显示的封装。无论是 VGA接口 还是 LCD接口(LCD封装),原理上都是一样,不同的只是驱动上的方法而已。

    clip_image002

    上图是 lcd_interface.v 的组合模块。它包含了液晶控制模块,RAM模块,和SPI写模块。和VGA接口一样,RAM模块包含了图像信息,而且RAM模块也添加了访问优先级的逻辑。SPI写模块和实验12是一模一样。至于液晶控制模块就有点特殊了。

    液晶控制模块包含了对液晶的“初始化控制”和“绘图控制”的功能以外,还能自动的从RAM模块读取图像信息。乍看lcd_interface.v vga_interface.v 都是一样,它们皆能执行“读取图片信息的操作”以外,还能执行“显示驱动的操作”。此外, 对于 lcd_interface.v 的调用,我们只要针对 lcd_interface.v RAM模块 写入图像信息即可。

    lcd_interface.v 的功能大致如下:

    (一)初起的时候,液晶控制模块对液晶初始化。RAM模块本身也自行初始化。

    (二)每隔一段时间,液晶控制模块就会从RAM模块读取图像信息,然后利用这些信息来驱动液晶的显示。

    在封装之前,需要考虑几个参数的配置:

    液晶扫描频率

    40Hz

    图像分辨率

    64 x 128

    液晶的扫描频率40Hz,亦即每25ms为液晶写入一副 64 x 128 大小分辨率的图像。

    lcd_ram_module.v

    clip_image004

    16行,声明了该 8 Bits x 1024 Words 的储存空间,是由m4k资源组成。而且还提示 Quartus II 的综合器无视“写时读”的问题。该储存器是由 pika_ani.mif 该文件爱你初始化。

    spi_write_module.v

    clip_image006

    clip_image007

    基本上和实验十二的 spi_write_module.v 是完全一样。

    lcd_control_module.v

    clip_image009

    clip_image010

    clip_image011

    ( o )哇!代码那么长!不要被吓到!只要简单的分析,读者会发现,其实上述的内容,读者从实验一到实验二十的经过,它们只是重复出现而已。

    16行定义了25ms的常量。20~28行是25ms的定时器。

    我们知道“仿顺序操作”的模块都有一个特征,就是“不被使能不工作”,“完成工作就报告”。但是为了使液晶控制模块有独立性的能力,结果就添加一个“定时使能”的功能。在32~40行,就是充当这样的角色。isStart寄存器(32行)的位宽是2位,亦即该液晶控制模块拥有2个功能。在初始状态 isStart 被复位为 2'b10

    51~145行就是液晶控制模块的核心部分,故放映除出了“命令式仿顺序操作”的影子。61~114行是 initial_module.v 的部分,然而该功能被使能是在 isStart[1] ,亦即isStart寄存器最高位被拉高的时候才发生。

    也就是说,lcd_interface.v 初始化的时候,51~145的“initial function”(液晶初始化功能)就被执行。在同一个时间20~28行的定时器也开始计数。但是在定时器完成计数之前,在109行,产生了“完成反馈”,亦即“initial fucntion”已经执行完毕。此时在39行,if条件成立 isStart 被清理。

    115~145行是“draw function”(液晶绘图功能)。该功能会发生在,当isStart[0]isStart寄存器的最低位被拉高的时候。每隔25ms的时间在20~28行的定时器都会产生定时,isStart的最低位都会被拉高。换句话说,每隔25msdraw function”就会被执行。

    当“draw function”完成后(140行),就会产生一个“完成反馈”。在同一个时间39行的if条件就会成立,isStart会被清零。

    148行的 Read_Addr_Sig 信号是作为“RAM模块”读取操作的寻址信号。

    在前面,笔者显示了该lcd_interface.v 的扫描频率是 40Hz。如果换做公式来表达的话:

    T = 1 / F

      = 1 / 40Hz

      = 25 ms

    这也是20~28行的定时器要每隔25ms产生一次定时的原因。因为每隔25msisStart寄存器的最低位就会被拉低,然后“draw function”就会被执行。换句话来说,定时器的存在是为了充当“仿顺序操作”模块的“Start_Sig”信号。当然也可以这样说“Start_Sig Done_Sig 都是发生在液晶控制模块的内部

    lcd_interface.v

    clip_image013

     

    clip_image014

    该组合模块和 "图形" 基本上都是相似的,自己看着办吧。

    实验二十说明:

    如果实验十二和实验二十相比较,实验二十的RAM模块替代了实验十二的ROM模块作为图像信息的储存器。SPI写模块没有任何改变。实验二十的液晶控制模块使用了类似“命令仿顺序操作”的方法,整合了实验十二的 initial_module.v draw_module.v

    此外液晶控制模块在初始化的时候,会对液晶资源执行初始化的操作。然后每个25ms,液晶控制模块都会从RAM模块读取图像信息,用于液晶的显示驱动。

    所以说 vga_interface.v lcd_interface.v 有许多相同的地方。基本上它们都是使用同一个工作原理,就是提高扫描频率,利用肉眼的弱点,时而产生动态扫描的效果。如果笔者明白了 vga_interface.v 的工作原理,自然而然就会明白 lcd_interface.v 的工作原理。

    完成的扩展图:

    clip_image002

    实验二十结论:

    调用 lcd_interface.v 模块如同对 RAM模块写入信息。


    实验二十演示:

    这一章主要是演示 lcd_interface.v 如何调用。

    clip_image004

    在组合模块 lcd_interface_demo.v ROM模块的储存空间是 8 Bits x 2048 Words,我们知道一副分辨率 64 x 128 的图像所占的储存空间是 8 Bits x 1024 Words , ROM模块亦即包含两副图像信息。

    clip_image006

    皮卡丘动作1

    clip_image008

    比卡丘动作2

    就是以上这只小可爱的两幅图像信息。换句话说,该演示是要实现动画。

    lcd_interface_demo.v 的大致操作如下:

    (一)ROM模块读第一副图像信息,然后写入 lcd_interface.v RAM模块里。

    (二)延迟大约500ms

    (三)ROM模块读第一副图像信息,然后写入 lcd_interface.v RAM模块里。

    (四)延迟大约500ms

    (五)重复步骤1~4

    lcd_interface_demo.v

    clip_image010

    clip_image011

    clip_image012

    11行声明了 1ms的常量。15~25行是1ms的定时器,然而29~37行是秒级的计数器。

    94~101行实例化了 ROM模块,而且在105~113行实例化了 lcd_interface.v

    64~90行是该模块的控制程序。X寄存器计数列填充(61行),Y寄存器计数行切换(62行),Z寄存器控制图像切换(41行)。那么图像寻址地址的表达式是 X + ( Y << 7 ) + ( Z  << 10 )X << 7 表示了一行有128长度,Z << 10 表示了一副图像有 1024的长度。

    79~81行表示了,从 ROM模块 读取图像信息至 lcd_interface.v RAM模块的操作。84~85行是延迟500ms的操作。

    当步骤0的时候(78行),Z的值是049行),也就是第一副图像信息被选择,然后在79~81行,会将ROM模块 0~1023 的图像信息写入 lcd_interface.v RAM模块。当完成 8 次的 128次列填充,79行的if条件就会成立,i会递增以示下一个步骤。(注意,在79~81行的操作的期间 isWrite 一直被拉高,也就说 lcd_interface.v Write_En_Sig 也是一直被拉高 - 81行。)

    当步骤等于1的时候(83行),会产生500ms的延迟效果。然后i会递增,以示下一个步骤。

    当步骤2的时候(78行),Z的值是150行),也就是说第二幅图像信息被选中。接下来的动作,和步骤0一样,只是图像信息不同而已。

    当步骤等于3的时候(83行),同样也会产生500ms的延迟效果。i递增 ...

    步骤487行)将i清理,以示重复执行步骤0~3

    在这里有一个重点,就是在110行,Write_Addr_Sig 信号是由 rAddr[9..0] 驱动。因为有关图像切换仅是影响 rAddr[10] 的位而已。

    实验二十演示说明:

    没有什么特别的。对lcd_interface.v 的调用如同对 RAM模块写入信息而已。

    实验二十结论说明:

    嗯!封装以后的 lcd_interface.v ,调用的工作都非常方便了。


  • 相关阅读:
    webpack脚手架增加版本号
    background-image:url为空引发的两次请求问题
    vue中引入.svg图标,使用iconfont图标库
    mysql数据库
    vue 博客知识点汇总
    vue中显示markdown文件为html
    canvans知识点
    js如何实现一定时间后去执行一个函数
    CSS3选择器使用小结
    为什么margin-top不是作用于父元素
  • 原文地址:https://www.cnblogs.com/kingst/p/1864712.html
Copyright © 2020-2023  润新知