搜索
bottom↓
回复: 39
打印 上一主题 下一主题

按键软件消抖(Verilog)

[复制链接]

出0入0汤圆

跳转到指定楼层
1
发表于 2010-2-3 16:00:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
新近写的,水平有限,欢迎拍砖。

参考了特权的代码。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

-------------------------------------------------

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

2
发表于 2010-2-3 16:19:02 | 只看该作者
按键旁边并俩电容。

出0入0汤圆

3
发表于 2010-2-3 18:26:10 | 只看该作者
不错

出0入0汤圆

4
发表于 2010-2-3 18:28:22 | 只看该作者
不错

出0入0汤圆

5
发表于 2010-2-16 14:03:58 | 只看该作者
学习一下,谢谢LZ

出0入12汤圆

6
发表于 2010-2-16 17:02:26 | 只看该作者
我是这样想的,写起来似乎更清楚一点
1 计数器每计到20位,溢出时缓冲按键,旧的缓冲向后移动,一共2级缓冲;
2 当某一位的二级缓冲加上当前按键的值是3'b011 (假设“1”表示有按键),则输出“1”,否则“0”

出0入0汤圆

7
发表于 2010-3-10 20:59:39 | 只看该作者
新手上路,学习了~

出0入0汤圆

8
发表于 2010-3-12 17:01:03 | 只看该作者
正需要这个

出0入0汤圆

9
发表于 2010-3-16 21:21:19 | 只看该作者
感觉好复杂哦

出0入0汤圆

10
发表于 2010-3-19 16:05: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;
分享一下

出0入0汤圆

11
发表于 2010-3-24 08:59:47 | 只看该作者
mark,study

出0入0汤圆

12
发表于 2010-5-23 18:24:45 | 只看该作者
终于看懂了~谢谢~

出0入0汤圆

13
发表于 2010-5-24 15:08:39 | 只看该作者
mark

出0入0汤圆

14
发表于 2010-5-24 15:08:55 | 只看该作者
mark

出0入0汤圆

15
发表于 2010-5-24 23:43:00 | 只看该作者
刚刚看懂了特权的按键消抖,不错不错。。

出0入0汤圆

16
发表于 2010-5-26 23:30:13 | 只看该作者
mark

出0入0汤圆

17
发表于 2010-5-27 13:53:04 | 只看该作者
哪位大哥能帮忙解释一下这一句是什么意思?“else if(cnt == 20'hF_FFFF)  // 0xFFFFF/50M = 20.9715ms ”
小弟刚学,见笑了!20‘hF_FFFF为什么中间有下划线?这是代表什么意思呢?

出0入0汤圆

18
 楼主| 发表于 2010-5-27 14:33:42 | 只看该作者
回复【16楼】yealien  
-----------------------------------------------------------------------

下划线不影响使用,区分之后更好数嘛。

出0入0汤圆

19
发表于 2010-5-27 15:33:53 | 只看该作者
多谢楼主,再请教一下,“0xFFFFF/50M = 20.9715ms ”中50M是什么意思呢?为什么0xFFFFF除以50M就等于20.9715ms ?不知可否帮忙解答一下?多谢了!

出0入0汤圆

20
发表于 2010-5-30 10:47:33 | 只看该作者
不知还有谁可以帮手解答一下,“,“0xFFFFF/50M = 20.9715ms ”中50M是什么意思呢?为什么0xFFFFF除以50M就等于20.9715ms ”,多谢了!确实看不懂。

出0入0汤圆

21
 楼主| 发表于 2010-5-30 10:55:21 | 只看该作者
回复【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

出0入0汤圆

22
发表于 2010-5-30 14:03:58 | 只看该作者
不知道,向你学习

出0入0汤圆

23
 楼主| 发表于 2010-5-30 15:19:03 | 只看该作者
回复【21楼】hefq  何访贤
-----------------------------------------------------------------------
弓虽。知道HDL什么吗?我很无语。

出0入0汤圆

24
发表于 2010-5-31 14:05:25 | 只看该作者
新手再顶!多谢指点!

出0入0汤圆

25
发表于 2010-5-31 14:45:38 | 只看该作者
楼主,为什么你算出0xF_FFFF=1,048,575 ?我算出来不是这个数啊?65536+4096+256+16+1=69,905,

出0入0汤圆

26
 楼主| 发表于 2010-5-31 15:20:58 | 只看该作者
回复【24楼】yealien  
-----------------------------------------------------------------------

吓我一跳,真以为我又出丑了。我用我的CASIO按了好几次,没错。0xF_FFFF = 15*16^0 + 15*16^1 + 15*16^2 + 15*16^3 + 15*16^4 = 1048575。

出0入0汤圆

27
发表于 2010-5-31 18:00:57 | 只看该作者
刚才看了一个书,我算错了,惭愧!
多谢楼主指点!

出0入0汤圆

28
发表于 2010-6-5 23:40:38 | 只看该作者
延时20ms是不是太长了,你这好像只有按下消抖,没有弹起消抖

出0入0汤圆

29
发表于 2010-6-19 21:20:39 | 只看该作者
当初学FPGA的时候,看了周立功的按键消抖verilog代码。硬件测试无问题,原理不是延时,而是用一系列的移位寄存器将信号移入,然后判断各个寄存器的值是否相同,相同的话则证明是有键按下,好像当时移位寄存器的时钟是20M,效果不错,而且代码很简单。等找到程序后再贴上。

出0入0汤圆

30
发表于 2010-6-20 21:04:26 | 只看该作者
mark

出0入0汤圆

31
发表于 2010-6-20 22:51:01 | 只看该作者
mark

出0入0汤圆

32
发表于 2011-11-11 15:58:11 | 只看该作者
马克

出0入0汤圆

33
发表于 2011-11-12 12:22:16 | 只看该作者
很好, 谢谢楼主的

出0入0汤圆

34
发表于 2013-4-19 00:23:34 | 只看该作者
多次检测比较消抖

出0入0汤圆

35
发表于 2013-5-6 13:48:29 | 只看该作者
好吧,献上一个精简版的
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;

出0入0汤圆

36
发表于 2013-5-11 20:41:54 | 只看该作者
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

出0入0汤圆

37
发表于 2013-5-14 16:20:43 | 只看该作者
记得以前看过一个巨精简的,直接以50Hz频率检测键盘按键,一般抖动是不响应的。。。

出0入0汤圆

38
发表于 2013-5-15 14:03:34 | 只看该作者
说实话,很烂

出0入0汤圆

39
发表于 2013-5-15 15:14:33 | 只看该作者
这是条邪路啊……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 08:03

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表