【FPGA/verilog -入门学习14】vivado FPGA按键消抖

//led流水 1s


//1,按键触发变化,上升沿 or 下降沿,都清除计数
//2,当20ms计数到来时,加载一次按键状态,如果中途有按键变化,清除计数
`timescale 1ns/1ps

module vlg_design(
    input i_clk,
    input i_rest_n,
    input[7:0] key,
    output reg[7:0] led
    );
    
`define SIMULATION 
`ifdef     SIMULATION
parameter CNT_20MS_MAX = 200/20 - 1;
`else
parameter CNT_20MS_MAX = 20_000_000/20 - 1;
`endif


//4个按键边沿检测
reg [1:0]r_key_pluse;
assign  w_key_press = key[0] & key[1] & key[2] & key[3] ;
always @(posedge i_clk) begin
    if(!i_rest_n) r_key_pluse <= 2'd0;
    else r_key_pluse <= {r_key_pluse[0],w_key_press};
end

 wire  w_key_pos = r_key_pluse[0] &~r_key_pluse[1];
 wire  w_key_nes = r_key_pluse[1] &~r_key_pluse[0];



//20ms计数
//当20ms 没有破坏的时候,一直正常计数,当有发生按键抖动时候清除
reg [19:0]r_cnt_20ms ;
always @(posedge i_clk) begin
    if(!i_rest_n) r_cnt_20ms <= 2'd0;
    else if(w_key_pos || w_key_nes) r_cnt_20ms <= 2'd0;
    else if(r_cnt_20ms < CNT_20MS_MAX) r_cnt_20ms <= r_cnt_20ms + 1;
    else r_cnt_20ms <= 2'd0;
end

wire [3:0]w_key_temp = (r_cnt_20ms == CNT_20MS_MAX)?key[3:0]: w_key_temp;

//按键状态变化标志
reg [3:0]r_key_save[1:0];
 
always @(posedge i_clk) begin
    if(!i_rest_n)begin
    r_key_save[1] <= 4'd0;
    r_key_save[0] <= 4'd0;
    end
    else  begin
        r_key_save[1] <= r_key_save[0];
        if (r_cnt_20ms == CNT_20MS_MAX) r_key_save[0] <= w_key_temp;
    end
end

wire [3:0]w_key_flag = (r_key_save[1] &~ r_key_save[0]); //按键按下1->0 flag = 1 触发,0->1 ,1->1 ,0->0 ,flg =0

//led灯显示状态

always @(posedge i_clk) begin
    if(!i_rest_n) led[3:0] <= 4'd0;
    else if (w_key_flag[0]) led[0] = ~led[0] ;
    else if (w_key_flag[1]) led[1] = ~led[1] ;
    else if (w_key_flag[2]) led[2] = ~led[2] ;
    else if (w_key_flag[3]) led[3] = ~led[3] ;
end


endmodule


`timescale 1ns/1ps

module testbench_top();
    

//参数定义

`define CLK_PERIORD        20        //时钟周期设置为20ns(50MHz)    


//接口申明
reg i_clk;
reg i_rest_n;
reg [7:0]  key;
wire [7:0] led;
    

    
//对被测试的设计进行例化
    
vlg_design        uut_vlg_design(
    .i_clk(i_clk),
    .i_rest_n(i_rest_n),
    .key(key),
    .led(led)
    );    

///

 

initial begin
key <= 8'b11111111;
i_clk <= 0;
i_rest_n <= 0;
#20;
i_rest_n <= 1;

end


always #(`CLK_PERIORD/2) i_clk = ~i_clk;

initial begin

@(posedge i_clk);
@(posedge i_rest_n);




 
key <= 8'b11111110;
repeat(15) @(posedge i_clk);

key <= 8'b11111111;
repeat(50) @(posedge i_clk);    

key <= 8'b11111101;
repeat(5) @(posedge i_clk);

key <= 8'b11111111;
repeat(50) @(posedge i_clk);    

key <= 8'b11110111;
repeat(5) @(posedge i_clk);    
    
    
 

#2_000_000;
$stop;

end
endmodule

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值