module debouncer#( parameter WIDTH = 4, parameter LAG = 10 )( input wire clk, input wire nrst, input wire debounce_tick, //1kHz input wire butt, output reg filtered ); reg [WIDTH-1:0] cnt; reg prev_butt; reg butt_buff;//just to make button synced with clock always @(posedge clk or negedge nrst) begin if(!nrst) begin cnt<=LAG; butt_buff<=0; prev_butt<=0; filtered<=0; end else if (debounce_tick) begin if (prev_butt == butt_buff) begin if (cnt) begin cnt <= cnt-1; end else begin filtered <= butt_buff; end end else begin cnt <= LAG; end prev_butt <= butt_buff; butt_buff <= butt; end end endmodule module button#( parameter WIDTH = 5, parameter DEBOUNCE_LAG = 10, //250000 = 10ms parameter FIRST_CLICK = 25,//100ms parameter FREQ_START = 31,//(1/f) 3Hz -> 333ms rounded down to 310ms to reduce bits //parameter FREQ_DECREMENT = 12,// hardcoded -> percentage * 16: 12 -> 12/16 = 75% of prev each loop parameter FREQ_MAX = 5 //(1/f) 20Hz -> 50ms )( input wire clk, //25MHz input wire nrst, input wire debounce_tick, //100Hz input wire cnt_tick, //1kHz input wire butt, output reg [7:0] press_count ); reg butt_filt; reg [WIDTH-1:0] time_cntr; //reg [WIDTH-1:0] curr_period; reg [WIDTH-1:0] next_period; reg [WIDTH-1:0] period_decremented; reg is_pressed; reg if_increment; debouncer#(.LAG(DEBOUNCE_LAG)) deb( .clk(clk), .nrst(nrst), .debounce_tick(debounce_tick), .butt(butt), .filtered(butt_filt) ); always @(posedge clk or negedge nrst) begin if(!nrst) begin press_count<=0; time_cntr<=FIRST_CLICK; next_period<=FREQ_START; is_pressed<=0; if_increment<=0; end else if (cnt_tick) begin if_increment <= 0; if(is_pressed) begin if (time_cntr==0) begin if_increment <= 1; time_cntr <= next_period; if (period_decremented < FREQ_MAX) begin next_period <= FREQ_MAX; end else begin next_period <= period_decremented; end end else begin time_cntr <= time_cntr-1; end end else begin time_cntr<=FIRST_CLICK; next_period<=FREQ_START; end is_pressed <= butt_filt; press_count <= press_count + (if_increment | (!is_pressed & butt_filt)); //period_decremented <= (next_period>>4)*FREQ_DECREMENT; // we loose some prec here, but who cares with this time resolution //12=0b1100 period_decremented <= ({next_period,1'h0} + {1'h0,next_period})>>2; end end endmodule