在这章开始,笔记不再讨论“低级建模”相关的基础了,在前几章笔记已经说过,“低级建模”为“后期准备”的影响力是可大可小。在这里我们先讨论这样一个话题:
一层高楼,我们必须从地基开始建起。第一楼的“地基”必须稳固,而且结构必须良好。不然的话,第二楼的建筑工作就有困难。
Verilog HDL 语言的建模就是这样一回事,早期的模块建模,我们只是针对每一个硬件资源,建立一个“基础”而已。这个“基础”虽然可以调用,但是却不是真正的完成品。
然而每一个“基础”的最后工程就是所谓的“封装”。
“封装”的定义可以是很多,但是笔者把它看为是“建模的最后工程”。我们知道每一个建筑物都需要地基,但是完成地基不代表完成建筑。
请回忆一下,在实验三和实验四是我们不是建立了“按键消抖”的功能模块。估计读者们在早期可能会误会“就这样简单?实验就完了?”。实验三和实验四就宛如“按键的地基”而已,因为“消抖功能”对按键来说是必须拥有的。但是在实验三和实验四却没有针对黑金开发板上的“按键资源”,执行所谓“竣工”意义上的建模。
在针对某一个硬件资源的封装之前,不同的硬件资源都有不同的考虑。如黑金开发板上的5个独立按键,如果我要为它们封装的话,我们必须考虑什么?
(一)按键的功能 - 按键按下消抖,按键按下产生高脉冲,按键释放消抖。
(二)按键的数目 - 5个按键资源。
然而实验四的debounce_module2.v符合如上的功能,那么我们只要基于该模块,执行5次的的实例化再组合以后,就会完成“针对黑金开发板的独立按键”封装工作。
上图是基于实验四 debounce_module2.v 经过5次实例化后,再以 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 |
具体的内容,我们直接看源码。
在源码第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。
这个组合模块,也没有什么特别 ... 超级简单的。
这个演示主要是演示 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 中调用。这章的实验,对于封装来讲,算是最简单的一种吧。前面我都说了,不同的封装都有不同的考虑。把这个实验当成暖身吧。
文章评论(0条评论)
登录后参与讨论