马上注册,看完整文章,学更多FPGA知识。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
—边缘检测工程:按键捕捉模块代码解析 作者:陈刀刀 本文为明德扬原创文章,转载请注明出处! 按键捕捉模块的功能:可以达到按一次按键就可以得到一次识别的效果,并且需要对按键进行消抖处理,消除按下按键时不稳定、随机的抖动电压信号。
一、设计架构 有些同学看到按键消抖处理,就理所应当以为是将按键按下这一活动的抖动部分进行消除,但其实按键的消抖只是一种比较正式的说法,其本质上是在抖动的波形中,捕捉到比较稳定的电压。 我们通过实际情况来学习下。一般按键都是低电平有效,通常情况下按键信号为高电平,当主动按下按键时会变成低电平,这是按键的基本电平情况。前面我们有说到,在按下的瞬间,稳定状态的信号前后都会产生抖动,这时即使按键信号等于0也无法表示按键被按下。 如下图所示,按键持续为高电平,当按下按键的时候会变为低电平,但是在此前后都会产生一段高高低低的抖动信号。按键捕捉的方法就是持续的检测信号的进度,比如到第一个低电平产生时,开始计时,假设第一个出现的低电平持续时间为6ms,不满足按键按下标准;第二个低电平信号出现持续时间为8ms,不满足按键按下标准;到第四个低电平信号,持续了10ms以上,满足按下按键标准,即可判断这里有一次的按下按键操作;接着第五个低电平信号,持续时间为6ms,不满足按下按键标准。这种方法,就可以帮助我们很好的确判断有效按键信号。
按键捕捉模块使用一个计数器的架构,对按键信号长度进行计数。该计数器架构为:
计数器cnt0:时钟时钟计数器。用于计数按键信号持续超过10ms的时间,10ms即是500000个时钟,所以该计数器的计数周期为500000。
二、信号的意义
信号 | | | | | | | | | | | 按键输入信号。,没按下时为持续为高电平状态即1,按下时为低电平。变0表示按下按键。 | | | 按键输出有效指示信号。代表捕捉到按下一个按键。输出信号,持续为高电平状态即0,变1表示按下按键。当计数器计数结束时,输出按键信号。 | | | 设计逻辑:当时钟计数器数到10ms时,表示捕捉到一次按下,输出1个时钟的高电平。 | | | | | | | | | | | | | | | 时钟计数器。该计数器用来计算按键按下时的持续时间。按键信号持续时间计数器,该计数器计数按键信号持续超过10ms的时间,该计数器的计数周期为500000。 |
三、参考代码 下面展出本模块的设计,欢迎进一步交流,如果需要源代码,欢迎与本人联系。
- module key_module(
- clk ,
- rst_n ,
- key_in ,
- key_vld
- );
- parameter DATA_W = 20 ;
- parameter KEY_W = 4 ;
- parameter TIME_20MS = 500_000 ;
- input clk ;
- input rst_n ;
- input [KEY_W-1 :0] key_in ;
- output [KEY_W-1 :0] key_vld ;
- reg [KEY_W-1 :0] key_vld ;
- reg [DATA_W-1:0] cnt ;
- wire add_cnt ;
- wire end_cnt ;
- reg flag_add ;
- reg [KEY_W-1 :0] key_in_ff1 ;
- reg [KEY_W-1 :0] key_in_ff0 ;
- always @(posedge clk or negedge rst_n)begin
- if(rst_n==1'b0)begin
- cnt <= 20'b0;
- end
- else if(add_cnt)begin
- if(end_cnt)
- cnt <= 20'b0;
- else
- cnt <= cnt + 1'b1;
- end
- else begin
- cnt <= 0;
- end
- end
- assign add_cnt = flag_add==1'b0 && (key_in_ff1 != {KEY_W{1'b1}});
- assign end_cnt = add_cnt && cnt == TIME_20MS - 1;
- always @(posedge clk or negedge rst_n)begin
- if(rst_n==1'b0)begin
- flag _add<= 1'b0;
- end
- else if(end_cnt)begin
- flag_add <= 1'b1;
- end
- else if(key_in_ff1 == {KEY_W{1'b1}})begin
- flag_add <= 1'b0;
- end
- end
- always @(posedge clk or negedge rst_n)begin
- if(rst_n==1'b0)begin
- key_in_ff0 <= 0;
- key_in_ff1 <= 0;
- end
- else begin
- key_in_ff0 <= key_in ;
- key_in_ff1 <= key_in_ff0;
- end
- end
- always @(posedge clk or negedge rst_n)begin
- if(rst_n==1'b0)begin
- key_vld <= 0;
- end
- else if(end_cnt)begin
- key_vld <= ~key_in_ff1;
- end
- else begin
- key_vld <= 0;
- end
- end
- endmodule
复制代码
|