概述
A.按键消抖
一、设计背景:
在用机械按键进行操作时候,按键过程会有抖动,即出现不稳定状态,因此需要按键消抖。一般经验值是10ms。
二、设计需求:
设计使用尖峰脉冲信号作为按键稳定的标志信号(flag),通过仿真看到按键消抖的功能。
三、设计方案:
五、代码
状态机:
六、仿真验证:
编写tb文件模拟按键,设置cnt_num为4。即/*cnt_num(4)*/也就是在50Hz时钟下,100ns可以就可使按键稳定,如下
练习:
用一个按键控制数码管显示,数码管显示的数值就是按键的次数,没按一次,数码管显示的数字加一,数值从0-f循环显示
代码:
顶层:
//顶层
module key_filter_seg_top(clk,rst_n,key_in,sel,seg);
input clk;
input rst_n;
input key_in;
output [2:0]sel;
output [7:0]seg;
wire flag;
filter /*#(.cnt_num(4)) */ filter_inst(
.clk(clk),
.rst_n(rst_n),
.key_in(key_in),
.flag(flag)
);
key_filter_seg key_filter_seg_inst(
.clk(clk),
.rst_n(rst_n),
.flag(flag),
.sel(sel),
.seg(seg)
);
endmodule
子模块代码:
//按键消抖模块:利用尖峰脉冲信号来对按键的动作中作一次处理
module filter(clk,rst_n,key_in,flag);
input clk;
input rst_n;
input key_in;
output reg flag;//输出的尖峰脉冲信号(按键稳定的标志信号)
reg[31:0] cnt;
reg state;//状态寄存器:两个状态(按下和抬起)
`define s0 1'b0
`define s1 1'b1
parameter cnt_num = 50_000_000/100-1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt <= 32'b0;
state <= `s0;
flag <= 1'b0;
end
else
begin
case(state)
`s0:begin
if(!key_in )//有按键按下
begin
if(cnt < cnt_num)//未达到消抖时间
begin
cnt <= cnt + 1'b1;
flag <= 1'b0;
end
else//达到消抖时间
begin
cnt <= 32'b0;
flag <= 1'b1;
state <= `s1;
end
end
else //没有按键按下
begin
state <= `s0;//等待按键按下
cnt <= 32'b0;
flag <= 1'b0;
end
end
`s1:begin
flag <= 1'b0;
if(key_in)//按键抬起
begin
if(cnt < cnt_num)//没有到达消抖时间
begin
cnt <= cnt + 1'b1;
flag <= 1'b0;
end
else//到达消抖时间
begin
cnt <= 32'd0;
flag <= 1'b0;
state <= `s0;
end
end
else//按键未抬起
begin
state <= `s1;//等待按键抬起
end
end
default : state <= `s0;
endcase
end
end
endmodule
数码管点亮模块:
module key_filter_seg(clk,rst_n,flag,sel,seg);
input clk;
input rst_n;
input flag;
output [2:0]sel;
output reg [7:0]seg;
reg [3:0] key_cnt;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_cnt <= 4'b0;
end
else
begin
if(flag)
begin
if(key_cnt <4'd15)
begin
key_cnt <= key_cnt + 1'b1;
end
else
begin
key_cnt <= 4'd0;
end
end
else
begin
key_cnt <= key_cnt;
end
end
end
assign sel = 3'd1;
always @(*)
begin
if(!rst_n)
begin
seg = 8'b1100_0000;
end
else
begin
case(key_cnt)
4'd 0: seg = 8'b1100_0000; //“0”
4'd 1: seg = 8'b1111_1001; //“1”
4'd 2: seg = 8'b1010_0100; //“2”
4'd 3: seg = 8'b1011_0000; //“3”
4'd 4: seg = 8'b1001_1001; //“4”
4'd 5: seg = 8'b1001_0010; //“5”
4'd 6: seg = 8'b1000_0010; //“6”
4'd 7: seg = 8'b1111_1000; //“7”
4'd 8: seg = 8'b1000_0000; //“8”
4'd 9: seg = 8'b1001_1000; //“9”
4'd10: seg = 8'b1000_1000; //“A”
4'd11: seg = 8'b1000_0011; //“b”
4'd12: seg = 8'b1100_0110; //"C"
4'd13: seg = 8'b1010_0001; //"d"
4'd14: seg = 8'b1000_0110; //"E"
4'd15: seg = 8'b1000_1110; //"F"
endcase
end
end
endmodule
仿真验证:
`timescale 1ns/1ns
module tb_key_filter_seg_top();
reg clk;
reg rst_n;
reg key_in;
wire sel;
wire [7:0]seg;
key_filter_seg_top key_filter_seg_top_inst(
.clk(clk),
.rst_n(rst_n),
.key_in(key_in),
.sel(sel),
.seg(seg)
);
initial
begin
clk = 1;
rst_n = 0;
key_in = 1;//抬起
#100
rst_n = 1;
#100
key_in = 0;//按下
#80
key_in = 1;//抬起
#100
key_in = 0;//按下(有效第一次)
#120
key_in = 1;//抬起
#200
key_in = 0;//按下(有效第二次)
#160
key_in = 1;//抬起
#240
$stop;
end
always #10 clk = ~clk;
endmodule
下板与仿真相符。
最后
以上就是威武花生为你收集整理的FPGA——zhixin培训 Day_07——按键消抖的全部内容,希望文章能够帮你解决FPGA——zhixin培训 Day_07——按键消抖所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复