ZYNQ——按键消抖实验


原理简介

按键作为基本的人机输入接口,在很多电子设计中都是比较常见的,但是由于其机械特性,在按键按下或者松开的时候,按键的输入值是有抖动的。按键的抖动是其固有特性,因此无论按键按下或松开的多么平稳,按键的抖动也是难以消除的。本文通过FPGA计数(计时)来达到按键消抖的目的。
计数的基本原理是:当按键的输入发生变化时,计数器就清零,判断按键的输入是否发生变化是通过两级D触发器的异或实现的。如果按键的输入没有发生变化,那么计数器就累加,直至累加到一个预定值,这个预定值是通过时间和时钟的频率确定的。计数器累加到这个预定值之后,就认为按键的输入已经稳定,可以输出,因此就得到了没有抖动的按键值。
按键消抖的示意图如下图所示。
在这里插入图片描述


软件仿真

在进行板上验证之前,先在Vivado软件中编写代码进行仿真,因为仿真的速度比较快,这样可以提高我们的效率。
仿真用到的设计源代码如下。

module key_anti_shake(
    input clk,
    input rst,
    input key_in,
    output reg key_out
    );

reg [3:0] count;
reg [3:0] count_next;
reg D1,D2;  //两级D触发器
wire add_flag;  //计数标志位
wire q_reset;
reg key_out_d;  

assign q_reset = (D1^D2);   //通过异或两级D触发器的值判断按键的变化
assign add_flag = ~(count == 4'd10);  //为1时,count可以继续加1;为0时,按键稳定,可输出

always@(q_reset,add_flag,count)
begin
    case({
    
    q_reset,add_flag})
        2'b00: count_next <= count;
        2'b01: count_next <= count + 1;
        default: count_next <= 4'b0000;  //如果q_reset=1就说明两级D触发器结果不一样,肯定不稳定
    endcase
end

always@(posedge clk or posedge rst)
begin
    if(rst == 1'b1) 
    begin 
        D1 <= 1'b0; 
        D2 <= 1'b0; 
        count <= 4'b0000; 
    end 
    else 
    begin 
        D1 <= key_in; 
        D2 <= D1; 
        count <= count_next; 
    end
end

always@(posedge clk or posedge rst)
begin
    if(rst == 1'b1) 
        key_out <= 1'b1;
    else if(count == 4'd10)
        key_out <= D2;
    else
        key_out <= key_out;
end

always@(posedge clk or posedge rst)
begin
    if(rst == 1'b1) 
    begin
        key_out_d <= 1'b1;
    end
    else
    begin
        key_out_d <= key_out;
    end
end

endmodule

仿真测试代码如下。

`timescale 1ns / 1ps
module key_anti_shake_sim();
reg clk;
reg rst;
reg key_in;
wire key_out;

initial
begin
    clk = 0;
    rst = 0;
    key_in = 1;
    #100
    key_in = 0;
    #100
    key_in = 1;
    #100
    key_in = 0;
    #600
    key_in = 1;
end

always #10 clk =~clk;
key_anti_shake uut_key_anti_shake(
    .clk(clk),
    .rst(rst),
    .key_in(key_in),
    .key_out(key_out)
);
endmodule

仿真输出结果如下图所示。
在这里插入图片描述
可以看到,首先是两级D触发器的不同使得q_reset变化,因此激活了重新计数,当计数到指定的数时,如果按键输入还没有发生变化,则认为按键的输入已经稳定,可以将其值输出。按键消抖实验的重点其实就是两级D触发器的输出值,如果在计数没到指定值时,两级D触发器输出有变化会使得 q_reset=1,而 q_reset=1的结果就是计数要从0重新开始,也就是说,要输出稳定的按键输入值,按键的值必须稳定持续指定的时间长度才可以。


板上验证

上面的代码中为了仿真方便,计数设计的比较小,在开发板上验证时,为了使按键消抖的效果明显,我在程序中将稳定的时间设置为1秒,这样就能够更清楚的看到,LED在按键触发1秒之后进行响应,也就是LED动作滞后按键1秒钟。
在开发板上验证使用的代码如下。

`timescale 1ns / 1ps

module key_anti_shake(
    input clk,
    input rst,
    input key_in,
    output key_out
    );

reg [25:0] count;
reg [25:0] count_next;
reg D1,D2;
wire add_flag;
wire q_reset;
reg key_out_d;

assign q_reset = (D1^D2); //judge whether the level change through xor
assign add_flag = ~(count == 26'd50_000_000);  //延迟1s

always@(q_reset,add_flag,count)
begin
    case({
    
    q_reset,add_flag})
        2'b00: count_next <= count;
        2'b01: count_next <= count + 1;
        default: count_next <= 26'd0;  //如果q_reset=1就说明两级D触发器结果不一样,肯定不稳定
    endcase
end

always@(posedge clk or negedge rst)
begin
    if(rst == 1'b0) 
    begin 
        D1 <= 1'b0; 
        D2 <= 1'b0; 
        count <= 26'd0; 
    end 
    else 
    begin 
        D1 <= key_in; 
        D2 <= D1; 
        count <= count_next; 
    end
end

always@(posedge clk or negedge rst)
begin
    if(rst == 1'b0) 
        key_out_d <= 1'b1;
    else if(count == 26'd50_000_000)
        key_out_d <= D2;
    else
        key_out_d <= key_out_d;
end

assign key_out = key_out_d;
endmodule

引脚分配如下图所示。
在这里插入图片描述
把比特流文件下载到开发板上验证时结果一直不正确,后来才发现我是在仿真代码的基础上修改的,而仿真代码中的复位是高电平有效,而我正好也给复位分配了一个按键引脚,而按键在不按下时就是高电平,因此,开发板上电后就一直在复位状态,除非按下复位按键,所以我把代码中的复位改为了低电平有效,重新生成比特流文件,下载到开发板验证。
按键消抖实验的开发板验证结果如下面动图所示。
请添加图片描述
可以看到,持续按下开发板上的 PL KEY1 按键1秒后,对应的 PL LED1 亮,松开按键1秒后,PL LED1 灭,因此,按键消抖的功能实现了!在实际应用中,按键消抖用不了这么长时间,我这里是为了演示的结果更加明显,一般延时大概几十毫秒就可以,其中,要延时的时间(以秒为单位)和计数之间的关系为:计数值 = 要延时的时间 × 频率。
比如在 50MHz 系统中延时 20ms, 计数值 = 20 × 1 0 − 3 × 50 × 1 0 6 = 1 0 6 计数值 = 20 × 10^{-3} × 50 × 10^6 = 10^6 计数值=20×103×50×106=106


以上就是ZYNQ——按键消抖实验的全部内容了!
参考资料:
ZYNQ 开发平台 FPGA 教程 AX7020

猜你喜欢

转载自blog.csdn.net/weixin_42570192/article/details/131236875