注:本文由不愿透露姓名的 @Cardia 同学撰写。以下为正文。

在上一篇文章中,通过LED灯的实例介绍了时序逻辑的实现,其文章链接如下:

人生状态机:[走近FPGA]之点亮LED​zhuanlan.zhihu.com

本文的所有实例都使用硬木课堂Xilinx Aritx 7 FPGA板进行上实现,且附有上板演示视频,该开发板的链接如下:

硬木课堂 Xilinx Aritx 7 FPGA板 Arm Cortex-M SoC设计 集创赛​item.taobao.com

在这篇文章中,将结合之前介绍的模块化设计思想以及数字电路中组合逻辑与时序逻辑的知识,分享三个在FPGA开发板上实现的数码管动态显示的案例。

数码管动态显示原理

在介绍实例之前,我们需要先了解一下数码管动态显示的原理。在之前的文章中,曾介绍过数码管的显示原理,且实例中涉及到了数码管的静态显示,该文章链接如下:

人生状态机:[走近FPGA]之组合逻辑进阶——模块化设计​zhuanlan.zhihu.com

由于多位数码管的段选信号是连接在一起的,即数码管是共享段码的,那么所有点亮的数码管在同一时刻只能显示相同的图案。这看似大大局限了数码管的显示效果,但其实也有办法让多位的数码管在人眼看来能“同时”显示不同的图案,以获得更多样性的显示效果。其实现方法就是利用人眼的视觉暂留效应,轮流点亮数码管,并且在各位数码管点亮的期间给出对应的段码,只要进行这一过程的速度控制得当,人眼就来不及观察到各个数码管依次点亮,而是能看到多位数码管稳定地显示各自的图案。

在上个链接的文章,即介绍模块化设计的文章中,有一个实例是利用拨码开关手动地控制数码管的位选。而在实现数码管动态显示时,这个轮流选通的过程其实也是类似的,不过该过程需要电路能“自动”完成,且对位选通的时间间隔有一定要求,这一时间间隔既不能过长,否则人眼观察时有闪烁感,也不能过短,否则观察时数码管亮度会比较低。对于这篇文章中演示时使用的FPGA开发板来说,板载数码管共有六位,可以将数码管位选通的时间间隔设置为1ms。

实例一

实例一将分享一个基本的数码管动态显示案例。其实现目标是通过开发板上的三组拨码开关SW3-SW0、SW7-SW4、SW11-SW8分别控制三位数码管进行十六进制显示。根据数码管动态显示的原理和模块化设计的思想,该实例的电路框图设想如下:

实例一电路框图

如上图所示,既然涉及数码管显示,显示译码的部分是必不可少的,该模块由两个译码器组成,分别负责数码管位选译码和段码译码,进行段码译码的译码器还需要通过多路复用器与三组数据输入进行连接。另外,由于板载的晶振时钟频率为50MHz,要实现动态显示原理中介绍的以1ms为时间间隔进行位扫描,需要对时钟进行分频,得到1KHz的时钟,所以电路中需要一个时钟分频的模块。最后,便是实现数码管的轮流选通以实现动态显示,为了能在某位数码管被选通的同时能给出对应该位数码管的段码,需要有一个模块指明当前点亮的是哪一位数码管,在该设计中采用的是计数器来充当这一模块。该计数器以分频得到的时钟作为输入,计数输出既作为位选译码器的输入也作为多路复用器的控制信号输入,这样就可以实现数码管在轮流选通的同时,也得到对应的段码输出。

下面给出了实例一中负责显示译码功能的两个模块的参考代码,实质都是译码器,分别是数码管的位选译码模块和段码译码模块。这两个模块可在涉及数码管显示的工程中复用,复用时如果使用的数码管位数不同,只需要调整位选译码模块端口声明中bit_disp的位宽以及位选译码部分的代码即可,段码译码模块一般不需要作调整。

module 

module 

下面是时钟分频模块的代码,在上一篇文章中也有介绍,这里为了模块复用的方便,使用了parameter语句进行参数化设计,当需要得到其他频率的时钟时,只需要在例化时更改分频计数值的最大值即可(但该值不可以超过2^32,因为模块中cnt寄存器设置的位宽为32位)。

module 

接下来是计数器模块的参考代码,其功能是在每个输入时钟的上升沿使计数值加1。由于实例一使用了三位数码管,因此计数器设置的最大计数值为2’b10,该计数器模块计数值的循环序列为2’b00、2’b01、2’b10。

module 

接着是多路复用器模块的参考代码,结合实例一的框图,需要描述一个三选一的多路复用器。

module 

最后是顶层模块,根据设想的框图将各个模块例化即可,我们可以再次回顾一下例化的意义,其实就是用硬件代码的方式把电路各元件之间的连接关系描述出来。如下是顶层模块的参考代码,可以注意一下例化时钟分频模块时进行参数传递的方式,该方法在进行功能仿真时也会用到。

