FPGA自学教程 08 使用状态机实现按键消抖

 双非硕士 研一下学期视觉转FPGA(在b站跟小梅哥视频)

长路漫漫,但希望前途光明

按键抖动是按键在日常工作中,经常出现的现象,为了避免该现象,设计了一个按键抖动消除的实验。

代码内容如下

module key_filter(
    Clk,
    Reset_n,
    Key,
//    p_key_flag,
//    n_key_flag,
    key_flag,
    key_state
    );
    
    input Clk;
    input Reset_n;
    input Key;
//    output reg p_key_flag;
//    output reg n_key_flag;
    output key_flag;
    output reg key_state;
    //定义一个边沿检测寄存器
    reg [1:0]r_key;
    always@(posedge Clk)
        begin
            r_key[0] <= Key;
            r_key[1] <= r_key[0];
        end
    
    //定义一个上升沿
    wire p_edge;
    assign p_edge = (r_key == 2'b01);
    //定义一个下降沿
    wire n_edge;
    assign n_edge = (r_key == 2'b10);
    
    reg p_key_flag;
    reg n_key_flag;
    assign key_flag = p_key_flag | n_key_flag;
    //开始进行状态机的框架
    reg [19:0]cnt;
    reg [1:0]state;    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        begin
            cnt <= 0;
            state <= 0;
            p_key_flag <= 0;
            n_key_flag <= 0;
            key_state <= 1'b1;
        end
     else 
         begin
            case(state)
                0:
                begin
                    n_key_flag <= 1'b0;
                    if(n_edge == 1)
                        state <= 1;
                    else 
                        state <= 0;
                end
                1:
                begin
                    if(cnt >= 1000000 -1 )
                        begin
                            state <= 2;
                            p_key_flag <= 1;
                            key_state <= 0;
                            cnt <= 0;
                        end
                    else if (( (p_edge == 1) && (cnt < 1000000 - 1) ))
                        begin 
                            state <= 0;
                            cnt <= 0;
                        end   
                     else 
                        begin
                            cnt <= cnt + 1'b1;     
                            state <= 1;
                        end
                end
                2:
                begin
                    p_key_flag <= 0;
                    if(p_edge == 1)
                        begin
                            state <= 3;
                        end
                    else 
                        state <= 2;
                end
                3:
                begin
                    if(cnt >= 1000000 - 1)
                        begin
                            n_key_flag <= 1;
                            state <= 0;
                            key_state <= 1;
                            cnt <= 0;
                        end
                    else if((cnt < 1000000 - 1 ) && (n_edge == 1) )
                        begin
                            state <= 2;
                            cnt <= 0;
                        end
                    else
                        begin 
                            cnt <= cnt + 1'b1;
                            state <= 3;
                        end
                end
            endcase
         end
endmodule

仿真代码内容如下:

`timescale 1ns / 1ps
module key_filter_tb();
    
    reg Clk;
    reg Reset_n;
    reg Key;
//    wire p_key_flag;
//    wire n_key_flag;
    wire key_flag;
    wire key_state;
        
    key_filter key_filter(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Key(Key),
//        .p_key_flag(p_key_flag),
//        .n_key_flag(n_key_flag),
        .key_flag(key_flag),
        .key_state(key_state)
        );
    
    initial Clk = 1;
    always#10 Clk = ~Clk;
    
    initial begin
        Reset_n = 0;
        Key = 1;
        #201;
        Reset_n = 1;
        #3000;
        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;//(0,9999999)
                    #rand Key = ~Key;
                end
                Key = 0;
                #40000000;
                
                repeat(5)begin
                    rand = {$random(seed)} % 10000000;//(0,9999999)
                    #rand Key = ~Key;
                end
                Key = 1;
                #40000000;           
            end
        endtask
endmodule

波形图如下:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值