【连载】【FPGA黑金开发板】Verilog HDL那些事儿--低级建模的资源(六)

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

P7302380_thumb

2.5 低级建模的资源

低级建模有讲求资源的分配,目的是使用“图形”来提高建模的解读性。

clip_image002

图上是低级建模最基本的建模框图,估计大家在实验一和实验二已经眼熟过。功能模块(低级功能模块)是一个水平的长方形,而控制模块(低级控制模块)是矩形。组合模块,可以是任意的形状(随意正方形)。注意功能模块和控制模块都包含“模块名”和“.v文件名”,相反组合模块只含“.v文件名”。

每一个“低级建模资源"的任务如自身命名一样。功能模块的例子有“flash_module.v”,控制模块的例子有“run_module.v”,和 “mix_module.v”是组合模块。

一个完整的建模都是由图上的基本资源“组合再组合”。当然低级建模有一个问题,就是建模量很大,但是这个问题是见仁见智,因为不同的人都有不同的组合习惯。除此之外,低级建模有一个必须遵守的准则就是“一个功能模块(控制模块)仅有一个功能”

。为什么这个准则那么重要呢?

因为低级建模是利用“图形”来表达一个完整的模块。其中,模块与模块之间是以“信号”来表达关系。

clip_image004

假设一个例子:一个老板对一个员工命令。老板(控制模块),和员工(功能模块)。如果从另一种角度去思考 ,“老板发号”,“员工干活”。“连线”表示了他们是“宾主关系”。

clip_image006

又或者另一个例子:一个老员工对一个新手员工发号。在现实中,老员工是来打工的(功能模块),新手也是来打工的(功能模块)。但是老员工有时也需要新手来支持。如上框图,那么从“连接”上推断,结果即可“一目了然”,亦即“老手新手关系”

上面两个例子,表示了我非常提倡“一个功能模块(控制模块)仅有一个功能”。因为如此,会大大的提升解读性,初次之外也使得建模更容易更多样化。

单单两个例子是无法说明白“低级建模”的好处,我们以一个简单实验,从设计中理解。

实验三:消抖模块之一

clip_image008

图上是一个简单的按键消抖模块。设计的方法主要是由“电平检查模块”和“10ms延迟模块”组合合成。

设计的思路如下:

1)一但检测到按键资源按下(高电平到低电平变化),“电平检查模块” 就会拉高

H2L_Sig电平,然后拉低。

2)“10ms延迟模块”,检测到H2L_Sig 高电平,就会利用10ms过滤H2L_Sig,拉高

输出

3)当按键被释放“电平检测模块”,会拉高L2H_Sig 电平,然后拉低。

4)“10ms延迟模块”,检查到L2H_Sig就会利用10ms过滤H2L_Sig,然后拉低输出。

实验三源码:

clip_image010

clip_image011

clip_image013

clip_image014

clip_image016

实验三说明:

detect_module.v 是电平检测的功能模块。14行定义了100us的常量,而第18~30行是用于延迟100us。因为电平检测模块是非常敏感,在复位的一瞬间,电平容易处于不稳定的状态。isEn = 1 寄存器是表示100us的延迟已经完成(28行)。

第34~37行,声明了四个寄存器。H2L_F1,H2L_F2,是针对检测电平由高变低。相反的L2H_F1,L2H_F2,则是针对检测电平由低变高。在41~46行,对各个寄存器初始化了,由于H2L_FX是为了检测由高变低的电平,所以初始化位逻辑1。L2H_FX 是为了检测由低变高的电平,初值被设置为逻辑0。

//初始化

H2L_F1 <= 1'b1;

H2L_F2 <= 1'b1;

//每一个时间的操作

H2L_F1 <= Pin_In;

H2L_F2 <= H2L_F1;

//每一个时间的布尔运算输出

Pin_Out = H2L_F2 & !H2L_F1

上面代码是用来检测电平由高变低。H2L_F1和H2L_F2的初值都是逻辑1。假设第一个时间Pin_In 为低电平,H2L_F1就会被赋值位逻辑0,而H2L_F1则是被赋值为H2L_F1上一个时间的值(也就是H2L_F1的初值)。

我们知道在第一个时间,H2L_F1为逻辑0, H2L_F2位逻辑1。由于对H2L_F1的取反操作,H2L_F1与H2L_F2“求与”运算,所以这个表达式的输出是逻辑1。

