按键消抖+控制led灯

   实现功能描述:通过选择不同按键,控制4个小灯的不同变化。具体实现功能如下:

      当按键key1按下时,led灯从右往左依次闪烁;

      当按键key2按下时,led灯从左往右依次闪烁;

      当按键key3按下时,led灯全亮;

      当按键key4按下时,led灯每次加1'b1;//如:led=0010;led+1'b1=0011;

程序:

        led灯模块:

          

module key_led (
    input  wire       clk,//时钟50MHZ
    input  wire       rst_n,//复位信号,下降沿有效
    input  wire [3:0] key_value,
    input wire  [3:0] key_flag,

    output reg  [3:0] led 
);
//按键消抖
//wire [3:0] flag;
//wire [3:0] key_value;
parameter  TIME = 24'd10_000_000;//0.2s
reg [23:0]  cnt;//计数寄存器,计数0.2s
reg [2:0]   state;//记录四个led状态

//0.2s计数器模块
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt <= 24'd0;//计数器清零
    end
    else if(cnt == TIME - 1)begin//记满10_000_000个数后清零
        cnt <= 24'd0;//计数器清零
    end
    else begin
        cnt <= cnt + 1'd1;
    end
end
//状态确定模块
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        state <= 3'd0;
    end
    else if((key_flag==4'b0001)&&(key_value[0]==1'b0))begin //此时led从右往左依次闪烁
        state <= 3'd1;
    end
    else if((key_flag==4'b0010)&&(key_value[1]==1'b0))begin //此时led从左往右依次闪烁
        state <= 3'd2;
    end
    else if((key_flag==4'b0100)&&(key_value[2]==1'b0))begin //此时四个led灯同时闪烁
        state <= 3'd3;
    end
    else if((key_flag==4'b1000)&&(key_value[3]==1'b0))begin //此时led加一
        state <= 3'd4;
    end
    else begin
        state <= state;
    end   
end

