机械按键是常用的器件,但在机械按键使用的过程中,总伴随着抖动,在本次实验中,我们将完成按键的去抖,并且通过按键控制LED亮灭。
理想情况下,按键按下过后,按键处为低电平,当按键释放过后恢复为高电平,但在实际情况下,由于按键采用的机械结构,当按键按下过后,电平不能立即保持为低,会有一段时间的跳变后才稳定,保持为低。同理,当按键释放的时候,电平不能立即保持为高,也有一段时间的不稳定状态。
在本次实验中,通过按键输入电平保持为低的达到20ms 后认为按键已经稳定,通过计数器对按键输入为低电平时间进行计数,消除按键抖动。
{signal: [
{name: 'clk', wave: 'p........................'},
{},
{name: 'rst_n', wave: '0.1......................'},
{},
{name: 'key', wave: '1....0..........1........'},
{},
{name: 'key_d', wave: '1.....0..........1.......'},
{},
{name: 'key_dd', wave: '1......0..........1......'},
{},
{name: 'cnt_time', wave: '2.......22222......2222..', data: ['0','1','2','3','...','MAX','0','1','2']},
{},
{name: 'flag', wave: '0............1.....0.....'},
{},
{name: 'key_flag', wave: '0............10..........'},
{},
{name: 'led_r', wave: '2............2...........', data: ['2b\'01','2b\'10']},
{},
{name: 'led', wave: '2............2...........', data: ['2b\'10','2b\'01']}
]}
`timescale 1ns / 1ps
module key_debounce(
input wire clk,
input wire rst_n,
input wire key,
output wire [1:0] led
);
//==================================================================
// Parameter define
//==================================================================
parameter MAX = 1_000_000;
//==================================================================
// Internal Signals
//==================================================================
reg key_d;
reg key_dd;
reg [21:0] cnt;
reg flag;
reg key_flag;
reg [1:0] led_r;
//----------------------------- key_d -----------------------------
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
key_d <= 1'b1;
end
else begin
key_d <= key;
end
end
//----------------------------- key_dd -----------------------------
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
key_dd <= 1'b1;
end
else begin
key_dd <= key_d;
end
end
//----------------------------- cnt -----------------------------
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
cnt <= 'd0;
end
else if (key_dd == 1'b0 ) begin
if(cnt == MAX) begin
cnt <= cnt;
end
else begin
cnt <= cnt + 1'b1;
end
end
else begin
cnt <= 'd0;
end
end
//----------------------------- flag -----------------------------
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
flag <= 1'b0;
end
else if (cnt == MAX) begin
flag <= 1'b1;
end
else if(key_dd == 1'b1) begin
flag <= 1'b0;
end
else begin
flag <= flag;
end
end
//----------------------------- key_flag -----------------------------
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
key_flag <= 1'b0;
end
else if(cnt == MAX && flag == 1'b0) begin
key_flag <= 1'b1;
end
else begin
key_flag <= 1'b0;
end
end
//----------------------------- led_r -----------------------------
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
led_r <= 2'b00;
end
else if(key_flag == 1'b1) begin
led_r <= led_r + 1'b1;
end
else begin
led_r <= led_r;
end
end
// 取反
assign led = ~led_r;
endmodule
create_clock -period 20.000 [ get_ports clk ]
set_property PACKAGE_PIN N18 [ get_ports clk ]
set_property PACKAGE_PIN P15 [ get_ports {led[0]} ]
set_property PACKAGE_PIN U12 [ get_ports {led[1]} ]
set_property PACKAGE_PIN P16 [ get_ports key ]
set_property PACKAGE_PIN T12 [ get_ports rst_n ]
set_property IOSTANDARD LVCMOS33 [ get_ports clk ]
set_property IOSTANDARD LVCMOS33 [ get_ports {led[*]} ]
set_property IOSTANDARD LVCMOS33 [ get_ports key ]
set_property IOSTANDARD LVCMOS33 [ get_ports rst_n ]
Lab4_key_debounce_RUN
愿我们共同进步! 感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。