FPGA边沿检测与按键消抖

边沿检测有上升沿检测、下降沿检测、双边沿检测。以按键控制LED灯为例,下面是按键原理图



从按键连接的原理图,可以看到,按键未按下时是低电平,当按键按下即为高电平,如果要实现按键按下一次led改变一次状态,即检测按键上升沿。再加上按键消抖代码如下

module key (KEY,LED_N,RST_N,CLK);
	input [7:4] KEY;				//四个按键
	output [7:4] LED_N;				//四个 LED灯
	input RST_N,CLK;				//时钟,复位按键
	
//******************************************************************************
//上升沿检测
//*****************************************************************************
	reg [7:4]key;
	always @(posedge CLK or negedge RST_N)
			if (!RST_N) 
				key <= 4'b0000;
			else 
				key <= KEY;
	
	reg [7:4]key_r;
	always @ (posedge CLK or negedge RST_N)
		if (!RST_N) 
				key_r <= 4'b0000;
			else 
				key_r <= key;
	
	wire [7:4] key_an;
	assign key_an = ~key_r & key;		//
//***********************************************************************************	
	
	reg [19:0] cnt;
	always @ (posedge CLK or negedge RST_N)
		if (!RST_N) 
			cnt <= 20'd0;
			else if (key_an) 
				cnt <= 20'd0;
			else 
				cnt = cnt + 1'b1;
//******************************************************************************
//上升沿检测
//*****************************************************************************
reg [7:4] low_key;
always @ (posedge CLK or negedge RST_N)
if (!RST_N)
low_key <= 4'b0000;
else if (cnt == 20'h000ff)
low_key <= KEY;

reg [7:4] low_key_r;
always @ (posedge CLK or negedge RST_N)
if (!RST_N) low_key_r <= 4'b0000;
else
low_key_r <= low_key;

wire [7:4] led_ctrl = ~low_key_r & low_key;
//*****************************************************************************
reg [7:4] led;
always @ (posedge CLK or negedge RST_N)
if (!RST_N)
led <= 4'b1111;
else
begin
if (led_ctrl[7])
 led[7] <= ~led[7];
if (led_ctrl[6])
led[6] <= ~led[6];
if (led_ctrl[5])
led[5] <= ~led[5];
if (led_ctrl[4])
 led[4] <= ~led[4];
end
assign LED_N[7] = led[7], LED_N[6] = led[6], LED_N[5] = led[5], LED_N[4] = led[4];
endmodule


两条*****线中的 代码就是上升沿检测,两个寄存器key,key_r分别储存按键前后两个时钟的值,key_an 由 ~key_r & key得到

时钟周期:    1    2    3     4   5

key  :         0000 0000 0000  0000 0001

key_r:      xxxx0000 00000000  0000~key_r:     xxxx 11111111  11111111

此处假设在第5个时钟周期有按键按下,那么在 第五个时钟周期,key_an的值为 0001。那么这段代码实现的效果就是按键每按下一次相应的led状态改变一次。如果实现的功能是按键按下时led一个 状态,按键松开时 led一个状态,那么就要同时检测led的双边沿。只要把代码中的

	assign key_an = ~key_r & key;		






       wire [7:4] led_ctrl = ~low_key_r & low_key;

更换成
assign key_an = key_r ^ key;
wire [7:4] led_ctrl = low_key_r ^ low_key;
即可。


如果按键原理图中,按键按下为低电平,松开为高电平,要实现按键每按下一次,led的值改变一次,就要进行下降沿检测,

代码中的

	assign key_an = ~key_r & key;		

       wire [7:4] led_ctrl = ~low_key_r & low_key;

要更换成
assign key_an = key_r & ~key;
wire [7:4] led_ctrl = low_key_r & ~low_key;
解析 如下

时钟周期:    1    2   3 4   5

key  :      1111 1111   1111   1111 1110

key_r:      xxxx 1111 1111 1111  1111 ~key_r:     xxxx 0000 0000 0000 0001

在 第五个时钟周期,key_an的值为 0001。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值