原创 【连载】【FPGA黑金开发板】Verilog HDL那些事儿--独立按键封装(十五)

2010-12-17 13:11 2331 6 6 分类: FPGA/CPLD

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

第五章:低级建模-封装(接口建模)

在这章开始,笔记不再讨论“低级建模”相关的基础了,在前几章笔记已经说过,“低级建模”为“后期准备”的影响力是可大可小。在这里我们先讨论这样一个话题:

一层高楼,我们必须从地基开始建起。第一楼的“地基”必须稳固,而且结构必须良好。不然的话,第二楼的建筑工作就有困难。

Verilog HDL 语言的建模就是这样一回事,早期的模块建模,我们只是针对每一个硬件资源,建立一个“基础”而已。这个“基础”虽然可以调用,但是却不是真正的完成品。

然而每一个“基础”的最后工程就是所谓的“封装”。

“封装”的定义可以是很多,但是笔者把它看为是“建模的最后工程”。我们知道每一个建筑物都需要地基,但是完成地基不代表完成建筑。

5.1 实验十四 - 独立按键封装

请回忆一下,在实验三和实验四是我们不是建立了“按键消抖”的功能模块。估计读者们在早期可能会误会“就这样简单?实验就完了?”。实验三和实验四就宛如“按键的地基”而已,因为“消抖功能”对按键来说是必须拥有的。但是在实验三和实验四却没有针对黑金开发板上的“按键资源”,执行所谓“竣工”意义上的建模。

 

 

 

在针对某一个硬件资源的封装之前,不同的硬件资源都有不同的考虑。如黑金开发板上的5个独立按键,如果我要为它们封装的话,我们必须考虑什么?

(一)按键的功能 - 按键按下消抖,按键按下产生高脉冲,按键释放消抖。

(二)按键的数目 - 5个按键资源。

然而实验四的debounce_module2.v符合如上的功能,那么我们只要基于该模块,执行5次的的实例化再组合以后,就会完成“针对黑金开发板的独立按键”封装工作。

 

 

上图是基于实验四 debounce_module2.v 经过5次实例化后,再以 key_interface.v 组合模块执行封装而成的“按键接口”。

key_interface.v

上面代码就是利用实验四的debounce_module2.v 多次实例化的结果。

 Key_In[4..0] 和 Key_Out[4..0] 位分配的如下。

按键资源

Key_In[4..0]

Key_Out[4..0]

↑上

Key_In[4]

Key_Out[4]

↓下

Key_In[3]

Key_Out[3]

←左

Key_In[2]

Key_Out[2]

→右

Key_In[1]

Key_Out[1]

·中

Key_In[0]

Key_Out[0]

实验十四演示:

实验十四演示,是利用5位按键分别去调制“可调PWM模块”。我们知道按键接口的作用,就是除了按键消抖以外,每当按下某一个按钮,某一个输出就是输出一个高脉冲。

在这个演示中,最陌生应该是 optional_pwm_module.v 这个模块吧。

“可调PWM模块”笔者在初期的笔记打算加入的,但是考虑到初期的问题,才延后到这里。PWM实验对于Verilog HDL 语言来说是一个经典的实验。那么什么是PWM,我们来简单认识一下:

 

 1k频率:

 

 

 T = 1 / f = 1 / 1k = 1ms

 

 1/100 个PWM块 = 1ms / 100 = 10us

 

 

 10 % PWM = 10 x 10us = 100 us

 50 % PWM = 50 x 10us = 500 us

 80 % PWM = 80 x 10us = 800 us

 

 

PWM信号在宏观上是拥有不同占空比比率的信号周期。从上图我们可以看到,假设我要求1k的频率方波信号,那么一个周期就是 1ms 。再假设我求得占空比的比率是可以从1~100%之间调节,那么我必须将一个周期的时间再分为 100 份,亦即 10us 一个PWM块。

上图中指示了3个不同占空比的PWM信号:

10% PWM信号,高电平保持时间 100us, 低电平保持时间 900us。

50% PWM信号,高电平保持时间 500us, 低电平保持时间 500us。

80% PWM信号,高电平保持时间 800us, 低电平保持时间 200us。

PWM信号在电流(电压)的调节上是非常方便的。一些简单的计算可以是如下:

假设某输出口的驱动能力是10mA,当仅有10% PWM 的情况下,驱动能力降落仅剩原有的10%能力,亦即 1mA。

在实验十四的演示中,利用optional_pwm_module.v 控制对 LED 发光亮度。然而不同的是,optional_pwm_module.v 虽然是1k的输出频率,但是PWM块分为256份(0~255),而不是典型的100份PWM块。

T = 1 / f = 1 / 1k = 1ms

