-
Notifications
You must be signed in to change notification settings - Fork 384
/
debounce_v1.v
118 lines (94 loc) · 2.69 KB
/
debounce_v1.v
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
//------------------------------------------------------------------------------
// debounce_v1.v
// published as part of https://github.com/pConst/basic_verilog
// Konstantin Pavlov, [email protected]
//------------------------------------------------------------------------------
// INFO ------------------------------------------------------------------------
// Button debounce v1
//
// - sampling inputs using configurable divided clock (this is the
// simplest form of low-pass filter)
// - switching output only when both samples have equal level
// (this gives some form of hysteresis in case we sample unstable data)
//
/* --- INSTANTIATION TEMPLATE BEGIN ---
debounce_v1 #(
.WIDTH( 4 ),
.SAMPLING_FACTOR( 16 )
) DB1 (
.clk( clk ),
.nrst( 1'b1 ),
.ena( 1'b1 ),
.in( btn[3:0] ),
.out( btn_db[3:0] )
);
--- INSTANTIATION TEMPLATE END ---*/
module debounce_v1 #( parameter
WIDTH = 1,
SAMPLING_FACTOR = 16 // 0 - sampling every clk
// 1 - sampling on clk/2
// 2 - sampling on clk/4 etc....
// only one or none should be enabled
TREAT_UNSTABLE_AS_HIGH = 0,
TREAT_UNSTABLE_AS_LOW = 0
)(
input clk,
input nrst,
input ena,
input [WIDTH-1:0] in,
output reg [WIDTH-1:0] out = 0
);
localparam SAMPLING_RANGE = 32;
wire [SAMPLING_RANGE-1:0] s_clk;
clk_divider #(
.WIDTH( SAMPLING_RANGE )
) clk_div (
.clk( clk ),
.nrst( nrst ),
.ena( 1'b1 ),
.out( s_clk[SAMPLING_RANGE-1:0] )
);
wire [SAMPLING_RANGE-1:0] s_clk_rise;
edge_detect #(
.WIDTH( SAMPLING_RANGE )
) clk_div_ed (
.clk( clk ),
.anrst( nrst ),
.in( s_clk[SAMPLING_RANGE-1:0] ),
.rising( s_clk_rise[SAMPLING_RANGE-1:0] )
);
wire do_sample;
assign do_sample = s_clk_rise[SAMPLING_FACTOR];
reg [WIDTH-1:0] in_d1 = 0;
reg [WIDTH-1:0] in_d2 = 0;
always @(posedge clk) begin
if (~nrst) begin
in_d1[WIDTH-1:0] <= 0;
in_d2[WIDTH-1:0] <= 0;
end else if (ena && do_sample) begin
in_d1[WIDTH-1:0] <= in_d2[WIDTH-1:0];
in_d2[WIDTH-1:0] <= in[WIDTH-1:0];
end // if
end
integer i;
always @(posedge clk) begin
if( ~nrst ) begin
out[WIDTH-1:0] <= 0;
end else begin
// every input has its own state
for (i = 0; i < WIDTH; i=i+1) begin
case ( {in_d2[i],in_d1[i]} )
2'b00: out[i] <= 1'b0;
2'b11: out[i] <= 1'b1;
default: begin
if (TREAT_UNSTABLE_AS_HIGH) begin
out[i] <= 1'b1;
end else if (TREAT_UNSTABLE_AS_LOW) begin
out[i] <= 1'b0;
end
end
endcase
end // for
end
end
endmodule