FPGA实现按键检测消抖程序

这个是黑金的板子提供的原版按键消抖程序
FPGA实现按键检测消抖程序_第1张图片

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/02/29 10:59:33
// Design Name: 
// Module Name: key_detected
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module key_detected#
( parameter FREQ = 50,         //model clock :Mhz
  parameter MAX_TIME = 20     //ms
)(
    input       clk, 
    input       rstn, 
    input       button_in,
    output reg  button_posedge,
    output reg  button_negedge   
);
 ---------------- internal constants --------------
localparam N = 32 ;           // debounce timer bitwidth

localparam TIMER_MAX_VAL =   MAX_TIME * 1000 * FREQ;
---------------- internal variables ---------------
reg  [N-1 : 0]  q_reg;      // timing regs
reg  [N-1 : 0]  q_next;
reg DFF1, DFF2;             // input flip-flops
wire q_add;                 // control flags
wire q_reset;
reg button_out_d0;
reg  button_out;
 ------------------------------------------------------

contenious assignment for counter control
assign q_reset = (DFF1  ^ DFF2);          // xor input flip flops to look for level chage to reset counter
assign q_add = ~(q_reg == TIMER_MAX_VAL); // add to counter when q_reg msb is equal to 0
    
 combo counter to manage q_next 
always @ ( q_reset, q_add, q_reg)
begin
    case( {q_reset , q_add})
        2'b00 :
                q_next <= q_reg;
        2'b01 :
                q_next <= q_reg + 1;
        default :
                q_next <= { N {1'b0} };
    endcase     
end

 Flip flop inputs and q_reg update
always @ ( posedge clk or negedge rstn)
begin
    if(!rstn)
    begin
        DFF1 <= 1'b0;
        DFF2 <= 1'b0;
        q_reg <= { N {1'b0} };
    end
    else
    begin
        DFF1 <= button_in;
        DFF2 <= DFF1;
        q_reg <= q_next;
    end
end

 counter control
always @ ( posedge clk or negedge rstn)
begin
	if(!rstn)
		button_out <= 1'b1;
    else if(q_reg == TIMER_MAX_VAL)
        button_out <= DFF2;
    else
        button_out <= button_out;
end

always @ ( posedge clk or negedge rstn)
begin
	if(!rstn)
	begin
		button_out_d0 <= 1'b1;
		button_posedge <= 1'b0;
		button_negedge <= 1'b0;
	end
	else
	begin
		button_out_d0 <= button_out;
		button_posedge <= ~button_out_d0 & button_out;
		button_negedge <= button_out_d0 & ~button_out;
	end	
end
endmodule

然后自己写了一个key检测的程序


`timescale 1ns / 1ps

module keyscan#
( parameter FREQ = 50,         //model clock :Mhz
  parameter MAX_TIME = 20,    //ms
  parameter key_init_voltag=1'b1
)(
    input clk,
    input rstn,
    input key_in,
    output  key_posedge,
	output  key_negedge
    );
localparam Cnt_bit=32;
localparam TIMER_MAX_VAL = MAX_TIME * 1000 * FREQ;
//---------------------------------------------
reg [Cnt_bit-1:0] Count;
wire Cnt_Clear;
//---------------------------------------------
reg Detect1,Detect2;
assign Cnt_Clear=(Detect1^Detect2);
always@(posedge clk or negedge rstn)
	if(!rstn)begin
		Detect1<=1'b0;
		Detect2<=1'b0;	
	   end
	   else begin
		Detect1<=key_in;	
		Detect2<=Detect1;
	   end
//---------------------------------------------	   
always@(posedge clk or negedge rstn)
	if(!rstn)begin
		Count<=32'd0;	
	   end
	   else if(Cnt_Clear)
		Count<=32'd0;
	   else if(Count==TIMER_MAX_VAL)
		Count<=32'd0;
	   else Count<=Count+1'd1;	   
//----------------------------------------------	   
reg sample_voltag;
always@(posedge clk or negedge rstn)
	if(!rstn)
	 sample_voltag<=key_init_voltag;
	 else if(Count==TIMER_MAX_VAL)
	 sample_voltag<=key_in;
	 else
	 sample_voltag<=key_init_voltag;
	 
//------------------------------------------------
reg Delay1_sample;
reg Delay2_sample;
always@(posedge clk)begin
	Delay1_sample<=sample_voltag;
	Delay2_sample<=Delay1_sample;
end
assign key_posedge=(~Delay1_sample&Delay2_sample);
assign key_negedge=(Delay1_sample&~Delay2_sample);
endmodule

大致讲解一下思路:
传统的软件消抖的思路是等待电平稳定后采样,来确定按键是否按下。
我们认为一般抖动一般时间10-20ms范围内。
1.首先我们需要计数器来计时,这个计数器在检测到电平变化时候就清零,否则就一直计数。
2.当计数到20ms时候采样输入的按键电平,当检测到电平变低后,则说明按键被拉低,当依然是高电平,这说明按键还是没有按下。
3.检测采样的电平上升沿,下降沿即可输出检测到按下按键的电平。

你可能感兴趣的:(数字IC基础知识回顾)