5月7日

按键防抖

1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz。

在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三个为例;

其次是算下按键按下后计数多少后,采样按键值,这个需要简单的运算:输入时钟为12MHz,也就是大约80ns的周期,那么去除15ms的抖动,需要计数多少次呢?

经过计算,大约180000次,换成16进制为:2BF20,如此以来,计数器20位足够保险了。

有了以上的准备工作了,我们开始编写一个按键的按键消抖程序了:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2019/05/07 19:29:37
// Design Name:
// Module Name: key
//
//


module key(
input clk,
input rst_n,
input sw_in,
output reg sw_out
);

//按键本身值为1,按下按键后键值为0.
reg sw_in_r0;

always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
sw_in_r0 <= 1;
end
else begin
sw_in_r0 <= sw_in;
end
end

wire edge_l, edge_h;
assign edge_l = sw_in_r0 & (~sw_in); //下降沿检测
assign edge_h = sw_in & (~sw_in_r0);//上升沿检测

wire edge_en; //键值变化后,edge_en变为高
assign edge_en = edge_l | edge_h;

reg [19:0] count;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
count <= 0;
end
else if(edge_en) begin
count <= 0;
end
else begin
count <= count + 1;
end

end

always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
sw_out <= 1'b1;
end
else if(count == 20'h2BF20) begin
sw_out <= sw_in;
end
else begin
;
end
end



endmodule

再给出3个按键的Verilog描述:(这个之前写过:《按键消抖与LED控制》实验的个人思考与总结)

`timescale 1ns / 1ps


module sw_debounce(
clk,rst_n,
sw1_n,sw2_n,sw3_n,
sw_out
);

input clk; //主时钟信号
input rst_n; //复位信号,低有效
input sw1_n,sw2_n,sw3_n; //三个独立按键,低表示按下
output [2:0] sw_out;

//---------------------------------------------------------------------------
reg key_rst;

always @(posedge clk or negedge rst_n)
if (!rst_n) key_rst <= 1'b1;
else key_rst <= sw3_n&sw2_n&sw1_n;

reg key_rst_r; //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中

always @ ( posedge clk or negedge rst_n )
if (!rst_n) key_rst_r <= 1'b1;
else key_rst_r <= key_rst;

//当寄存器key_rst由1变为0时,led_an的值变为高,维持一个时钟周期
wire key_an = key_rst_r & (~key_rst);
/*
key_rst 1 1 1 0 0 1
~key_rst 0 0 0 1 1 0
key_rst_r 1 1 1 0 0 1
key_an 0 0 1 0 0
*/
//---------------------------------------------------------------------------
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[2:0] low_sw;

always @(posedge clk or negedge rst_n)
if (!rst_n) low_sw <= 3'b111;
else if (cnt == 20'h2BF20) //满12ms,将按键值锁存到寄存器low_sw中
low_sw <= {sw3_n,sw2_n,sw1_n};

assign sw_out = low_sw;


endmodule



2. 记录题目1中用到的工具,操作步骤,遇到的错误和提示信息。


工具:Vivado 2018,Notepad++