FPGA学习——按键控制LED流水灯(附源码 无按键消抖版本)

一、前言

在博主的cyclone4开发板上一共有4个按键,本次实验的目的是为了实现每按下一次按键,都会使开发板上的4个LED灯切换一次状态,博主一共设计了四种状态,分别是:

按键状态
按键1按下自右向左的流水灯
按键2按下自左向右的流水灯
按键3按下四灯常亮
按键4按下四灯闪烁

二、开发板按键原理图

在这里插入图片描述

  • 由原理图可以看出,开发板按键按下代表低电平

三、源码

在源码中博主设计了一个0.2s的计数器和两位的cstate状态寄存器,用来控制LED的状态及流水灯闪烁。同时可以看出博主设计了一个flag寄存器,由于本次实验未添加按键消抖模块,因此按键按下后需要一直按住才能实现效果,而引入flag后,我们便可以通过按键按下后一瞬间的电平改变从而改变flag的状态,再由flag的状态控制LED的状态,以此算是一种无按键消抖的平替。

注意:这并不能算是按键消抖,只是因为抖动时间极短,难以在LED灯上体现出来,实际上flag最后还是采样的稳定的低电平信号。
按键消抖及按键消抖控制led请查看博主此篇博文!!
这算是博主在初学FPGA是犯下的错误!!!

module key_led (
    input   wire            clk,
    input   wire            rst_n,
    input   wire    [3:0]   key,

    output  reg     [3:0]   led
);
    parameter MAX = 10_000_000;
    reg [23:0]  cnt;
    reg [1:0]   cstate;
    reg [3:0]   flag;

//0.2s计数器
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)begin
            cnt <= 1'b0;
        end
        else if(cnt == MAX - 1'b1)begin
            cnt <= 1'b0;
        end
        else begin
            cnt <= cnt + 1'b1;
        end
    end

//状态控制 之所以不需要在状态计满后清零,是因为后续在计数至11后再加1值来到100
//而我们的状态设置为两位寄存器,因此只取后两位变为00,相当于清零
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cstate <= 2'd0;
        end
        else if(cnt == MAX - 1'b1)begin
            cstate <= cstate + 1'b1;
        end
        else begin
            cstate <= cstate;
        end
    end
//根据按键状态改变flag状态
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            flag <= 4'b0000;
        end
        else if(key[0] == 1'b0)begin
            flag <= 4'b0001;
        end
        else if(key[1] == 1'b0)begin
            flag <= 4'b0010;
        end
        else if(key[2] == 1'b0)begin
            flag <= 4'b0100;
        end
        else if(key[3] == 1'b0)begin
            flag <= 4'b1000;
        end
        else begin
            flag <= flag;
        end
    end
//根据flag状态改变led状态
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            led <= 4'b0000;
        end
        else if(flag == 4'b0001)begin
            case (cstate)
               2'd0 : led <= 4'b0001;
               2'd1 : led <= 4'b0010;
               2'd2 : led <= 4'b0100;
               2'd3 : led <= 4'b1000;
                default: led <= 4'b0000;
            endcase
        end
        else if(flag == 4'b0010)begin
            case (cstate)
               2'd0 : led <= 4'b1000;
               2'd1 : led <= 4'b0100;
               2'd2 : led <= 4'b0010;
               2'd3 : led <= 4'b0001;
                default: led <= 4'b0000;
            endcase
        end
        else if(flag == 4'b0100)begin
            case (cstate)
               2'd0 : led <= 4'b1111;
               2'd1 : led <= 4'b0000;
               2'd2 : led <= 4'b1111;
               2'd3 : led <= 4'b0000;
                default: led <= 4'b0000;
            endcase
        end
        else if(flag == 4'b1000)begin
            case (cstate)
               2'd0 : led <= 4'b1111;
               2'd1 : led <= 4'b1111;
               2'd2 : led <= 4'b1111;
               2'd3 : led <= 4'b1111;
                default: led <= 4'b0000;
            endcase
        end
        else begin
            led <= 4'b0000;
        end
    end

endmodule

四、实现效果

在这里插入图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
FPGA按键消抖实现流水灯的方法是通过在按键输入信号上应用消抖电路来解决按键抖动问题。消抖电路可以使用计数器和状态机的组合来实现。当按键按下时,计数器开始计数,如果在一定的时间内没有检测到按键抬起的信号,那么就认为按键有效,触发流水灯的状态变化。这样可以避免因按键抖动而导致流水灯频繁切换的问题。 在给出的代码中,按键消抖的实现是通过计数器cnt来实现的。当按键按下时,计数器开始计数,当计数器达到最大值时,即认为按键有效,触发流水灯的状态变化。同时,在计数器达到最大值之前,如果检测到按键抬起的信号,计数器会被清零,重新开始计数。 具体实现的代码如下: ```verilog module key_ctrl ( input clk, input rst_n, input wire key, output wire \[3:0\] led_on ); parameter MAX = 25'd25_000_000; reg \[25:0\] cnt; //计数寄存器 reg\[3:0\] led_r; //记录0.5s计数器设计 always @(posedge clk or negedge rst_n) begin if(!rst_n) begin cnt <= 26'd0; end else if (cnt == MAX - 1'd1) begin cnt <= 26'd0; end else begin cnt <= cnt + 1'd1; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin led_r <= 4'b0001; end else if(!key) begin if (cnt == MAX - 1'd1) begin led_r <= {led_r\[2:0\], led_r\[3\]}; end else begin led_r <= led_r; end end else begin led_r <= led_r; end end assign led_on = led_r; endmodule ``` 这段代码中,按键消抖的实现是通过两个always块来完成的。第一个always块用于计数器的计数和清零,第二个always块用于观察按键状态并触发流水灯的状态变化。通过这种方式,可以实现按键消抖并实现流水灯效果。 #### 引用[.reference_title] - *1* [FPGA按键消抖后实现流水灯控制](https://blog.csdn.net/Headogerz/article/details/81529807)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [FPGA按键流水灯](https://blog.csdn.net/jynyyhd/article/details/131698029)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【FPGA第二天】按键消抖+流水灯](https://blog.csdn.net/qq_53085291/article/details/130352656)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值