256份PWM块 = 1ms / 256 = 3.9us

如果以20Mhz的频率产生 3.9us的定时:

N = ( 3.9E-6 ) / ( 1 / 20 E+6 )

  = 78.125

  = 78

===================================================================

我们知道 key_interface.v的 Key_In[4..0] 和 Key_Out[4..0] 位分配是如下:

[4]Up(Button)  [3]Down(Button)  [2]Left(Button)  [1]Right(Button)  [0]Middle(Button)

我们以key_interface.v的位分配,针对optional_pwm_module.v 的PWM调节如下:

位分配

按键映射

optional_pwm_module.v 的调节功能

[4]

Up(Button)

PWM块 +10

[3]

Down(Button)

PWM块 -10

[2]

Left(Button)

PWM块 -1

[1]

Right(Button)

PWM块 +1

[0]

Middle(Button)

PWM块1/2

具体的内容,我们直接看源码。

optional_pwm_module.v

在源码第11行,定义了以20Mhz频率定时3.9us 的常量。15~23行是3.9us的定时器。

第27~35行是256块PWM的计数器。37~70行是该模块的核心功能:

当 Option_Key(亦即 key_interface.v Key_Out 的连线口)其中某一位产生高脉冲的时候,都会有各种的功能, 37~70行简略下,功能如下表:

key_interface.v

Key_Out[4..0]

optional_pwm_module.v

Option_Key[4..0]

按键映射

功能

[4]

[4]

Up

PWM块 +10

[3]

[3]

Down

PWM块 -10

[2]

[2]

Left

PWM块 -1

[1]

[1]

Right

PWM块 +1

[0]

[0]

Middle

PWM块 1/2

寄存器 Option_Seg 表示了可调节的PWM块。假设 Option_Seg 的值调节至 127, 已经是 127 / 255 也就是 50% PWM。

然而寄存器 System_Seg 是自动递增的 PWM块,每 3.9us 定时 System_Seg 就会自动递增(34~35行)。当 System_Seg 从0值递增至255值,这就表示 3.9us x 256 = 1ms ,亦即一个周期已经计数完毕。然后又从下一个周期开始计数。(32~33行)

假设我要产生 50 % PWM的信号,必然 Option_Seg 的值必须调制 127。然后再经72行表达式的关系,就会产生50%占空比的PWM信号,PWM产生过程如下:

当 System_Seg 计数器从 0 ~ 127 递增的时候,由于 72行的表达式 ( System_Seg < Option_Seg ) 的关系,在 System_Seg 计数器的值在 0~127之间,LED的输出都是高电平。当System_Seg 计数器的值递增超过 127之后,亦即 128~255 之间,LED的输出都是低电平。

 

 

 

 

左图是 72 行表达式的关系图,Option_Seg 可以看成是一个比对常量,当 System_Seg 小于Option_Seg 常量值 LED的输出是高电平。当System_Seg 的值超过Option_Seg的常量值,LED的输出就是低电平。

在这里我们稍微来讨论46~68行的功能。

当 Option_Key[4] 产生一个高脉冲,如果 Option_Seg 的值小于 245,那么 Option_Seg 的值就增加 10 。反之如果 Option_Seg 的值大于 245,Option_Seg 就直接赋予255。

当 Option_Key[3] 产生一个高脉冲,如果 Option_Seg 的值大于 9,那么 Option_Seg 的值就减少 10 。反之如果 Option_Seg 的值小于 9,Option_Seg 就直接赋予0。

当 Option_Key[2] 产生一个高脉冲,如果 Option_Seg 的值小于 255,那么 Option_Seg 的值就增加 1 。反之如果 Option_Seg 的值大于等于255,Option_Seg 就直接赋予255。

当 Option_Key[1] 产生一个高脉冲,如果 Option_Seg 的值大于 0,那么 Option_Seg 的值就减少 1 。反之如果 Option_Seg 的值小于等于 0,Option_Seg 就直接赋予0。

当 Option_Key[0] 产生一个高脉冲,Option_Seg 就直接赋予127。

exp14_demo.v

这个组合模块,也没有什么特别 ... 超级简单的。

实验十四演示说明:

这个演示主要是演示 key_interface.v 如何调用而已。然而 key_interface.v 调用的重点就是在于 Key_Out[4..0] 每个位的为分配。

完成扩展图:

key_interface.v

 

 

key_interface_demo.v

实验十四演示结论:

这个实验比较简单,主要是利用实验四的debounce_module2.v 然后针对5位的按键资源执行实例化成为 key_interface.v ,然后在 key_interface_demo.v 中调用。这章的实验,对于封装来讲,算是最简单的一种吧。前面我都说了,不同的封装都有不同的考虑。把这个实验当成暖身吧。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条