button.v 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. module debouncer#(
  2. parameter WIDTH = 20,
  3. parameter LAG = 250000
  4. )(
  5. input wire clk,
  6. input wire nrst,
  7. input wire butt,
  8. output reg filtered
  9. );
  10. reg [WIDTH-1:0] cnt;
  11. reg prev_butt;
  12. reg butt_buff;//just to make button synced with clock
  13. always @(posedge clk or negedge nrst) begin
  14. if(!nrst) begin
  15. cnt<=LAG;
  16. butt_buff<=0;
  17. prev_butt<=0;
  18. filtered<=0;
  19. end else begin
  20. if (prev_butt == butt_buff) begin
  21. if (cnt) begin
  22. cnt <= cnt-1;
  23. end else begin
  24. filtered <= butt_buff;
  25. end
  26. end else begin
  27. cnt <= LAG;
  28. end
  29. prev_butt <= butt_buff;
  30. butt_buff <= butt;
  31. end
  32. end
  33. endmodule
  34. module button#(
  35. parameter WIDTH = 24,//2^24 corresponds to 0.67s max time
  36. parameter DEBOUNCE_LAG = 250000, //250000 = 10ms
  37. parameter FIRST_CLICK = 2500000,//100ms -> 2500000
  38. parameter FREQ_START = 8333333,//(1/f) 3Hz -> 333ms -> 8333333
  39. //parameter FREQ_DECREMENT = 12,// hardcoded -> percentage * 16: 12 -> 12/16 = 75% of prev each loop
  40. parameter FREQ_MAX = 1250000//(1/f) 20Hz -> 50ms -> 1250000
  41. )(
  42. input wire clk, //25MHz
  43. input wire nrst,
  44. input wire butt,
  45. output reg [31:0] press_count
  46. );
  47. reg butt_filt;
  48. reg [WIDTH-1:0] time_cntr;
  49. //reg [WIDTH-1:0] curr_period;
  50. reg [WIDTH-1:0] next_period;
  51. reg [WIDTH-1:0] period_decremented;
  52. reg is_pressed;
  53. reg if_increment;
  54. debouncer#(.LAG(DEBOUNCE_LAG)) deb(
  55. .clk(clk),
  56. .nrst(nrst),
  57. .butt(butt),
  58. .filtered(butt_filt)
  59. );
  60. always @(posedge clk or negedge nrst) begin
  61. if(!nrst) begin
  62. press_count<=0;
  63. time_cntr<=FIRST_CLICK;
  64. next_period<=FREQ_START;
  65. is_pressed<=0;
  66. if_increment<=0;
  67. end else begin
  68. if_increment <= 0;
  69. if(is_pressed) begin
  70. if (time_cntr==0) begin
  71. if_increment <= 1;
  72. time_cntr <= next_period;
  73. if (period_decremented < FREQ_MAX) begin
  74. next_period <= FREQ_MAX;
  75. end else begin
  76. next_period <= period_decremented;
  77. end
  78. end else begin
  79. time_cntr <= time_cntr-1;
  80. end
  81. end else begin
  82. time_cntr<=FIRST_CLICK;
  83. next_period<=FREQ_START;
  84. end
  85. is_pressed <= butt_filt;
  86. press_count <= press_count + (if_increment | (!is_pressed & butt_filt));
  87. //period_decremented <= (next_period>>4)*FREQ_DECREMENT; // we loose some prec here, but who cares with this time resolution
  88. //12=0b1100
  89. period_decremented <= ({next_period,1'h0} + {1'h0,next_period})>>2;
  90. end
  91. end
  92. endmodule