【Verilog HDL 训练】第 09 天(按键消抖)
【摘要】 5月7日
按键防抖
1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz。
在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三个为例;
其次是算下按键按下后计数多少后,采样按键值,这个需要简单的运算:输入时钟为12MHz,也就是大约80ns的周期,那么去除15ms的抖动,需要计数多少次呢?
经...
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++
文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。
原文链接:reborn.blog.csdn.net/article/details/89927569
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)