ZYNQ学习笔记(五)---按键控制LED灯亮灭实验

这个实验其实很早就做了,但是由于这段时间自己一直在忙一些其他的事所以没有及时更新。今天抽出个空来更新一下。本次实验是关于按键控制LED亮灭。其中涉及到的内容有计数器、按键消抖以及一些简单的逻辑。

1.按键消抖的原理

按键消抖的方法有很多种,目前我知道的有大概两种,一种是使用移位寄存器打拍,但是只有当移位寄存器一直输出0或者一直输出1的时候,才代表完成了消抖;另一种是使用计数器和锁存键值来实现消抖,这里我介绍后者,因为感觉后者更加稳定可靠一些,虽然代码有些许的繁琐。

采用这个方法,想要实现按键消抖,我们首先需要先编写一个计数器(用于定时,大约20ms),这个计数器有一个特点:在抖动的时候不计时,会自动清零,只有在键值稳定的时候才会计数到20ms。

为了让计数器具有这个特点,我们在设计计数器之前,先对前一时钟和后一时钟的键值进行分别进行缓存,最后将这两个键值异或起来赋值给一个标志位key_n,用于在键值不稳定时控制时钟去清0。

然后我们需要一个检测并锁存键值的latch,当每次计满20ms的时候取一次键值,并与先前的键值进行比较。最后由比较后的结果来控制LED亮灭。

具体原理可以再参考这位博主的博客:基于FPGA的按键消抖_luoai_2666的博客-CSDN博客_fpga按键消抖

2.代码实现

这边也可以改成2个或者多个按键控制led,只要修改相应变量的位宽和变量个数即可,读者可以自行修改。

///*----------------2-按键消抖+按键控制LED亮灭(1个按键控制LED,另一个用于复位)-----------------*/

module key(
            input wire clk,//时钟主频50M,计数100 0000次达到20ms
            input wire rst_n,
            
            input wire sw_1,
            output reg [1:0] led
    );
    reg  key_buffer1;
    reg  key_buffer2;

//-------judge-------//    
always @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        key_buffer1<=1'b1;
        key_buffer2<=1'b1;
    end
    else begin
        key_buffer1<=sw_1;
        key_buffer2<=key_buffer1;
    end    
end

wire  key_n;//用于判断前后两个时钟采样得到的键值是否一样
assign key_n=key_buffer1^key_buffer2;//按位异或,当没有按键按下时,key_n=0

//----------counter---------//
/*只有在按键值不变时才会一直计数至20ms。如果按键值两个时钟前后有所改变(此时也就是按键抖动的时候),那么计数就清零。*/
    reg [19:0] cnt;  //100 0000转换成bin就是需要20位
    wire add_cnt;
    wire end_cnt;
always @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        cnt<=20'd0;
    end
    else if(add_cnt)begin
        if(end_cnt) 
            cnt<=0;
        else 
            cnt <= cnt+1'b1;
    end
end

assign add_cnt=1;
assign end_cnt=(key_n||(cnt==100_0000-1));//当按键值变化(抖动或者按键状态变化) 或者 计数到20ms 时,end_cnt变为1。

//----------latch---------//
reg  latch;
reg  latch_fin;
always @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
    latch <= 1'b1;
    latch_fin <= 1'b1;
    end
    else begin
            latch_fin <= latch;
        if(cnt==100_0000-1)begin
            latch <= sw_1;
        end
    end    
end

wire  led_ctrl=latch_fin &(~latch);//先前的按键状态latch_fin:11;按下后一按键状态latch:01

always @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led <=2'b11;
    end
    else if(led_ctrl) led <= 2'b01;
end
    
    
    
    
endmodule

运行仿真后效果如下图所示:

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值