赞
踩
目录
首先是处于空闲状态(IDLE),此时等待下降沿的到来,如果下降沿没有到来,那就继续等待;如果下降沿到来了就进入
按下消抖状态(P_FILTER),在P_FILTER状态下要做三件事,第一件事是计时大于20ms则表明按键已经按下,则进入下一状态;第二件事是20ms内检测到上升沿,则表明此时处于抖动状态,立即退回空闲状态。第三件事是20ms内未检测到上升沿,就干巴巴的等待20ms,直至20ms结束仍未有上升沿就进入第一件事。
第三个状态是等待状态(WAIT_R),此时按键已经被按下,这个状态要做的事就是一直检测上升沿的到来,如果上升沿没到来就一直待在等待状态,如果一旦检测到上升沿出现,则立即进入
释放消抖状态(R_FILTER),此状态同样要做三件事:第一件事是计时大于20ms则表明按键已经释放,则进入下一状态;第二件事是20ms内检测到下降沿,则表明此时处于抖动状态,立即退回等待状态。第三件事是20ms内未检测到下降沿,就干巴巴的等待20ms,直至20ms结束仍未有下降沿就进入第一件事。
- //基于状态机思维的按键消抖功能verilog实现思路
- //1.对异步输入信号打拍消除亚稳态
- //2.寄存打拍后信号,对比得出上升沿与下降沿标志信号
- //3.列出所有状态,编写状态机整体框架
- //4.编写各状态间跳转方向以及对应跳转条件
- //5.编写状态输出逻辑,在正确时刻输出信号赋值
-
- module key_filter(
- input Key,
- input Clk,
- input Reset_n,
- output reg Key_P_Flag,
- output reg Key_R_Flag,
- output reg Key_State//向外输出过滤后的电平信号,使得输出电平比较干净。
- );
-
-
- reg [29:0]cnt_20ms;//定时20ms计数器
- reg [1:0]state;
- reg sync_d0_key,sync_d1_key;//定义两个同步D触发器的输出作为输入是为了消除未知信号Key的亚稳态,以及将异步信号Key变为同步信号
- reg r_key;//定义下降沿
- wire nedge_key;//下降沿定义
- wire pedge_key;//下降沿定义
-
- //进行打拍来减小亚稳态
- always@(posedge Clk)
- sync_d0_key <= Key;
- always@(posedge Clk)
- sync_d1_key <= sync_d0_key;
-
- always@(posedge Clk)
- r_key <= sync_d1_key;
-
- assign nedge_key = (sync_d1_key == 0)&&(r_key == 1);//边沿检测下降沿实现
- assign pedge_key = (sync_d1_key == 1)&&(r_key == 0);//边沿检测上升沿实现
-
- localparam IDLE = 0;//localparam是本地参数定义,用于定义一个标识符代表常量,无法进行参数传递,不可修改
- localparam P_FILTER = 1; //parameter可以进行参数传递,就是可修改的意思。
- localparam WAIT_R = 2;
- localparam R_FILTER = 3;
- parameter Dly_20ms_cnt = 1000_000-1;
-
- wire time_20ms_reached;
- assign time_20ms_reached = (cnt_20ms >= Dly_20ms_cnt);//20ms到来的脉冲信号
-
-
- //time_20ms_reached脉冲信号的产生
- // always@(posedge Clk or negedge Reset_n)
- // if(!Reset_n)begin
- // cnt_20ms <= 0;
- // time_20ms_reached <= 0;
- // end
- // else if(state==P_FILTER || state==R_FILTER )begin
- // if(cnt_20ms == Dly_20ms_cnt)begin
- // cnt_20ms <= 0;
- // time_20ms_reached <=1;
- // end
- // else begin
- // cnt_20ms <= cnt_20ms +1;
- // time_20ms_reached <= 0;
- // end
- // end
- // else begin
- // cnt_20ms <= 0;
- // time_20ms_reached <= 0;
- // end
-
- // wire time_20ms_reached;
- // assign time_20ms_reached = cnt_20ms >= Dly_20ms_cnt;
- // always@(posedge Clk or negedge Reset_n)
- // if(!Reset_n)
- // cnt_20ms <= 0;
- // else if(state==P_FILTER || state==R_FILTER)
- // cnt_20ms <= cnt_20ms + 1;
- // else
- // cnt_20ms <= 0;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)begin
- state <= IDLE;//复位开始状态处于IDLE空闲态
- Key_R_Flag <= 0;
- Key_P_Flag <= 0;
- cnt_20ms <= 0;//在状态机里面实现,防止计数到1000000
- Key_State <= 1;
- end
- else begin
- case(state)
- IDLE:
- if(nedge_key)
- state <= P_FILTER;
- else begin
- state <= IDLE;
- Key_R_Flag <= 0; //告知外界按键已经松开的信号变为0
- end
- P_FILTER:
- if(time_20ms_reached)begin//顺利到达20ms说明按键已经顺利按下
- state <= WAIT_R;
- Key_P_Flag <= 1; //告知外界按键已经按下
- cnt_20ms <= 0;//计时到20ms后直接清零。
- Key_State <= 0;//此时外界按键已经按下,所以输出低电平
- end
- else if(pedge_key)begin
- state <= IDLE;
- cnt_20ms <= 0;//回到IDLE后清零重新计数
- end
- else begin
- state <= state;
- cnt_20ms <= cnt_20ms+1;//其他状态开始计数
- end
- WAIT_R:
- if(pedge_key)
- state <= R_FILTER;
- else begin
- state <= WAIT_R;
- Key_P_Flag <= 0;
- end
- R_FILTER:
- if(time_20ms_reached)begin
- state <= IDLE;
- Key_R_Flag <= 1; //告知外界按键已经松开
- cnt_20ms <= 0;//计时到20ms后直接清零。
- Key_State <= 1; //此时外界按键已经松开,所以Key_State为高电平,这样输出电平就比较干净
- end
- else if(nedge_key)begin
- state <= WAIT_R;
- cnt_20ms <= 0;//回到WAIT_R后清零重新计数
- end
- else begin
- state <= state;
- cnt_20ms <= cnt_20ms+1;//其他状态开始计数
- end
- endcase
- end
- endmodule
- `timescale 1ns / 1ps
-
- module key_filter_tb();
-
- reg Key;
- reg Clk;
- reg Reset_n;
- wire Key_P_Flag;
- wire Key_R_Flag;
- wire Key_State;
- key_filter key_filter(
- .Key(Key),//一个输入信号
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Key_P_Flag(Key_P_Flag),
- .Key_R_Flag(Key_R_Flag),
- .Key_State(Key_State)
- );
-
-
- initial Clk = 1;
- always #10 Clk = ~Clk;
-
- initial begin
- Reset_n = 0;
- Key = 1;
- #201;
- Reset_n = 1;
-
- //第一次按下测试
- //空闲稳定
- Key = 1; #100000000;
-
- //按下抖动
- Key = 0; #18000000;//按下抖动 低 18ms
- Key = 1; #2000000;//按下抖动 高 2ms
- Key = 0; #1000000;//按下抖动 低 1ms
- Key = 1; #200000;//按下抖动 高 0.2ms
- Key = 0; #20000000;//按下稳定 低 20ms
-
-
- //按下稳定
- Key = 0; #50000000;//按下稳定 低 50ms
-
- //释放抖动
- Key = 1; #2000000;//释放抖动 高 2ms
- Key = 0; #1000000;//释放下抖动 低 1ms
- Key = 1; #20000000;//释放稳定 高 20ms
-
- //释放稳定
- Key = 1; #50000000;//释放稳定 高 50ms
-
-
- //第二次按下测试
-
- //空闲稳定
- Key = 1; #100000000;
-
- //按下抖动
- Key = 0; #18000000;//按下抖动 低 18ms
- Key = 1; #2000000;//按下抖动 高 2ms
- Key = 0; #1000000;//按下抖动 低 1ms
- Key = 1; #200000;//按下抖动 高 0.2ms
- Key = 0; #20000000;//按下稳定 低 20ms
-
-
- //按下稳定
- Key = 0; #50000000;//按下稳定 低 50ms
-
- //释放抖动
- Key = 1; #2000000;//释放抖动 高 2ms
- Key = 0; #1000000;//释放下抖动 低 1ms
- Key = 1; #20000000;//释放稳定 高 20ms
-
- //释放稳定
- Key = 1; #50000000;//释放稳定 高 50ms
- $stop;
- end
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。