当前位置:   article > 正文

按键控制led变化_按键控制led灯亮灭

按键控制led灯亮灭

按键控制led变化

一、简介

使用按键控制开发板上一个led灯的亮灭,当按键按下的时候led灯就亮,当再一次按下按键的时候led就不亮了。由于按键存在抖动,按键松开的时候led灯就不亮,所以需要一个消抖模块对按键消抖

二、代码

module key_led (
    input wire clk,
    input wire rst_n,
    input wire[3:0] key,
     
    output reg[3:0] led
);
parameter TIME_0_2S = 10_000_000;  //
reg[24:0] cnt_0_2S;
reg[1:0] state;
//=================0.2s计时====================//
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_0_2S<=24'd0;
    end
    else if(cnt_0_2S == TIME_0_2S - 1)begin
        cnt_0_2S<=24'd0;
    end
    else begin
        cnt_0_2S<=cnt_0_2S+1'b1;
    end
end


//=================state=================//
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        state<=2'b00;
    end
    else if(cnt_0_2S == TIME_0_2S - 1) begin
        state<=state+1'b1;
    end
    else begin
        state<=state;
    end
end
//================按键控制流水灯===============//
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        led<=4'b0000;
    end
    else if(~key[0]) begin
        case (state)
            2'd0:led<=4'b0001;
            2'd1:led<=4'b0010;
            2'd2:led<=4'b0100;
            2'd3:led<=4'b1000;
        endcase
    end
    else if(~key[1]) begin
        case (state)
            2'd0:led<=4'b1000;
            2'd1:led<=4'b0100;
            2'd2:led<=4'b0010;
            2'd3:led<=4'b0001;
        endcase
    end
    else if(~key[2]) begin
        case (state)
            2'd0:led<=4'b1111;
            2'd1:led<=4'b0000;
            2'd2:led<=4'b1111;
            2'd3:led<=4'b0000;
        endcase
    end
    else if(~key[3]) begin
        case (state)
            2'd0:led<=4'b1111;
            2'd1:led<=4'b1111;
            2'd2:led<=4'b1111;
            2'd3:led<=4'b1111;
        endcase
    end
    else begin
        led<=4'b0000;
    end
end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// -----------------------------------------------------------------------------
// Author : 辣子鸡味的句橘子,331197689@qq.com
// File   : key_debounce.v
// Create : 2023-07-14 10:36:44
// Revise : 2023-07-14 10:36:44
// Editor : sublime text4, tab size (4)
// -----------------------------------------------------------------------------
module key_debounce(
    input wire clk,
    input wire rst_n,
    input wire[3:0] key_in,//四个按键信号输入

    output reg[3:0] key_out//四个按键信号消抖输出
);

parameter TIME_20MS = 1000_000;
reg[19:0] cnt;//20ms计数器
wire add_cnt;//计数开始
wire ent_cnt;//计数终止
wire nedge;//下降沿检测

reg[3:0] key_in_r0;//同步key_in输入信号
reg[3:0] key_in_r1;//延迟一个周期
reg[3:0] key_in_r2;//延迟两个周期

reg flag;//消抖开始标志信号

//计数器模块,当addent满足时开始计数,检测到下降沿重新计数,end_ent满足时停止计数,消抖完成
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       cnt<=20'd0;
    end
    else if(add_cnt)begin
        if(ent_cnt)begin
            cnt<=20'd0;
        end
        else if(nedge)begin
            cnt<=20'd0;
        end
        else begin
            cnt<=cnt+1;
        end
    end
    else begin
        cnt<=cnt;
    end
end

assign add_cnt = flag;//计数开始条件
assign end_cnt = (cnt == TIME_20MS - 1)&&add_cnt;//终止结束条件,当满足计时到20ms,且满足计时条件时成立

//信号延时模块
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        key_in_r0<=4'b1111;
        key_in_r1<=4'b1111;
        key_in_r2<=4'b1111;
    end
    else begin
        key_in_r0<=key_in;
        key_in_r1<=key_in_r0;
        key_in_r2<=key_in_r1;
    end
end

//检测下降沿,当任意一个按键出现下降沿都会被检测到
assign nedge = (~key_in_r1[0]&key_in_r2[0])||(~key_in_r1[1]&key_in_r2[1])||(~key_in_r1[2]&key_in_r2[2])||(~key_in_r1[3]&key_in_r2[3]);

//消抖开始模块
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       flag<=1'b0;
    end
    else if(nedge)begin//当出现下降沿开始消抖
        flag<=1'b1;
    end
    else if(end_cnt)begin//当end_cnt满足时停止消抖
        flag<=1'b0;
    end
    else begin
        flag<=flag;
    end
end

//输出信号赋值模块,当消抖完毕标志按键按下,出现一个脉冲信号表示按键按下
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
       key_out<=4'b1111;//默认为高电瓶
    end
    else if(end_cnt)begin
        key_out<=key_in;//稳定信号赋值
    end
    else begin
       key_out<=4'b1111;//其他信号默认为高电平
    end
end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
module key_top(
    input wire clk,
    input wire rst_n,
    input wire[3:0] key,

    output wire[3:0] led
);
wire[3:0] key_r;

key_debounce inst_key_debounce (
	.clk(clk), 
	.rst_n(rst_n), 
	.key(key), 
	.key_r(key_r));
key_led inst_key_led (
	.clk(clk), 
	.rst_n(rst_n), 
	.key(key_r), 
	.led(led));

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

三、仿真代码

module key_top_tb();
reg clk;
reg rst_n;
reg[3:0] key;
wire[3:0] led;
wire[3:0] key_r;

parameter SYS_CLK = 20;
parameter TIME = 100;
always #(SYS_CLK/2) clk = ~clk;
initial begin
	clk=1'b0;
	rst_n=1'b0;
	#(2*SYS_CLK);
	rst_n=1'b1;
	key = 4'b1111;
	#(2*SYS_CLK);
	repeat (19) begin
   		key[0] = ~key[0];
   		#(2*SYS_CLK);
	end
	key[0] = 1'b0;
	#(400*SYS_CLK);
	$stop;
end
key_debounce #(.TIME_20MS(TIME)) inst_key_bounce (
	.clk(clk), 
	.rst_n(rst_n), 
	.key(key), 
	.key_r(key_r));

key_led #(.TIME_0_2S(TIME)) inst_key_led (
	.clk(clk), 
	.rstn(rstn), 
	.key(key), 
	.led(led));


endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

四、仿真结果

在这里插入图片描述

五、总结

总的来说编写不算复杂,需要注意的是模块之间的连接和按键消抖模块

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/685621
推荐阅读
相关标签
  

闽ICP备14008679号