module 

下面进行实例一的功能仿真。上一篇文章中也提到过,由于实例中包含时钟分频的部分,如果不修改时钟分频的参数,仿真需要的时间将会过长,而且得到的仿真波形也不利于观察,所以可以在编写testbench时修改时钟分频计数最大值,更快地完成功能仿真,而且同样能观察到时钟分频模块是否正常工作,只是得到的时钟频率不同。实例一的testbench参考代码如下,例化时将分频计数的最大值改为了1,即只对时钟进行四分频,可以加快仿真过程。如下是testbench的参考代码。

module 

下面给出了在Modelsim中的部分仿真波形,可以观察到由于testbench中将分频计数最大值的参数改为了1,分频模块对时钟进行了四分频,另外,计数器工作正常,显示译码的结果也是正确的。后续两个实例的仿真也是类似的,都可以通过修改参数缩短仿真所需的时间,在过程块中设置不同的输入组合进行简单的功能测试。由于过于相似,在之后的两个实例中就不再重复这一过程,希望读者能自己尝试着编写testbench,养成上板验证前进行仿真的习惯。

实例一仿真波形

仿真完成后在Vivado中进行综合、管脚约束、布局布线并生成比特流文件,便可以上板观察现象。下面给出了本例的管脚约束以及演示视频。

实例一管脚约束

知乎视频​www.zhihu.com

实例二

在上一例中,使用了FPGA开发板上的所有拨码开关却只够控制三位数码管进行动态显示,而在本例中将分享一个只需少部分拨码开关就可控制六位数码管动态显示的案例。实例二的实现目标是通过一组拨码开关来选定某一位数码管,再通过另一组四位的拨码开关指定该数码管显示的位数,仅用两组拨码开关实现对六位数码管动态显示的控制。根据这一实现目标,给出了如下的电路框图构想。

实例二电路框图

上图中的许多模块与实例一致,因为涉及数码管的动态显示,所以仍然需要显示译码、时钟分频、多路复用器和计数器模块。为了实现能对各个指定数码管的显示数据进行互不干扰的输入和寄存,本例的参考设计是设置六个寄存器来寄存各位数码管需要显示的数据(指图中的SW6-SW3对应的四位二进制输入),并使用译码器将控制输入SW2-SW0进行译码并得到寄存器的使能信号。事实上,在很多应用中译码器都被用于产生使能信号,显示译码中的位选译码部分也可以看作是使用译码器来产生数码管的位使能信号。

根据上面的分析,该例的许多功能模块其实与实例一相似,包括时钟分频模块、计数器模块、多路复用器模块以及数码管的位选译码模块和段码译码模块。其中时钟分频模块和数码管段码译码模块无需做任何改动,计数器模块和数码管位选译码模块由于本例使用的数码管数量发生了改变需要进行一些调整。对于计数器模块,由于数码管数量增加至六位,所以用于指明当前点亮哪一位数码管的计数值位宽拓展到3位,最大计数值设置为3’b101。参考代码如下所示:

module 

接着调整位选译码模块的代码,由于使用的数码管增加至了六位,需要将端口声明中bit_sel的位宽改为三位,并修改位选译码部分的代码,该模块修改后的参考代码如下:

module 

而对于多路复用器模块,根据框图可以很容易看出,在本例中需要一个六选一且每路数据位宽都为4bit的多路复用器,下面给出了实例二中多路复用器模块的参考代码。

module 

然后设计实例二中的译码器模块,该模块用于产生后续六个寄存器的使能信号,其参考代码如下:

module 

接下来是对寄存器模块的描述,根据框图中的构想,本例中使用的寄存器需要有使能端,其参考代码如下:

module 

最后是顶层模块的描述,需要根据设计时绘制的框图正确地连接各个模块,下面给出了实例二顶层模块的参考代码:

module 

将顶层模块和各个功能模块加入Vivado建立的工程中,并按步骤进行至上板观察,通过上板验证会发现这样的设计其实是有缺陷的。下面给出了上板的演示视频,视频中试图让六位数码管分别显示1、2、3、4、5、6。

知乎视频​www.zhihu.com

从视频可以看到,想要对不同位的数码管分别设置要显示的数据时,数码管的显示会乱跳,这时因为利用拨码开关进行输入时很多时候不能一步到位得到想要的输入。例如在设置好第三位数码管的显示数据后,如果想要接着设置第四位数码管的显示数据,理想状态下,只需要把控制输入SW2-SW0从3’b011改为3’b100,再修改数据输入即可,但是实际情况下改变控制输入就至少需要三步,即拉高SW2、拉低SW1以及拉低SW0,根据顺序的不同这中间可能会产生3’b001、3’b010等输入组合,这时可能就会导致本来已经设置好的数码管其对应的寄存器又存入了新的输入数据,反应到现象上就是数码管本来设置好的显示数据又发生了变化。为了改进这一点,我们可以对RTL代码进行修改,解决办法是借助使能信号,让译码器仅在需要的时候才对控制输入进行译码。

