现在的位置: 首页 > 综合 > 正文

【连载】【FPGA黑金开发板】Verilog HDL那些事儿–数码管封装(十六)

2012年09月01日 ⁄ 综合 ⁄ 共 3316字 ⁄ 字号 评论关闭

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

2

5.2 实验十五:数码管封装

数码管的驱动实验在实验七有干过了是吗,但是驱动和封装时不同一回事(5.1章说过了)。在实验七中,我曾经针对“十进制”“两位数码管”,去完成驱动的设计,但是在建模的过程中,我也付出许多昂贵的逻辑资源,因为在设计中涉及了“求余和除法”的数学符号。

 

实验七也仅是当当针对“两位数码管”而已,如果换做是“六位数码管”的封装动作,实验七的设计思路当然是行不通的。所以在这一章的实验,我们要充分的使用Verilog HDL语言强大的“位操作”来简化数码管的封装工作。

 

数码管位数

6

每一位停留时间

1 ms

一次性扫描时间

6 ms

扫描频率

166.67 Hz

(具体的内容请回顾3.1章)

 

上表是封装数码管所要求的属性。下面是封装的“图形”。

 

clip_image002

 

在上图的组合模块数码管接口smg_interface.v中,输入信号 Number_Sig 占了24位宽,然而Number_Sig 的位分配如下表:

 

Number_Sig[23:0]

位代表(从左边数起)

Number_Sig[23:20]

第一位 数字 | 数码管

Number_Sig[19:16]

第二位 数字 | 数码管

Number_Sig[15:12]

第三位 数字 | 数码管

Number_Sig[11:8]

第四位 数字 | 数码管

Number_Sig[7:4]

第五位 数字 | 数码管

Number_Sig[3:0]

第六位 数字 | 数码管

 

 

为什么每一位数字|数码管,都用4位位宽来代表呢?其实这个idea是来至ds1302芯片。

我们知道每数码管可以支持显示0~F,正是因为如此,如果我们用每4位位宽来代表某一个数码管显示的信号,那么我们就可以“免得使用除法或者求余运算符”。一来方便设计,而来减少资源。

 

举个例子:24'h123456, 亦即0001 0010 0011 0100 0101 0110

 

smg_encode_module.v在这里的功能就是就是将数字 0~F加码为数码管码 。然而,比较特别的是,smg_control_module.v smg_scan_module.v 有并行操作的性质。smg_interface.v 的大致操作如下:

 

假设我往 Number_Sig 输入 24'h123456

 

T1smg_control_module.v 会将 Number_Sig[23:20] 送往至 smg_encode_module.v加码并且送往数码管。在同一时间smg_scan_module.v 会扫描第一位数码管(使能)。

T2smg_control_module.v 会将 Number_Sig[19:16] 送往至 smg_encode_module.v加码并且送往数码管,在同一时间smg_scan_module.v 会扫描第二位数码管(使能)。

T3smg_control_module.v 会将 Number_Sig[15:12] 送往至 smg_encode_module.v加码并且送往数码管,在同一时间smg_scan_module.v 会扫描第三位数码管(使能)。

T4smg_control_module.v 会将 Number_Sig[11:8] 送往至 smg_encode_module.v加码并且送往数码管,在同一时间smg_scan_module.v 会扫描第四位数码管(使能)。

T5smg_control_module.v 会将 Number_Sig[7:4] 送往至 smg_encode_module.v加码并且送往数码管,在同一时间smg_scan_module.v 会扫描第五位数码管(使能)。

T6smg_control_module.v 会将 Number_Sig[3:0] 送往至 smg_encode_module.v加码并且送往数码管,在同一时间smg_scan_module.v 会扫描第六位数码管(使能)。

 

T1的时候第一位数码管会显示1。在T2的时候第二位数码管会显示2,其他的依此类推。最后在T6的时候,第六位数码管会显示6

