• (转载)FPGA基础篇底层模块分析(延迟防抖)


    本篇博客转载来源于http://www.cnblogs.com/kingst/,仅供学习。

    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。

  • 相关阅读:
    浅谈独立使用NDK编译库文件(Android)
    Ubuntu 13.04 安装使用clang
    一道TOPK问题
    exp-00091 oracle错误的解决办法
    win32多线程程序设计笔记(第四章下)
    数据库索引的实现原理 (转)
    [置顶] linux常用命令手册
    ZigBee研究之旅(二)
    java中length,length(),size()区别
    浅谈href=#与href=javascript:void(0)的区别
  • 原文地址:https://www.cnblogs.com/yingfang18/p/1896555.html
Copyright © 2020-2023  润新知