zoukankan      html  css  js  c++  java
  • [笔记]再笔记边干边学Verilog HDL 003

    lab03 消抖模块之一

    image

    本实验是一个简单的按键消抖。主要由电平检测和10ms延时2个模块组成。

    以前,知道按键要消抖,但一直没做过。究其原因,可能是觉得麻烦,效果不炫,悲哀。无论如何,“出来混,总要还的”。咋消抖呢?大大们说,先检测电平变化,再将确定的变化延时输出。说起来简单,其中还有些小九九:

    1> 消的是什么抖?

    首先,要搞清楚,“抖”(跳变)是从哪里来的,最开始,我们的常识:按下按键,电平就变了。假设是由高变低。事实上,在按下的过程中,由于,按键大多是机械结构,就会产生轻微的跳变,瞬间(us级)跳变n次。也就是说这个瞬间,电平不是那么“干净”,所以就有了消抖的需求:期颐得到“干净”、确定的电平。这要求真不高,只是,俺以前直接无视了。

    2> 咋消?

    接着上面的按键的动作说,既然电平瞬间就由高变为我们要的低,那么,消抖就要在这个瞬间完成。首先,要知道按键想得到一个什么样的电平,就需要检测电平,而前面说了,电平有段时间是抖动的,干脆从100us之后开始检测,这样就忽略了抖动,(至于这100us是咋来的,科学吗?不晓得,做实验测试,还OK)。检测电平之后,判断出是高变低还是低变高,这个判断有需要很短的时间(ns级),然后,就是稳定的电平了,至此,我们得到了电平的确切变化动作,再加上一个延时模块,包含判断电平变化的时间,也就是akuei2说的“过滤”。这里用的10ms,够吗,当然够,为啥是10ms,不晓得,不过同样,实验可以验证。

    3> 设计思路

    (1)一旦检测到按键按下(高电平到低电平变化),“电平检查模块”就会拉高H2L_sig电平,然后拉低。

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

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

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

    代码

    detect_module.v

    1 /**
    2 * File name: detect_mocule.v
    3 *
    4 */
    5
    6 module detect_module
    7 (
    8 clk, rst_n, pin_in, H2L_sig, L2H_sig
    9 );
    10
    11 input clk;
    12 input rst_n;
    13 input pin_in;
    14 output H2L_sig;
    15 output L2H_sig;
    16
    17 parameter T100US = 13'd5000-1;
    18
    19 reg [12:0] count;
    20 reg isEn;
    21
    22 always @(posedge clk or negedge rst_n)
    23 if (!rst_n)
    24 begin
    25 count <= 13'd0;
    26 isEn <= 1'b0;
    27 end
    28 else if (count == T100US)
    29 isEn <= 1'b1;
    30 else
    31 count <= count + 1'b1;
    32
    33 reg H2L_F1;
    34 reg H2L_F2;
    35 reg L2H_F1;
    36 reg L2H_F2;
    37
    38 always @(posedge clk or negedge rst_n)
    39 if (!rst_n)
    40 begin
    41 H2L_F1 <= 1'b1;
    42 H2L_F2 <= 1'b1;
    43 L2H_F1 <= 1'b0;
    44 L2H_F2 <= 1'b0;
    45 end
    46 else
    47 begin
    48 H2L_F1 <= pin_in;
    49 H2L_F2 <= H2L_F1;
    50 L2H_F1 <= pin_in;
    51 L2H_F2 <= L2H_F1;
    52 end
    53
    54 assign H2L_sig = isEn ? (H2L_F2 & !H2L_F1) : 1'b0;
    55 assign L2H_sig = isEn ? (!L2H_F2 & L2H_F1) : 1'b0;
    56
    57 endmodule
    58

    这里isEn = 1寄存器是表示100us的延迟完成。电平检测模块的有效是发生在100us之后。

    delay_module.v

    1 /**
    2 * File name: delay_mocule.v
    3 *
    4 */
    5
    6 module delay_module
    7 (
    8 clk, rst_n, H2L_sig, L2H_sig, pin_out
    9 );
    10
    11 input clk;
    12 input rst_n;
    13 input H2L_sig;
    14 input L2H_sig;
    15 output pin_out;
    16
    17 parameter T1MS = 16'd50_000 - 1;
    18
    19 reg [15:0] count;
    20
    21 always @(posedge clk or negedge rst_n)
    22 if (!rst_n)
    23 count <= 16'd0;
    24 else if (isCount && count == T1MS)
    25 count <= 16'd0;
    26 else if (isCount)
    27 count <= count + 1'b1;
    28 else if (!isCount)
    29 count <= 16'd0;
    30
    31 reg [3:0] count_ms;
    32
    33 always @(posedge clk or negedge rst_n)
    34 if (!rst_n)
    35 count_ms <= 4'd0;
    36 else if (isCount && count == T1MS)
    37 count_ms <= count_ms + 1'b1;
    38 else if (!isCount)
    39 count_ms <= 4'd0;
    40
    41 reg isCount;
    42 reg rpin_out;
    43 reg [1:0] i;
    44
    45 always @(posedge clk or negedge rst_n)
    46 if (!rst_n)
    47 begin
    48 isCount <= 1'b0;
    49 rpin_out <= 1'b0;
    50 i <= 2'd0;
    51 end
    52 else
    53 case (i)
    54
    55 2'd0:
    56 if (H2L_sig) i <= 2'd1;
    57 else if (L2H_sig) i <= 2'd2;
    58
    59 2'd1:
    60 if (count_ms == 4'd10) begin
    61 isCount <= 1'b0;
    62 rpin_out <= 1'b1;
    63 i <= 2'd0;
    64 end
    65 else
    66 isCount <= 1'b1;
    67
    68 2'd2:
    69 if (count_ms == 4'd10) begin
    70 isCount <= 1'b0;
    71 rpin_out <= 1'b0;
    72 i <= 2'd0;
    73 end
    74 else
    75 isCount <= 1'b1;
    76
    77 endcase
    78
    79 assign pin_out = rpin_out;
    80
    81 endmodule
    82

    这里isCount是定时器和计数器的使能。由其控制10ms延时的开始。

    debounce_module.v

    1 /**
    2 * File name: debounce_mocule.v
    3 * Function: debounce module.
    4 * ------------------------------
    5 * Pins: KEY0-rst_n, KEY1-pin_in, LEDG8-pin_out
    6 *
    7 * Target board: DE2.
    8 * Software: Quartus II 9.1 sp1
    9 * ----------------------------
    10 * yf.x
    11 * 7-12-2011
    12 *
    13 */
    14
    15 module debounce_module
    16 (
    17 CLOCK_50, KEY, LEDG
    18 );
    19
    20 input CLOCK_50;
    21 input [1:0] KEY;
    22 output [8:8] LEDG;
    23
    24 wire H2L_sig;
    25 wire L2H_sig;
    26
    27 detect_module U1
    28 (
    29 .clk (CLOCK_50),
    30 .rst_n (KEY[0]),
    31 .pin_in (KEY[1]),
    32 .H2L_sig (H2L_sig),
    33 .L2H_sig (L2H_sig)
    34 );
    35
    36 delay_module U2
    37 (
    38 .clk (CLOCK_50),
    39 .rst_n (KEY[0]),
    40 .H2L_sig (H2L_sig),
    41 .L2H_sig (L2H_sig),
    42 .pin_out (LEDG[8])
    43 );
    44
    45 endmodule
    46
    47

    RTL图

    image

    小结

    本实验的目的是体验“低级建模”里的单模块单功能的建模准则。直观,方便人读。

  • 相关阅读:
    驱动Makefile
    ioremap
    file结构体
    Python基础-语法知识
    企业运营对 DevOps 的「傲慢与偏见」
    漂亮得不像实力派!
    如何用 OneAPM 优化你的 Node.js 应用?
    全球说:要给 OneAlert 点100个赞
    DevOps 和技术债务偿还自动化
    PHP 性能分析与实验(二)——PHP 性能的微观分析
  • 原文地址:https://www.cnblogs.com/halflife/p/2104355.html
Copyright © 2011-2022 走看看