下面给出了对译码器模块的修改参考,增添了对使能信号功能的描述,当使能信号en拉低时,该译码器产生给六个寄存器的寄存器使能信号全部拉低。

module 

译码器修改好后还需要在顶层模块中添加译码器使能信号的端口声明,并调整例化部分的代码,这里就不赘述了。下面给出了改进后的上板演示视频并附上了实例二的管脚约束表格,可以观察到借助了新增的使能输入,成功地让六位数码管分别显示了1-6的整数。

实例二管脚约束

知乎视频​www.zhihu.com

实例三

下面将介绍本文的最后一个实例,该例的实现目标为通过拨码开关输入BCD码设置起始时间(单位为秒),由数码管显示倒计时的过程。通过前面两个实例,相信读者对数码管进行动态显示所必需的这部分电路已经很熟悉了,如下图给出的电路框图所示,显示译码、时钟分频、计数器以及多路复用器这部分电路与实例一和实例二一致,需要关心的是如何能得到正确的数据来进行显示译码。根据实例三想要实现的主要功能倒计时,可以很容易联想到计数器,倒计时本身就是一种向下计数的过程,所以可以通过设计一个向下计数器来实现。由于倒计时一般是十进制显示,因此本例需要限制拨码开关的输入为BCD码输入,同样地,上面提到的向下计数器也需要专门设计为BCD码向下计数器。通过两个BCD码计数器进行级联,就可以实现起始数据为两位数的向下计数。

实例三电路框图

通过上面的分析,电路需要的大部分模块都在实例一二中设计过,唯一需要关注的是BCD码向下计数器的设计。根据实例三的实现目标,要能实现通过拨码开关设置倒计时起始时间的功能,BCD码向下计数器需要设置有置数的功能,另外为了进行级联,还需要设置用于级联的输入输出信号。BCD码向下计数器的参考设计如下图所示。

BCD码向下计数器

下面给出了BCD码向下计数器的参考代码,计数值为4位的BCD码,在每个时钟上升沿,若借位输入有效则进行向下计数,当向下计数至0时若借位输入仍有效,则拉高借位输出。该计数器还带有异步复位和同步置数的功能。

module 

其他功能模块的参考代码已在实例一中给出,由于本例只是用两位数码管,因此其他功能模块需要调整部分代码,如何调整已在实例二中详细介绍过,这里就不再赘述了。

如下给出了顶层模块的参考代码,编写时同样要注意各模块例化时的端口连接。本例中需要例化两个时钟分频模块,一个产生1KHz(周期为1ms)的时钟用于数码管依次选通位选信号,另一个产生1Hz(周期为1s)的时钟作为BCD码向下计数器的输入时钟以实现倒计时的功能。BCD码向下计数器模块的例化和级联也需要注意,级联的方法是将进行个位计数器的借位输出连接到进行十位计数器的借位输入。另外参考代码中将个位计数器的借位输入与两个计数器BCD码输出的逻辑或相连接,目的是在倒计时至0后停止计数,若想要进行循坏计数,可以在例化个位的BCD码向下计数器时将借位输入bin直接拉高。

module 

最后给出了实例三的上板演示视频以及具体的管脚约束表格,视频中将起始时间设置为了24s,从视频中可以观察到数码管正确地显示了倒计时的过程。

实例三管脚约束

知乎视频​www.zhihu.com

至此,关于数码管动态显示的三个实例就分享完毕了,本期文章中介绍了数码管动态显示的原理,分享的三个实例都采用了模块化设计的思想进行实现,同时还应用到了数字电路中组合逻辑和时序逻辑的知识。感谢您的阅读,下期再见。

