module debouncer#(
  parameter WIDTH = 20,
  parameter LAG = 250000
)(
  input wire clk,
  input wire nrst,
  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 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 = 24,//2^24 corresponds to 0.67s max time
  parameter DEBOUNCE_LAG = 250000, //250000 = 10ms
  parameter FIRST_CLICK = 2500000,//100ms -> 2500000
  parameter FREQ_START = 8333333,//(1/f) 3Hz -> 333ms -> 8333333
  //parameter FREQ_DECREMENT = 12,// hardcoded -> percentage * 16: 12 -> 12/16 = 75% of prev each loop
  parameter FREQ_MAX = 1250000//(1/f) 20Hz -> 50ms -> 1250000
)(
  input wire clk, //25MHz
  input wire nrst,
  input wire butt,

  output reg [31: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),
    .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 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
