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) beginif(!rst_n) beginsw_in_r0 <= 1;endelse beginsw_in_r0 <= sw_in;endendwire 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) beginif(!rst_n) begincount <= 0;endelse if(edge_en) begincount <= 0;endelse begincount <= count + 1;endendalways @ (posedge clk or negedge rst_n) beginif(!rst_n) beginsw_out <= 1'b1;endelse if(count == 20'h2BF20) beginsw_out <= sw_in;endelse begin;endendendmodule
再给出3个按键的Verilog描述:(这个之前写过:《按键消抖与LED控制》实验的个人思考与总结)
`timescale 1ns / 1psmodule 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++