利用全加器实现7段数码管_[走近FPGA]之数码管动态显示相关推荐

  1. 矩阵键盘与六位数码管_[走近FPGA]之矩阵键盘

    注:由于新学期较为繁忙,本文由不愿透露姓名的 @Cardia 撰写.以下为正文. 在上一篇文章中,介绍了二进制转十进制电路的实现,其文章链接如下: 人生状态机:[走近FPGA]之二进制转BCD码​zh ...

  2. 8086汇编4位bcd码_[走近FPGA]之二进制转BCD码

    注:本文由不愿透露姓名的 @Bulingxx 撰写.以下为正文. 在上一篇文章中介绍了数码管如何在FPGA开发板上实现动态显示,其文章链接如下: 人生状态机:[走近FPGA]之数码管动态显示​zhua ...

  3. 利用全加器实现7段数码管_简单共阴极数码管电路图大全(CD4511/段译码/驱动器)...

    共阴极则是把所有LED的阴极连接到共同接点com,而每个LED的阳极分别为a.b.c.d.e.f.g及dp(小数点),如下图所示.图中的8个LED分别与上面那个图中的A~DP各段相对应,通过控制各个L ...

  4. 利用全加器实现7段数码管_显示译码器 || 7段数码管 || 7段LCD || 7448 || 数电

    显示译码器 || 7段数码管 || 7段LCD || 7448 || 数电 1数码显示器件 在介绍显示译码器之前,先介绍一下常用的数码显示器件,可以分为 半导体显示器 液晶显示器 荧光数码管 辉光数码 ...

  5. fpga供电电压偏低会怎样_[走近FPGA]之开发板介绍篇

    开发板概述 在走近FPGA预告篇中,我们已经提到了系列文章使用的开发平台,硬木课堂Xilinx Artix 7 FPGA板,如下图所示.它使用的FPGA芯片型号为Xilinx Artix-7 XC7A ...

  6. 共阳数码管段码表_简单共阴极数码管电路图大全

    共阴极则是把所有LED的阴极连接到共同接点com,而每个LED的阳极分别为a.b.c.d.e.f.g及dp(小数点),如下图所示.图中的8个LED分别与上面那个图中的A~DP各段相对应,通过控制各个L ...

  7. 基于fpga的数码管动态扫描电路设计_【至简设计案例系列】基于FPGA的密码锁设计(altera版)...

    秦红凯 明德扬FPGA科教 一.项目背景概述 随着生活质量的不断提高,加强家庭防盗安全变得非常重要,但传统机械锁的构造过于简单,很容易被打开,从而降低了安全性.数字密码锁因为它的保密性很高,安全系数也 ...

  8. 蓝桥杯单片机数码管动态显示_单片机静态动态数码管

    单片机系统中常用的显示器有: 发光二极管LED(Light Emitting Diode)显示器.液晶LCD(Liquid Crystal Display)显示器.TFT液晶显示器等.LED显示器有两 ...

  9. 51单片机数码管滚动显示学号_静、动态数码管动态显示

    1. 数码管静态.动态显示原理 静态显示的特点是每个数码管的段选必须接一个8位数据线来保持显示的字形码.当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止.这种方法的优点是占用CPU时间少, ...

  10. 第一段Java程序_借助Win控制命令台编译执行 编辑器Notepad++

    第一段Java程序_借助Win控制命令台编译执行 编辑器Notepad++ 准备代码: 第一次编译: 显然需要先配置环境变量: 先找到java.exe和javac.exe所在的文件夹位置: 此电脑-& ...

最新文章

  1. UBUNTU : Destination Host Unreachable
  2. 10-Bootstrap Checksedit
  3. selenium中CSS选择器定位
  4. 关于如果减少勒索病毒的侵扰:
  5. Android-Intent界面跳转
  6. 用户常见的问题以及特殊技术问题
  7. PHP+MySQL实现读写分离
  8. hdu 4928 Series 2 (优化+模拟)
  9. seay代码审计mysql插件报错_Seay源代码审计系统v2.0源码
  10. java ssm进销存源码,ssm进销存流程管理系统
  11. 分享一个超详细的数据分析案例【Python】附ABTest详细介绍
  12. IT软件工程师工作内容
  13. 如何用计算机基础知识提问,职业学校《计算机应用基础》课的提问策略
  14. 基于STM32F103的单相在线式不间断电源设计
  15. Outlook邮件服务器eas,配置Outlook使用Outlook.com和Hotmail的两步验证
  16. python封装exe后其他人能用么_python用tesseract写的图片识别,封装exe后,本机可以用,软件放别的电脑上无法图......
  17. WP Mail SMTP配置谷歌邮箱
  18. Git与GitFlow工具介绍
  19. 安川最小巧机器人_盘点日本最值得关注的工业机器人13大巨头!
  20. 怎样量化评价搜索引擎的结果质量

热门文章

  1. macOS Monterey 12.2.1 (21D62) 正式版 ISO、IPSW、PKG 下载
  2. 新站如何做到短时间内获得大量的seo流量?
  3. NR-DL PDSCH Resource allocation 下行资源分配
  4. data在python_Fake data的使用和产生 - Python篇
  5. 武神主宰中的科幻理论体系设定
  6. HDR视频生态系统纵览
  7. galgame序列号怎么查看_国行Switch能完整体验的游戏有哪些?Switch支架掉了怎么办? | Jump指南...
  8. PCL中采样一致性算法
  9. Linus 一生只为寻找欢笑(下)-转
  10. web python 取代js_web前端:JavaScript,只有你想不到