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

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 8
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李锐博恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值