-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebounce_one_shot.sv
153 lines (137 loc) · 5.56 KB
/
debounce_one_shot.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company: Cal Poly
// Engineer: Paul Hummel
//
// Create Date: 06/27/2018 02:41:23 AM
// Design Name: debounce_one_shot
// Target Devices: Basys3
// Description:
// FSM-based debouncer with integrated one-shot output.
// One-shot output directly follows successfull completion of debouncing
// the rising edge and then the falling edged of the input signal.
// CLK should be 50 MHz RAT clock
//
// CONFIGURABLE PARAMETERS:
// c_LOW_GOING_HIGH_CLOCKS = minimum # clocks for stable high input
// c_HIGH_GOING_LOW_CLOCKS = minimum # clocks for stable low input
// c_ONE_SHOT_CLOCKS = length of one shot output pulse in clk cycles
//
// Revision:
// Revision 0.01 - Initial SystemVerilog version from Jeff Gerfen's VHDL
////////////////////////////////////////////////////////////////////////////////
module debounce_one_shot(
input CLK,
input BTN,
output logic DB_BTN
);
const logic [7:0] c_LOW_GOING_HIGH_CLOCKS = 8'h19; // 25 clks
const logic [7:0] c_HIGH_GOING_LOW_CLOCKS = 8'h33; // 50 clks
const logic [7:0] c_ONE_SHOT_CLOCKS = 8'h01; // 1 clks
typedef enum { ST_init, ST_BTN_low, ST_BTN_low_to_high, ST_BTN_high, ST_BTN_high_to_low, ST_one_shot} STATES;
STATES NS, PS;
logic [7:0] s_db_count = 8'h00;
logic s_count_rst, s_count_inc = 1'b0;
// Counter block to count the number of clock pulses when enabled /////////
always_ff @(posedge CLK) begin
if (s_count_rst == 1'b1)
s_db_count = 8'h00;
else if (s_count_inc == 1'b1)
s_db_count = s_db_count + 1;
end
////////////////////////////////////////////////////////////////////////////
// FSM State Register //////////////////////////////////////////////////////
always_ff @(posedge CLK) begin
PS = NS;
end
////////////////////////////////////////////////////////////////////////////
// FSM Logic //////////////////////////////////////////////////////////////
always_comb begin
// assign default values to avoid latches
NS = ST_init;
DB_BTN = 1'b0;
s_count_rst = 1'b0;
s_count_inc = 1'b0;
case (PS)
ST_init: begin // initialize FSM
NS = ST_BTN_low;
DB_BTN = 1'b0;
s_count_rst = 1'b1;
end
ST_BTN_low: begin // waiting for button press
if (BTN == 1'b1) begin // press detected
NS = ST_BTN_low_to_high;
s_count_inc = 1'b1; // start counting
end
else begin
NS = ST_BTN_low; // nothing detected
s_count_rst = 1'b1;
end
end
ST_BTN_low_to_high: begin // waiting for high bounce to settle
if (BTN == 1'b1) begin // button is still high
// button stayed high for specified time
if (s_db_count == c_LOW_GOING_HIGH_CLOCKS) begin
NS = ST_BTN_high;
s_count_rst = 1'b1;
end
else begin // keep counting
NS = ST_BTN_low_to_high;
s_count_inc = 1'b1;
end
end
else begin // button low, so still bouncing
NS = ST_BTN_low;
s_count_rst = 1'b1;
end
end
ST_BTN_high: begin // waiting for button release
if (BTN == 1'b1) begin
NS = ST_BTN_high;
s_count_rst = 1'b1;
end
else begin // button released
NS = ST_BTN_high_to_low;
s_count_inc = 1'b1;
end
end
ST_BTN_high_to_low: begin
if (BTN == 1'b0) begin // button still low
// button stayed low for specified time
if (s_db_count == c_HIGH_GOING_LOW_CLOCKS) begin
NS = ST_one_shot;
s_count_rst = 1'b1;
end
else begin // keep counting
NS = ST_BTN_high_to_low;
s_count_inc = 1'b1;
end
end
else begin // button high, so still bouncing
NS = ST_BTN_high;
s_count_rst = 1'b1;
end
end
ST_one_shot: begin // button press complete, create a single pulse
// one shot pulse has been high for specified time
if (s_db_count == c_ONE_SHOT_CLOCKS) begin
NS = ST_init;
s_count_rst = 1'b1;
DB_BTN = 1'b0;
end
else begin // keep counting
NS = ST_one_shot;
s_count_inc = 1'b1;
DB_BTN = 1'b1;
end
end
default: begin // failsafe
NS = ST_init;
s_count_rst = 1'b1;
s_count_inc = 1'b0;
DB_BTN = 1'b0;
end
endcase
end
////////////////////////////////////////////////////////////////////////////
endmodule