amobbs.com 阿莫电子技术论坛

标题: 按键软件消抖(Verilog) [打印本页]

作者: tear086    时间: 2010-2-3 16:00
标题: 按键软件消抖(Verilog)
新近写的,水平有限,欢迎拍砖。

参考了特权的代码。http://group.ednchina.com/1375/21132.aspx

-------------------------------------------------
module key_debounce(
  input            i_clk,
  input            i_rst_n,
  input      [4:1] i_key,               // 按下为0,松开为1
  output reg [4:1] o_key_val            // 键值
);  

//++++++++++++++++++++++++++++++++++++++
reg [4:1] key_samp1, key_samp1_locked;

// 将i_key采集至key_samp1
always @ (posedge i_clk, negedge i_rst_n)
begin
  if(!i_rst_n)
    key_samp1 <= 4'hF;
  else         
    key_samp1 <= i_key;
end

// 将key_samp1锁存至key_samp1_locked
always @ (posedge i_clk, negedge i_rst_n)
begin
  if(!i_rst_n)
    key_samp1_locked <= 4'hF;
  else         
    key_samp1_locked <= key_samp1;
end
//--------------------------------------

//++++++++++++++++++++++++++++++++++++++
wire [4: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)
begin
  if(!i_rst_n)
    cnt <= 20'h0;
  else if(key_changed1)
    cnt <= 20'h0;
  else
    cnt <= cnt + 1'b1;
end
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
reg [4:1] key_samp2, key_samp2_locked;

