zoukankan      html  css  js  c++  java
  • [笔记].独立按键消抖的改进.[Verilog]

    引子

    先前的[笔记].一种独立键盘消抖的Verilog写法.[Verilog]是针对4个按键写的。今天我略为改动下,改成参数化,已验证,非常好用。

    代码

    key_debounce.v
    module key_debounce
    #(parameter KEY_WIDTH = 4)
    (
      input                    i_clk,
      input                    i_rst_n,
      input      [KEY_WIDTH:1] i_key,       // 按下为0,松开为1
      output reg [KEY_WIDTH:1] o_key_val    // 键值
    );  
    
    //++++++++++++++++++++++++++++++++++++++
    reg [KEY_WIDTH:1] key_samp1, key_samp1_locked;
    
    // 将i_key采集至key_samp1
    always @ (posedge i_clk, negedge i_rst_n)
      if(!i_rst_n) 
        key_samp1 <= {KEY_WIDTH{1'b1}};
      else         
        key_samp1 <= i_key;
    
    // 将key_samp1锁存至key_samp1_locked
    always @ (posedge i_clk, negedge i_rst_n)
      if(!i_rst_n) 
        key_samp1_locked <= {KEY_WIDTH{1'b1}};
      else         
        key_samp1_locked <= key_samp1;
    //--------------------------------------
    
    //++++++++++++++++++++++++++++++++++++++
    wire [KEY_WIDTH:1] key_changed1;
    
    // 当key_samp1的某些位由1变为0时
    // key_changed1的某些位由0变为1,只维持一个时钟周期
    assign key_changed1 = key_samp1_locked & (~key_samp1); 
    //--------------------------------------
    
    
    //++++++++++++++++++++++++++++++++++++++
    reg [19:0] cnt;
    
    // 一旦有按键按下,cnt立即被清零
    always @ (posedge i_clk, negedge i_rst_n)
      if(!i_rst_n)
        cnt <= 20'h0;
      else if(key_changed1)
        cnt <= 20'h0;
      else
        cnt <= cnt + 1'b1;
    //--------------------------------------
    
    
    //++++++++++++++++++++++++++++++++++++++
    reg [KEY_WIDTH:1] key_samp2, key_samp2_locked;
    
    // 只有当按键不变化(不抖动),且维持20ms以上时
    // 才将i_key采集至key_samp2
    always @ (posedge i_clk, negedge i_rst_n)
      if(!i_rst_n)
        key_samp2 <= {KEY_WIDTH{1'b1}};
      else if(cnt == 20'hF_FFFF)            // 0xFFFFF/50M = 20.9715ms
        key_samp2 <= i_key;
    
    // 将key_samp2锁存至key_samp2_locked
    always @ (posedge i_clk, negedge i_rst_n)
      if(!i_rst_n)
        key_samp2_locked <= {KEY_WIDTH{1'b1}};
      else
        key_samp2_locked <= key_samp2;
    //--------------------------------------
    
    //++++++++++++++++++++++++++++++++++++++
    wire [KEY_WIDTH:1] key_changed2;
    
    // 当key_samp2的某些位由1变为0时
    // key_changed2的某些位由0变为1,只维持一个时钟周期
    assign key_changed2 = key_samp2_locked & (~key_samp2); 
    //--------------------------------------
    
    
    //++++++++++++++++++++++++++++++++++++++
    // 每次按键稳定后,输出键值
    // 按下为0,松开为1
    always @ (posedge i_clk, negedge i_rst_n)
      if(!i_rst_n)
        o_key_val <= {KEY_WIDTH{1'b1}};
      else
        o_key_val <= ~key_changed2;
    //--------------------------------------
    
    endmodule 

    解析

    关键是如何正确使用全局参数。第2行,在module名和moudule的I/O中间声明一些参量;同声明moudule的I/O一样,声明多个参量,使用逗号隔开;注意小括号末尾无需分号。第16行及以下类似行,先前是key_samp1 <= 4'hF,现在怎么写呢?复制KEY_WIDTH个1'b1即可:key_samp1_locked <= {KEY_WIDTH{1'b1}}。

    参考

    1 Quartus II->Edit->Insert Template..

  • 相关阅读:
    springCloud和docker笔记(1)——微服务架构概述
    gradle配置远程仓库(以及使用本地maven仓库)
    linux以及git和maven常用命令
    junit使用小结
    aop中获取方法的注解
    mysql使用总结
    mac的终端窗口的工作组的使用
    线性表试题中的操作代码
    echart与Accelerometer综合
    php与MySQL与echart综合使用
  • 原文地址:https://www.cnblogs.com/yuphone/p/1746035.html
Copyright © 2011-2022 走看看