Verilog 学习第六节(基于状态机的按键消抖原理与状态转移图)

文章介绍了按键消抖的基本原理,通过在检测到电平变化时启动20ms计时器来确定按键状态。详细阐述了空闲态、按下消抖状态、等待释放和释放消抖四个状态的转换逻辑,并提供了Verilog代码实现。测试文件用于验证模块功能的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按键消抖原理

在这里插入图片描述
通常情况下解决按键消抖可以采用当将上图中的第一个实际图转换成第二个方便处理分析的图,在第一次检测到电平波动从上生沿变化下降沿的时候开始计时20ms,下后面的都判断为按下状态;反之在按下状态时检测到上升状态也开始计时20ms将之后的判断为释放状态;以上的思路存在的问题即很可能抖动的时间不止20ms则会判断出错,所以采用下面的方法对按下维持的时间进行判断,若维持20ms及以上则为按下,释放也同理
在这里插入图片描述
课程重点:学会状态分析
1:空闲态:等待按键按下(等待下降沿),一旦出现下降沿就开始20ms的计时
2:按下消抖状态:20ms的计时状态,在这个状态里一边计时,一边检测有没有上升沿出现,如果有上升沿,回到空闲态;如果计时满20ms,没有出现上升沿,发出按键按下的通知信号
3:等待释放:等待按键释放(等待上升沿),一旦出现上升沿,就开始20ms的计时
4:释放消抖状态:20ms的计时状态,在这个状态里,一边计时,一边检测有没有出现下降沿,如果有下降沿,回到等待释放状态;如果计时满20ms,没有出现下降沿,发出按键释放的通知信号
在这里插入图片描述
源代码:

//此模块为按键消抖模块~
module key_filter(
    input Clk,
    input Reset,
    input Key,
//    output reg Key_P_Flag,
//    output reg Key_R_Flag,
    output Key_Flag,
    output reg Key_State
    );
    reg Key_P_Flag;
    reg Key_R_Flag;
    assign Key_Flag = (Key_P_Flag | Key_R_Flag);
    
    reg [1:0]r_Key;
    always@(posedge Clk)
       r_Key<={r_Key[0],Key};
    wire pegedge_key;
    wire negedge_key;
    assign negedge_key=(r_Key==2'b10);
    assign pegedge_key=(r_Key==2'b01);
    
    reg [19:0]cnt;
    
    reg [1:0]state;
    parameter IDLE=2'b00,P_FILTER=2'b01,WAIT_R=2'b10,R_FILTER=2'b11;
    always@(posedge Clk or negedge Reset)begin
        if(!Reset)begin
           state<=IDLE;
           cnt<=0;
           Key_P_Flag<=0;
           Key_R_Flag<=0;
           Key_State<=1;
        end 
        else begin
           case(state)
           IDLE:begin
              Key_R_Flag<=0;
              if(negedge_key)
                 state<=P_FILTER;
              else 
                 state<=IDLE;
           end
           P_FILTER:begin
              if(cnt<1000000-1)begin
                   if(pegedge_key)begin
                       state<=IDLE;
                       cnt<=0;
                       end
                   else
                       cnt<=cnt+1;
              end
              else if(cnt>=1000000-1)begin
                  Key_P_Flag<=1;
                  state<=WAIT_R;
                  cnt<=0;
                  Key_State<=0;
              end        
           end
           WAIT_R:begin
              Key_P_Flag<=0;
              if(pegedge_key)
                 state<=R_FILTER;
              else 
                 state<=WAIT_R;
           end
           R_FILTER:begin
           if(cnt<1000000-1)begin
                  if(negedge_key)begin
                      state<=WAIT_R;
                      cnt<=0;
                      end
                  else
                      cnt<=cnt+1;
             end
             else if(cnt>=1000000-1)begin
                 Key_R_Flag<=1;
                 state<=IDLE;
                 cnt<=0;
                 Key_State<=1;
             end        
          end  
          endcase
        end
    end
endmodule

测试文件:

`timescale 1ns / 1ps

module key_filter_tb(
    );
    reg Clk;
    reg Reset;
    reg Key;
    wire Key_Flag;
    wire Key_State;
   
    key_filter key_filter(
        Clk,
        Reset,
        Key,
        Key_Flag,
        Key_State
        );
     initial Clk=0;
     always#10 Clk=!Clk;
     initial begin
     Reset=0;
     #201
     Reset=1;
     press_key(2);
     $stop;
     end
     
     reg [31:0]rand;
     task press_key;
     input [3:0]seed;
     begin
     Key=1;
     #20000000;
     repeat(5)begin
         rand={$random(seed)}%10000000;
         #rand Key=~Key;
          end
     Key=0;
     #40000000;
     repeat(5)begin
         rand={$random(seed)}%10000000;
         #rand Key=~Key;
          end
     Key=1;
     #40000000;
     end
     endtask
     
endmodule

在这里插入图片描述
附:下面这个手册比较好用,自己有时间还要再找找!在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值