再假设第二个时间Pin_In保持为低电平,H2L_F1同样会被赋值为逻辑0, 而H2L_F2则是被赋值为H2L_F1上一个时间的值,亦即逻辑0 (第一个时间的值)。再经过布尔表达式的运算, 在第二个时间,H2L_F1 是逻辑0, H2L_F2是逻辑0, 所以输出的结果是逻辑0.

时间

H2L_F1

H2L_F2

Pin_Out = H2L_F2 ( !H2L_F1 )

Initial

1

1

0

T1

0

1

1

T2

0

0

0

第48~53行,正是执行如上的操作,无论是检测电平由高变低或者由低变高,思路基本都是一样。而最后的58~59行,是关于“电平检测”的布尔表达式。但是有一点不同的是,Pin_Out的输出,是发生在100us之后,因为100us之前被 isEn寄存器所限制(原因之前已经说了)。换一句话说,电平检测的有效是100us的延迟之后。

delay_module.v 是10ms延迟的功能模块。模块采用“仿顺序操作”的编写方式(第四章)。第16~42行是“延迟”的写法,第18~28行是1ms的定时器,而第32~40行是计数器。无论是定时器或者计数器都是由 isCount 标志寄存器使能。

第44~71行是“仿顺序操作”(第四章),第46行 i 寄存器用来控制执行的步骤。开始的时候i会根据“H2L_Sig”或者“L2H_Sig”进入不同的步骤(58~60行)。从62~64,或者66~68行,都是延迟10ms的操作,不同的地方就只有 rPin_Out 寄存器的赋值(63行与67行)。

我们先简单的了解一下地44~71行的设计思路:

1)如果H2L_Sig 信号有反应,就进入步骤1,

2)在进入步骤1之后,由于达不到if条件, isCount使能。定时器,计数器呀开始执行。

3)在经过10ms之后,isCount不使能,定时器,计数器停止执行。rPin_Out为逻辑1

。返回步骤0。

又或者:

1)如果L2H_Sig 信号有反应,就进入步骤2,

2)在进入步骤2之后,由于达不到if条件, isCount使能。定时器,计数器呀开始执行。

3)在经过10ms之后,isCount不使能,定时器,计数器停止执行。rPin_Out为逻辑0

。返回步骤0。

Debounce_module.v 是组合模块。模块的组合上上图。信号连线的地方已经很清楚的注释。

完成框图:

clip_image018

实验三结论:

实验三是“功能模块对功能模块”的组合建模。建模方法遵守了“一个模块一个功能”的准则,在加上“图形”和“连线”的描述,以一种最直接的方式,很好的提升“完成模块”的“解读性”和设计的“可能性”。

当然“低级建模”的好处不止在这里而已,随着建模的工程度增加,就会越发的凸显“低级建模”的优势。

实验三配置

黑金版的FPGA型号:CYCLONE II EP2C8Q208C8

clip_image002

实验三所包含的.v文件。

clip_image004

编译成功后的层次关系。

clip_image006

实验三所使用的按键资源是KEY1。

clip_image008

扩展板

clip_image010

核心板

核心板和扩展板的链接关系。实验三使用的扩展板资源是KEY1, 亦即PIN3。

clip_image012

实验3使用的LED资源是LED1,亦即PIN69。

clip_image014

引脚配置如上。关于CLK和RSTn的引脚配置就不再重复了。

clip_image016[6]

完成后扩展图。

实验四:消抖模块之二

clip_image020

实验四和实验三的区别,就是输出。实验三的debounce_modulve.v 当检测到由高变低的电平变化时就拉高输出,然而当检查到由低变高的电平变化时拉低输出。实验四的debounce_module.v 当检测到由高变低的电平变化时,拉高输出一个时钟的时间,然后拉低输出。当检测到由低变高的电平变化时,只有消抖动作,输出没有任何影响。

实验四源码:

clip_image022

实验四说明:

大部分的源码和实验三一样,不同的地方就在于delay_module.v的“仿顺序操作”代码段。从上面的代码可以看到,当检测到由高变低的电平变化的时候(第59行),步骤i就进入,步骤1。经延迟10ms过后,拉高输出,然后进入步骤2。步骤2会拉高拉低电平,然后回到步骤0。同样的,在步骤0当检测到由低变高的电平变化是,就会进入步骤3,经延迟10ms过后,就会返回步骤0。

posted on 2010-08-29 12:03  FPGA黑金开发板  阅读(2165)  评论(4编辑  收藏  举报