就这样一次性的扫描(六位数码管全扫描)就完成。啊,别忘了!每位数码管扫描停留的时间(使能的时间)大约是1ms。所以一次性扫描所需要的时间大约是6ms,亦即在每一秒内,数码管会扫描166次左右。

smg_interface.v 具体的操作还是直接看源码吧。

smg_control_module.v

clip_image004

clip_image005

 

11行是1ms的常量,第15~23行则是 1ms 的定时器。第27~63行是该控制模块的核心部分。rNumber是每一位数字的暂存器(28行)用来驱动 Number_Data67行)。(39~61行)每隔1ms 该控制模块就会将不同位的数字往 Number_Data 输出。

smg_encode_module.v

clip_image007


clip_image008

smg_encode_module.v 和实验七相比更简化了许多。

smg_scan_module.v

clip_image010

 

clip_image011

同样和实验七相比,数码管扫描模块没有了“行扫描”的概念,而是简化至仅有“列扫描”。第10行是1ms的常量申明,在14~22行是1ms的定时器。该模块和smg_control_module.v 一样,都是每隔1ms都有一个动作。smg_scan_module.v 每隔1ms就会使能不同的拉(38~60行)。然而数码管实际的扫描顺序是自左向右。在位操作上,亦即,逻辑0从最高位到最低位移位。

smg_interface.v

clip_image013

 

clip_image014

实验十五说明:

这个实验也没有什么特别的,最重要还是得搞懂 Number_Sig 的位分配。

完成扩展图:

clip_image016

实验十五结论:

实验十五和实验十四不同的是,实验十四的 key_interface.v 我们要考虑如何调用它的输出,然而实验十五的 smg_interface.v 我们则要考虑输入调用它的输入。



实验十五演示:

clip_image018

 

上图是实验十五演示要实现的“图形”。演示中会建立一个名为 demo_control_module.v

输出24'h000000 ~ 24'h999999 用来驱动 smg_interface.v 的输入。具体的内容还是直接看代码:

demo_control_module.v

clip_image020

 

clip_image021

 

8~24行之间,包含了100ms定时的常量(10行)和100ms的定时器(14~22行)。

26~74就是该模块的核心部分。寄存器rNum 是用于24'h000000 位处理(27),然而rNumber是用于驱动 Number_Sig78行)。每隔100ms 的定时都会是 rNum 递增(41行),43~69行之间就会执行“4位宽”数字之间的“进位操作”。

我们假设一个情况,当rNum的值是24'h000009,然后在下一个100ms的定时钟,rNum的值就会 +1 操作。在44行,if条件就会成立 rNum[3:0]就会被赋值位零,然后rNum[7:4]就会执行 +1 操作,rNum的值成为 24'h000010。接下来的几个步骤也会执行类似的操作。

67~69行表示了当rNum的值超过 24'h999999的时候,就会恢复为 24'h000000

在这里我们有一个问题?为什么不使用 rNum 驱动 Number_Sig 而是选择使用 rNumber寄存器来驱动 Number_Sig。如果我们把 rNum 当着 Number_Sig 的驱动对象,在i步骤 1~7之间,由于“进位操作”的关系,会使得 Number_Sig 的输出产生许多毛刺。因为如此,才使用而外的寄存器,当rNum完成“进位操作”以后,再赋值与rNumber,由rNumber驱动 Number_Sig ( 72)

在同一个时间 i步骤会被复原,以期待另一次操作的开始。

smg_interface_demo.v

clip_image023

 

clip_image024

 

上面的内容就是组合模块 smg_interface _demo.v ,基本上和“图形”是一样的。自己看着办吧。

实验十五演示说明:

这个演示说明了如何调用 smg_interface.v 的输入,而且还说明了, 善用位操作会简化设计和建模。

 

完成的扩展图:

 

clip_image026

实验十五演示结论:

数码管接口的调用演示。

抱歉!评论已关闭.