当前位置: 代码迷 >> 综合 >> 【Verilog HDL 训练】第 09 天(按键消抖)
  详细解决方案

【Verilog HDL 训练】第 09 天(按键消抖)

热度:12   发布时间:2023-12-12 20:52:45.0

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++ 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  相关解决方案