// 只有当按键不变化(不抖动),且维持20ms以上时
// 才将i_key采集至key_samp2
always @ (posedge i_clk, negedge i_rst_n)
begin
  if(!i_rst_n)
    key_samp2 <= 4'hF;
  else if(cnt == 20'hF_FFFF)            // 0xFFFFF/50M = 20.9715ms
    key_samp2 <= i_key;
end

// 将key_samp2锁存至key_samp2_locked
always @ (posedge i_clk, negedge i_rst_n)
begin
  if(!i_rst_n)
    key_samp2_locked <= 4'hF;
  else
    key_samp2_locked <= key_samp2;
end
//--------------------------------------

//++++++++++++++++++++++++++++++++++++++
wire [4:1] key_changed2;

// 当key_samp2由1变为0时
// key_changed2由0变为1,且维持一个时钟周期
assign key_changed2 = key_samp2_locked & (~key_samp2);
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
// 每次按键稳定后,都将键值取反
always @ (posedge i_clk, negedge i_rst_n)
begin
  if(!i_rst_n)
    o_key_val <= 4'hF;
  else
  begin
    if(key_changed2[1])
      o_key_val[1] <= ~o_key_val[1];
      
    if(key_changed2[2])
      o_key_val[2] <= ~o_key_val[2];
      
    if(key_changed2[3])
      o_key_val[3] <= ~o_key_val[3];
      
    if(key_changed2[4])
      o_key_val[4] <= ~o_key_val[4];
  end
end
//--------------------------------------

endmodule

-------------------------------------------------
作者: ngzhang    时间: 2010-2-3 16:19
按键旁边并俩电容。
作者: acer    时间: 2010-2-3 18:26
不错
作者: acer    时间: 2010-2-3 18:28
不错
作者: abs123    时间: 2010-2-16 14:03
学习一下,谢谢LZ
作者: kv2004    时间: 2010-2-16 17:02
我是这样想的,写起来似乎更清楚一点
1 计数器每计到20位,溢出时缓冲按键,旧的缓冲向后移动,一共2级缓冲;
2 当某一位的二级缓冲加上当前按键的值是3'b011 (假设“1”表示有按键),则输出“1”,否则“0”
作者: lmldai    时间: 2010-3-10 20:59
新手上路,学习了~
作者: lzc520xm    时间: 2010-3-12 17:01
正需要这个
作者: feegle    时间: 2010-3-16 21:21
感觉好复杂哦
作者: elcwoo    时间: 2010-3-19 16:05
我用的VHDL的源码,感觉差不多,也是判断按下时间的
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity debounce is
port(
key_pressed:in std_logic;--key_pressed
clk: in std_logic;--clock for synchrony
key_valid: out std_logic);--key_valid
end debounce;
architecture behave of debounce is
begin
process(clk)
variable dbnq:std_logic_vector(5 downto 0);
begin
if (key_pressed='1')then
dbnq:="111111";--unkey_pressed,counter reset at 63
elsif(clk'event and clk='1')then
if dbnq/=1 then
dbnq:=dbnq-1;--key_pressed not enough along time
end if;      --counter still subtract one
end if;
if dbnq=2 then
key_valid<='1';--key_valid after key_pressed 63
else
key_valid<='0';--key_invalid
end if;
end process;
end behave;
分享一下
作者: lsw0136    时间: 2010-3-24 08:59
mark,study
作者: lyhlt520    时间: 2010-5-23 18:24
终于看懂了~谢谢~
作者: myhonour    时间: 2010-5-24 15:08
mark
作者: myhonour    时间: 2010-5-24 15:08
mark
作者: z295287653    时间: 2010-5-24 23:43
刚刚看懂了特权的按键消抖,不错不错。。
作者: marrt.80    时间: 2010-5-26 23:30
mark
作者: yealien    时间: 2010-5-27 13:53
哪位大哥能帮忙解释一下这一句是什么意思?“else if(cnt == 20'hF_FFFF)  // 0xFFFFF/50M = 20.9715ms ”
小弟刚学,见笑了!20‘hF_FFFF为什么中间有下划线?这是代表什么意思呢?
作者: tear086    时间: 2010-5-27 14:33
回复【16楼】yealien  
-----------------------------------------------------------------------

下划线不影响使用,区分之后更好数嘛。
作者: yealien    时间: 2010-5-27 15:33
多谢楼主,再请教一下,“0xFFFFF/50M = 20.9715ms ”中50M是什么意思呢?为什么0xFFFFF除以50M就等于20.9715ms ?不知可否帮忙解答一下?多谢了!
作者: yealien    时间: 2010-5-30 10:47
不知还有谁可以帮手解答一下,“,“0xFFFFF/50M = 20.9715ms ”中50M是什么意思呢?为什么0xFFFFF除以50M就等于20.9715ms ”,多谢了!确实看不懂。
作者: tear086    时间: 2010-5-30 10:55
回复【19楼】yealien  
-----------------------------------------------------------------------

呵呵,板载晶振是50MHz的;那么1sec就可以分为50M个ticks;于是0xF_FFFF=1,048,575;1,048,575/50,000,000 = 0.020,971,5sec = 20.971,5msec。这是分频的惯用技俩,可以看看这里:
http://www.cnblogs.com/yuphone/archive/2010/02/08/1666130.html

另外这个简单例程,我又做了一点修改,改为参数化的。
http://www.cnblogs.com/yuphone/archive/2010/05/28/1746035.html
作者: hefq    时间: 2010-5-30 14:03
不知道,向你学习
作者: tear086    时间: 2010-5-30 15:19
回复【21楼】hefq  何访贤
-----------------------------------------------------------------------
弓虽。知道HDL什么吗?我很无语。
作者: yealien    时间: 2010-5-31 14:05
新手再顶!多谢指点!
作者: yealien    时间: 2010-5-31 14:45
楼主,为什么你算出0xF_FFFF=1,048,575 ?我算出来不是这个数啊?65536+4096+256+16+1=69,905,
作者: tear086    时间: 2010-5-31 15:20
回复【24楼】yealien  
-----------------------------------------------------------------------

吓我一跳,真以为我又出丑了。我用我的CASIO按了好几次,没错。0xF_FFFF = 15*16^0 + 15*16^1 + 15*16^2 + 15*16^3 + 15*16^4 = 1048575。
作者: yealien    时间: 2010-5-31 18:00
刚才看了一个书,我算错了,惭愧!
多谢楼主指点!
作者: liushizhe    时间: 2010-6-5 23:40
延时20ms是不是太长了,你这好像只有按下消抖,没有弹起消抖
作者: tianxingjian    时间: 2010-6-19 21:20
当初学FPGA的时候,看了周立功的按键消抖verilog代码。硬件测试无问题,原理不是延时,而是用一系列的移位寄存器将信号移入,然后判断各个寄存器的值是否相同,相同的话则证明是有键按下,好像当时移位寄存器的时钟是20M,效果不错,而且代码很简单。等找到程序后再贴上。
作者: wxx116zh    时间: 2010-6-20 21:04
mark
作者: ly520cs    时间: 2010-6-20 22:51
mark
作者: lxb007    时间: 2011-11-11 15:58
马克
作者: zidingl1    时间: 2011-11-12 12:22
很好, 谢谢楼主的
作者: skyxjh    时间: 2013-4-19 00:23
多次检测比较消抖
作者: lcrromi    时间: 2013-5-6 13:48
好吧,献上一个精简版的
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity stable_key is
port(
     clk:in std_logic;
     key_in:in std_logic;
     key_out:out std_logic
     );
end stable_key;


architecture fun of stable_key is
signal cnt:integer range 0 to 1999999;
signal key,key_d:std_logic;
begin
   
process(clk)
   
begin
    if clk'event and clk='1' then
      if key/=key_in then
         key_d<=key_in;
         cnt<=0;
      elsif cnt=1999999 then
         key_out<=not key_d;
         cnt<=0;
      else
         cnt<=cnt+1;
      end if;
      key<=key_in;
    end if;
end process;
end;
作者: zhengtn03    时间: 2013-5-11 20:41
module debounce(clk,key_i,key_o);
    input clk;
    input key_i;
    output key_o;

    parameter NUMBER = 10086000;
    parameter NBITS = 24;

    reg [NBITS-1:0] count;
    reg key_o_temp;

    reg key_m;
        reg key_i_t1,key_i_t2;

    assign key_o = key_o_temp;
       
        always @ (posedge clk) begin
                key_i_t1 <= key_i;
                key_i_t2 <= key_i_t1;
        end

    always @ (posedge clk) begin
        if (key_m!=key_i_t2) begin
            key_m <= key_i_t2;
            count <= 0;
        end
        else if (count == NUMBER) begin
            key_o_temp <= key_m;
        end
        else count <= count+1;
    end
endmodule

作者: gyth_lx    时间: 2013-5-14 16:20
记得以前看过一个巨精简的,直接以50Hz频率检测键盘按键,一般抖动是不响应的。。。
作者: 7802848    时间: 2013-5-15 14:03
说实话,很烂
作者: tennokoe    时间: 2013-5-15 15:14
这是条邪路啊……




欢迎光临 amobbs.com 阿莫电子技术论坛 (https://www.amobbs.com/) Powered by Discuz! X3.4