边缘检测与按键消抖

一、边缘检测

(一)基本原理

        在数字电路中,上升沿和下降沿检测是常见的任务,通常用于触发时钟边沿、捕捉输入信号的变化等。要对信号的边沿进行检测,则需要知道边沿前后的电平状态,若在边沿前一时刻是低电平,后一时刻是高电平,则是上升沿,反之则是下降沿。

        使用两个寄存器in1和in2对输入信号in进行存储,在非阻塞赋值中,由于是先运算再赋值,所以in1和in2信号分别在in信号上分别延后1个和2个时钟周期。

always @ (posedge sys_clk or negedge sys_rst_n) 
	begin
		if (!sys_rst_n)
			begin
				in1 <= 0;
				in2 <= 0;
			end
		else 
			begin
				in1<=in;
				in2<=in1;
			end
	end

        假设在第n个时钟周期对复位信号无效,则在第n+1个时钟周期上升沿来到时in1信号被赋值为in,在第n+2个时钟周期上升沿来到时in2信号被赋值为in。由此实现对输入信号打两拍的操作。

        检测上升沿:assign pos = in & (~in2);

        检测下降沿:assign neg = ~in & in2;

        检测双边沿:assign both =(in & (~in2)) | (~in & in2);

(二)具体实现

        以按键控制流水灯为例,当按键按下时会出现一个脉冲,系统检测到该脉冲时控制LED灯亮,再次按下按键时,灯灭,默认为灯灭。因此需要进行一次上升沿检测。具体代码如下:

module edge_detect(
input   sys_clk   ,
input   sys_rst_n ,
input   key       ,
output  led
);

reg key1,key2;
wire key_en;
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			key1 <= 1'b0;
			key2 <= 1'b0;
		end
	else if
		begin
			key1 <= key;
			key2 <= key1;
		end 
end
assign key_en = (key1) & (~key2);

always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		led <= 0;
	else if 
	begin
		if(key_en == 1)
			led = ~led;
	end
end

进行测试文件的编写,可以直接通过Quartus自动编写一部分,操作流程如下:

测试文件如下:


`timescale 1 ns/ 1 ps
module touch_led_vlg_tst();

reg key;
reg sys_clk;
reg sys_rst_n;
// wires                                               
wire led;

                   
touch_led i1 (
	.key(key),
	.led(led),
	.sys_clk(sys_clk),
	.sys_rst_n(sys_rst_n)
);
initial                                                
begin                                                  
        sys_clk = 1'b0;
		sys_rst_n = 1'b0;
		key = 1'b1;
		#100 sys_rst_n = 1'b1;
		#300 key = 1'b0;
		#300 key = 1'b1;
end          
assign #10  sys_clk <= ~sys_clk;                                     
                                      
endmodule

二、按键消抖

        按键消抖是指在处理数字输入时,防止由于物理按键的机械性能引起的抖动或干扰而产生的错误输入。物理按键可能在按下或释放时发生短暂的弹跳,导致多个触发事件。

由于FPGA对于电平信号十分敏感,因此输入进板子的信号如上所示。在消抖后,需要按键信号变为下面这种形式。

对于按键消抖,本文介绍两种方法,一是对按键信号进行打拍,检测新的按键信号与原信号电平信号是否相等,二是构建一个计数器,当按键电平被按下后,看电平状态是否能保持20ms,若能,则表示按键已处于稳定状态。

(一)

以按键控制蜂鸣器为例,当按键被按下时,蜂鸣器响

当检测到一个按键信号下降脉冲沿,则计时20ms,我们认为按键的抖动时间最长为20ms。代码如下:

module key_debounce(

input  sys_clk  ;
input  sys_rst_n;
input  key      ;
output beep     ;
);

reg       key1;
reg       key2;
reg [19:0]cnt ; 
wire      neg ;
wire add_cnt;
wire end_cnt;
//打拍
always @(posedge clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		key  <= 1'b1;
		key1 <= 1'b1;
		key2 <= 1'b1;
	end
	else begin
		key1 <= key;
		key2 <= key1;
	end
end 
//进行下降沿检测
assign neg = ~key1 & key2;

//计数器
always @(posedge clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		cnt <= 20'd0;
	else if(add_cnt) begin
		if(end_cnt)
			cnt <= 20'd0;
		else
			cnt <= cnt+1;
	end 
end 
assign add_cnt = neg;
assign end_cnt =add_cnt & cnt==1_000_000-1; 

//按键确认按下
always @(posedge clk or negedge sys_rst_n)begin
	if(!sys_rst_n)
		beep = 1'b0;
	else if(end_cnt)
	    beep = 1'b1;
end

endmodule

(二)

与第一种方法不同的是,只要按键信号与寄存器信号不同,就重新进行计数。

module key_debounce(
    input            sys_clk,          
    input            sys_rst_n,        
    
    input            key,              
    output reg       beep         
    );


reg [31:0] delay_cnt;
reg        key_reg;


always @(posedge sys_clk or negedge sys_rst_n) begin 
    if (!sys_rst_n) begin 
        key_reg   <= 1'b1;
        delay_cnt <= 32'd0;
    end
    else begin
        key_reg <= key;
        if(key_reg != key)             
            delay_cnt <= 32'd1000000;  
        else if(key_reg == key) begin  
                 if(delay_cnt > 32'd0)
                     delay_cnt <= delay_cnt - 1'b1;
                 else
                     delay_cnt <= delay_cnt;
             end           
    end   
end

always @(posedge sys_clk or negedge sys_rst_n) begin 
    if (!sys_rst_n) begin 
        beep = 1'b0;      
    end
    else begin
        if(delay_cnt == 32'd1) begin   
           beep = 1'b1;      
        end
        else begin
            beep = 1'b0;
        end  
    end   
end
    
endmodule 

##本文参考正点原子视频,如有侵权,请联系删除。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值