Verilog实现按键消抖(状态机方法)

这篇具有很好参考价值的文章主要介绍了Verilog实现按键消抖(状态机方法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

按键抖动分析

Verilog实现按键消抖(状态机方法)
常用的轻触按键内部结构为金属弹片,在手按下、松开的过程中往往会发生细微抖动。
Verilog实现按键消抖(状态机方法)
输出的逻辑电平也会发生快速翻转,按键按下和释放的过程中,都会产生抖动,虽然时间非常短暂,但是对于单片机、FPGA这种实时性非常高的系统来说是不可接受的,为了保证系统能正确识别按键的开关,必须对按下和释放的过程进行滤波处理。
Verilog实现按键消抖(状态机方法)

按键消抖逻辑

和单片机消抖逻辑类似,FPGA可以通过两个计数器来对持续的高低电平进行计时,当达到一定的时间时,可以认为触点稳定,可以认为是一次有效的按下或释放,从而输出对应的信号。

Verilog设计与仿真

下面是基于Verilog状态机思路,使用两个计数器分别对按下和释放进行滤波处理,理论上按下和释放不会同时出现,所以使用一个计数器也可以实现的,为了便于理解,我们使用两个计数器分别对高低电平进行计时。

按键消抖驱动模块drv_key.v

/*********************************************************************
 * Copyright(C), 2010-2023, CSDN @ whik1194
 * ModuleName : drv_key.v 
 * Date       : 2023年2月20日
 * Time       : 21:26:01
 * Author     : https://blog.csdn.net/whik1194
 * Function   : drv_key
 * Version    : v1.0
 *      Version | Modify
 *      ----------------------------------
 *       v1.0    .....
 *********************************************************************/

module drv_key(
    //Inputs
    input clk,
    input rst_n,
    input key,
    
    //Outputs
    output flag_press,
    output flag_release
);

//parameter 
parameter KEY_PRESS   = 1'b0;       //按键按下有效
parameter FILTER_TIME = 27_000_0;   //按键消抖时间

//localparam 
localparam KEY_RELEASE = !KEY_PRESS;
localparam S0_IDLE = 0;
localparam S1_KEY_PRESS = 1;
localparam S2_KEY_RELEASE = 2;

//reg
reg [31:0] cnt_press;
reg [31:0] cnt_release;
reg [4:0] key_sreg;       //shift reg
reg [3:0] fsm;
reg en;

wire key_is_press   = (key_sreg[4:1] == {4{KEY_PRESS}});
wire key_is_release = (key_sreg[4:1] == {4{KEY_RELEASE}});
wire key_is_shake   = !(key_is_press || key_is_release);

//assign
assign flag_press   = (fsm == S1_KEY_PRESS);
assign flag_release = (fsm == S2_KEY_RELEASE);

//always 
//按键边沿捕获移位寄存器
always @ (posedge clk) begin
    if(!rst_n) begin
        key_sreg <= {5{KEY_RELEASE}};
    end
    else begin
        key_sreg <= key_sreg << 1 | key;
    end
end

always @ (posedge clk) begin
    if(!rst_n) begin
        fsm <= S0_IDLE;
        cnt_press   <= 0;
        cnt_release <= 0;
        en <= 0;
    end
    else begin
        case (fsm)
            S0_IDLE: begin
                if(key_is_shake) begin
                    cnt_press <= 'd0;
                    cnt_release <= 'd0;
                    en <= 1;
                end                
                else if(key_is_press && en) begin
                    if(cnt_press < FILTER_TIME)
                        cnt_press <= cnt_press + 1;
                    else begin
                        cnt_press <= 0; //max = FILTER_TIME
                        fsm <= S1_KEY_PRESS;
                    end
                end
                else if(key_is_release && en) begin
                    if(cnt_release < FILTER_TIME)
                        cnt_release <= cnt_release + 1;
                    else begin
                        cnt_release <= 0; //max = FILTER_TIME
                        fsm <= S2_KEY_RELEASE;
                    end
                end
                else begin
                    fsm <= fsm;
                    cnt_press   <= 0;
                    cnt_release <= 0;
                    en <= 0;
                end
            end
            
            S1_KEY_PRESS: begin
                fsm <= S0_IDLE;
                en <= 0; 
            end
            
            S2_KEY_RELEASE: begin
                fsm <= S0_IDLE;
                en <= 0; 
            end
            
            default: begin
                fsm <= fsm;
            end
        endcase
    end
end

endmodule   //get_key end

Modelsim仿真激励模块drv_key_tb.v

/*********************************************************************
 * Copyright(C), 2010-2023, CSDN @ whik1194
 * ModuleName : drv_key.v 
 * Date       : 2023年2月20日
 * Time       : 21:26:01
 * Author     : https://blog.csdn.net/whik1194
 * Function   : drv_key
 * Version    : v1.0
 *      Version | Modify
 *      ----------------------------------
 *       v1.0    .....
 *********************************************************************/

`timescale 1ns/1ps

module drv_key_tb;

localparam PERIOD = 10;      //ns
localparam KEY_PRESS   = 1'b0; 
localparam KEY_RELEASE = !KEY_PRESS;
localparam FILTER_TIME = 500;   

reg clk;
reg rst_n;
reg key;

always #(PERIOD/2) clk <= !clk;

initial begin
    $display("testbench: %s", drv_key_tb);
    
    rst_n = 0;
    clk = 0;
    key = KEY_RELEASE;
    
    #(PERIOD*100)
    rst_n = 1;
    #(PERIOD*1000)
    
    task_press;
    task_release;
    task_press;
    task_release;
   
end

drv_key #(
    .FILTER_TIME(FILTER_TIME)
)drv_key(
    //Inputs
    .clk(clk),
    .rst_n(rst_n),
    .key(key),
    
    //Outputs
    .flag_press(),
    .flag_release()
);

integer i;
task task_press;
begin
    @(posedge clk);
    for(i = 0; i <= 10; i = i + 1) begin
        key = KEY_PRESS;
        #(100*PERIOD);
        @(posedge clk);
        key = !key;
        #(100*PERIOD);
        @(posedge clk);
    end
    
    key = KEY_PRESS;
    #(FILTER_TIME*PERIOD)
    #(FILTER_TIME*PERIOD)
    @(posedge clk);
    
end
endtask

task task_release;
begin
    @(posedge clk);
    for(i = 0; i <= 10; i = i + 1) begin
        key = KEY_RELEASE;
        #(100*PERIOD);
        @(posedge clk);
        key = !key;
        #(100*PERIOD);
        @(posedge clk);
    end
    
    key = KEY_RELEASE;
    #(FILTER_TIME*PERIOD)
    #(FILTER_TIME*PERIOD)
    @(posedge clk);
    
end
endtask

endmodule   //drv_key_tb end

Modelsim仿真波形:
Verilog实现按键消抖(状态机方法)
实际调用也非常方便,只需要指定按键按下的电平状态和滤波的周期即可:文章来源地址https://www.toymoban.com/news/detail-462396.html


drv_key #(
    .KEY_PRESS(1'b0),
    .FILTER_TIME(100_000_000/20) //100ms
)drv_key_ut0(
    //Inputs
    .clk(gclk),  	//50MHz=20ns
    .rst_n(gresetn),
    .key(key1),
    
    //Outputs
    .flag_press(flag_press),
    .flag_release(flag_release)
);

Modelsim工程下载

  • fsm_key_filter.rar

到了这里,关于Verilog实现按键消抖(状态机方法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【FPGA零基础学习之旅#10】按键消抖模块设计与验证(一段式状态机实现)

    🎉欢迎来到FPGA专栏~按键消抖模块设计与验证 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 🥝 模块设计: 🥝 按键消

    2024年02月12日
    浏览(41)
  • 按键消抖(Verilog&Vivado)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 按键作为基本的人机输入接口,由于其机械特性,在按键按下或松开的时候,都是会有抖动的。按键小豆的方式有很多。我的方法是通过计时来消抖,通过一个计数器,当按键输入有变化时,计数器清零

    2024年02月08日
    浏览(43)
  • 用verilog编写按键消抖代码

    本代码在按键按下和松开情况下均能消抖,消抖延时20ms(时钟频率为100MHz时)。 代码如下 module key3_led2( //from system input     input    clk,     input    rstn, //from external input to pl     input    ex_key1,        //按键从PL端输入 //from pl to ps     output    reg    pl_key1    //处理

    2024年02月02日
    浏览(43)
  • 【数电实验6】Verilog—按键防抖动设计

    【2022.05西南交大数电实验】 【本代码及波形已通过老师验收。 仅供参考。 】 【参考博客:Verilog实现独立按键消抖(状态机)_ty_xiumud的博客-CSDN博客_verilog按键消抖】 【参考视频(强推这个up主):[录播] 数字电子技术实验_哔哩哔哩_bilibili】   【2022.05.11更新: 目前 仅有一

    2024年02月03日
    浏览(39)
  • FPGA入门学习笔记(十三)Vivado实现按键消抖

    四种状态 按键未按下:静止状态呈高电平; 按下过程中:抖动状态呈高低电平; 按键已按下:静止状态呈低电平; 释放过程中:抖动状态呈高低电平。 按键消抖思路 :区别于单片机使用20ms延时判断电平正负,FPGA中采用电平保持计时,若时间长度超过20ms则认为发生了一次

    2024年02月04日
    浏览(65)
  • 【蓝桥杯嵌入式】定时器实现按键单击,双击,消抖以及长按的代码实现

    🎊【蓝桥杯嵌入式】专题正在持续更新中,原理图解析✨,各模块分析✨以及历年真题讲解✨都在这儿哦,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 -  蓝桥杯嵌入式_勾栏听曲_0的博客 🍻欢迎大家  🏹  点赞👍  评论📨  收藏⭐️ 📌个人主

    2024年01月17日
    浏览(46)
  • STM32按键消抖的几种实现方式-STM32 Button Debouncing

    按键按下和松开的时候,按键金属片之间的贴合、分离有一个过程。给STM32输入的信号并不是理想的0和1切换的过程。而是如下图所示的,按下和松开的一小段时间内按键信号出现抖动( jitter ),这种现象称为按键抖动( Button Bouncing )。为了避免程序上出现误动作,需要从

    2024年01月15日
    浏览(37)
  • 单片机入门资料,按键消抖方式,按键怎么消抖

     1.什么是按键消我们先来看一下按键按下去的波形图   1.按键消抖原理 我们可以看到当按键按下的那一时刻和松开的时候有类似于锯齿的形状那就是按键抖动,这个抖动不是我们人为能控制得了的,所以我们只能对进行硬件消抖或者进行软件消抖.          上图中我们可以

    2024年02月08日
    浏览(39)
  • Arduino程序设计(四)按键消抖+按键计数

    本文主要介绍两种按键控制LED实验: 第一种是采用软件消抖的方法检测按键按下的效果; 第二种是根据按键按下次数,四个LED灯呈现不同的流水灯效果。 按键在按下时,由于机械和物理特定的原因,经常会产生一些开关变换,而这些变换会让程序误认为是短时间内进行了多

    2024年02月10日
    浏览(73)
  • FPGA开发:按键消抖

    相关阅读 FPGA开发专栏 https://blog.csdn.net/weixin_45791458/category_12388695.html?spm=1001.2014.3001.5482         按键是FPGA开发板上的重要交互元件,因为按键的内部的结构设计,在按下和松开按键时,按键会无法避免地产生机械抖动,因此要对按键输入进行特殊处理,否则可能会因为机械

    2024年02月15日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包