//状态控制led模块
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        led <= 4'b0001;
    end
    else begin
        case (state)
            1: if (cnt == TIME - 1'b1) 
                  led<= {led[2:0],led[3]};
                else 
                  led <= led;
            2: if(cnt == TIME - 1'b1)
                  led <= {led[0],led[3:1]};
                else 
                   led <= led;
            3: if(cnt == TIME - 1'b1)
                  led <= 4'b1111;
                else
                  led <= led;
            4: if(cnt == TIME - 1'b1) 
                  led <=led+1'b1;
                else
                  led <=led;    
            default:led <= 4'b0001; 
        endcase
    end
end

endmodule

  按键消抖模块:

 

//四个按键消抖
module key_debounce (
    input wire clk,
    input wire rst_n,
    input wire [3:0] key,

    output reg [3:0] flag,
    output reg [3:0] key_value
);
parameter DELAY = 20'd1000_000;//20ms
reg [19:0]  delay_cnt ;//延迟计数器
reg [3:0]   key_reg;   //中间按键寄存器,存放当前按键的值,用于和下次按键作比较

//延迟计数器模块
always @(posedge clk or negedge rst_n) begin
   if (!rst_n) begin
       delay_cnt <= 20'd0;
       key_reg   <=4'b1111;
   end
   else begin
       key_reg <= key;
       if((key_reg[0]!=key[0])||(key_reg[1]!=key[1])||(key_reg[2]!= key[2])||(key_reg[3]!=key[3]))begin//如果抖动
       delay_cnt <= DELAY;   
       end
       else begin
          if(delay_cnt>20'd0)begin
            delay_cnt <= delay_cnt - 1'b1;
          end
          else begin
            delay_cnt <= 20'd0;//如果延时计数器小于等于0,延时计数器清零
          end
       end
   end
end
//获取各个按键的状态以及其稳定信号
//根据延时计数器获取flag[0]状态以及稳定按键信号key_value[0]
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
       flag[0]      <= 1'b0;
       key_value[0] <= 1'b1;
    end
    else if((delay_cnt == 20'd0)&&(key[0]==1'b0))begin
       flag[0]      <=1'b1;//当条件满足,改变抖动标志
       key_value[0] <=key[0];//将key[0]的稳定信号存入key_value中 
    end
    else begin
        flag[0]      <= 1'b0;//计数器没有记满1000_000;此时抖动
        key_value[0] <= key_value[0];
    end
end
//根据延时计数器获取flag[1]状态以及稳定按键信号key_value[1]
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
       flag[1]      <= 1'b0;
       key_value[1] <= 1'b1;
    end
    else if((delay_cnt == 20'd0)&&(key[1]==1'b0))begin
      flag[1]      <=1'b1;//当条件满足,改变抖动标志
       key_value[1] <=key[1];//将key[0]的稳定信号存入key_value中 
    end
    else begin
       flag[1]      <= 1'b0;//计数器没有记满1000_000;此时抖动
        key_value[1] <= key_value[1];
    end
end
//根据延时计数器获取flag[2]状态以及稳定按键信号key_value[2]
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      flag[2]      <= 1'b0;
       key_value[2] <= 1'b1;
    end
    else if((delay_cnt == 20'd0)&&(key[2]==1'b0))begin
       flag[2]      <=1'b1;//当条件满足,改变抖动标志
       key_value[2] <=key[2];//将key[0]的稳定信号存入key_value中 
    end
    else begin
       flag[2]      <= 1'b0;//计数器没有记满1000_000;此时抖动
        key_value[2] <= key_value[2];
    end
end
//根据延时计数器获取flag[3]状态以及稳定按键信号key_value[3]
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      flag[3]      <= 1'b0;
       key_value[3] <= 1'b1;
    end
    else if((delay_cnt == 20'd0)&&(key[3]==1'b0))begin
       flag[3]      <=1'b1;//当条件满足,改变抖动标志
       key_value[3] <=key[3];//将key[0]的稳定信号存入key_value中 
    end
    else begin
        flag[3]      <= 1'b0;//计数器没有记满1000_000;此时抖动
        key_value[3] <= key_value[3];
    end
end
endmodule

顶层模块:

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

    output wire[3:0] led
);
wire [3:0] key_value;
wire [3:0] flag;
parameter  TIME = 24'd10_000_000;//0.2s
key_led #(.TIME(TIME)) key_led_inst(
    /*input  wire      */.clk  (clk  ),//时钟50MHZ
    /*input  wire      */.rst_n(rst_n),//复位信号,下降沿有效
    /*input  wire [3:0]*/.key_value(key_value ),
                         .key_flag (flag),
    /*output reg  [3:0]*/.led (led) 
);


parameter DELAY = 20'b1000_1000;//20ms

key_debounce #(.DELAY(DELAY)) key_debounce_inst (
   /*input wire      */.clk      (clk  ),
   /*input wire      */.rst_n    (rst_n),
   /*input wire [3:0]*/.key      (key  ),

   /*output reg [3:0]*/.flag     (flag     ),
   /*output reg [3:0]*/.key_value(key_value)
);

    
endmodule

仿真测试模块:

   

`timescale 1ns/1ns


module tb_top_key_led ();
   reg clk;
   reg rst_n;
   reg [3:0] key;

   wire [3:0] led;
initial begin
    clk = 1'b0;
    rst_n=1'b0;
    #10
    rst_n=1'b1;
end

always #10 clk = ~clk;
initial begin
    key = 4'b1111;
    #40000
    key = 4'b1110;
    #40000
    key = 4'b1101;
    #40000
    key = 4'b1011;
    #40000
    key=  4'b0111;
    #50000;
    $stop;
end
top_key_led #(.TIME(200),
          .DELAY(1000)) 
top_key_led_inst(
    /*input  wire      */ .clk  (clk  ),//时钟50MHZ
    /*input  wire      */ .rst_n(rst_n),//复位信号,下降沿有效
    /*input  wire [3:0]*/ .key  (key  ),

    /*output reg  [3:0]*/ .led  (led)
);    
endmodule

仿真图:

   

 经过上板验证后,实验现象和实验预期设想相同,本次没有上传实验现象视频。   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值