FPGA_学习_07_按键消抖

机械按键是常用的器件,但在机械按键使用的过程中,总伴随着抖动,在本次实验中,我们将完成按键的去抖,并且通过按键控制LED亮灭。

FPGA_学习_07_按键消抖_第1张图片

理想情况下,按键按下过后,按键处为低电平,当按键释放过后恢复为高电平,但在实际情况下,由于按键采用的机械结构,当按键按下过后,电平不能立即保持为低,会有一段时间的跳变后才稳定,保持为低。同理,当按键释放的时候,电平不能立即保持为高,也有一段时间的不稳定状态。

在本次实验中,通过按键输入电平保持为低的达到20ms 后认为按键已经稳定,通过计数器对按键输入为低电平时间进行计数,消除按键抖动。

1 硬件原理

FPGA_学习_07_按键消抖_第2张图片

2 时序设计

FPGA_学习_07_按键消抖_第3张图片

{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']}
]}

 3 源代码

`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

4 约束文件

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		]  

5 运行结果

Lab4_key_debounce_RUN

愿我们共同进步! 感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。

你可能感兴趣的:(fpga开发,学习)