debounce switches
Stefan Schuermans

Stefan Schuermans commited on 2012-04-03 20:23:39
Showing 2 changed files, with 141 additions and 37 deletions.

... ...
@@ -15,49 +15,110 @@ END ENTITY e_io_switches;
15 15
 
16 16
 ARCHITECTURE a_io_switches OF e_io_switches IS
17 17
 
18
-    SIGNAL n_sample: std_logic_vector(1 DOWNTO 0);
19
-    SIGNAL r_sample: std_logic_vector(1 DOWNTO 0)  := (OTHERS => '0');
20
-    SIGNAL r_prev:   std_logic_vector(1 DOWNTO 0)  := (OTHERS => '0');
21
-    SIGNAL n_cnt:    std_logic_vector(31 DOWNTO 0);
22
-    SIGNAL r_cnt:    std_logic_vector(31 DOWNTO 0) := (OTHERS => '0');
18
+    CONSTANT c_scale:  natural := 50000;
19
+    CONSTANT c_states: natural := 5;
23 20
 
21
+    SUBTYPE t_state  IS std_logic_vector(31 DOWNTO 0);
22
+    TYPE    t_states IS ARRAY(0 TO c_states - 1) OF t_state;
23
+
24
+    CONSTANT c_state_def:  t_state  := io_switches_to_slv(
25
+                                         c_io_switches_pins_default);
26
+    CONSTANT c_states_def: t_states := (OTHERS => c_state_def);
27
+
28
+    SIGNAL n_scale: natural RANGE 0 TO c_scale - 1;
29
+    SIGNAL r_scale: natural RANGE 0 TO c_scale - 1 := 0;
30
+
31
+    SIGNAL n_states: t_states;
32
+    SIGNAL r_states: t_states := c_states_def;
33
+
34
+    SIGNAL n_debounced: t_state;
35
+    SIGNAL r_debounced: t_state := c_state_def;
36
+
37
+    SIGNAL n_rot_val:  std_logic_vector( 1 DOWNTO 0);
38
+    SIGNAL r_rot_val:  std_logic_vector( 1 DOWNTO 0) := (OTHERS => '0');
39
+    SIGNAL r_rot_prev: std_logic_vector( 1 DOWNTO 0) := (OTHERS => '0');
40
+    SIGNAL n_rot_cnt:  std_logic_vector(31 DOWNTO 0);
41
+    SIGNAL r_rot_cnt:  std_logic_vector(31 DOWNTO 0) := (OTHERS => '0');
42
+
43
+BEGIN
44
+
45
+    p_scale: PROCESS(r_scale)
46
+    BEGIN
47
+        IF r_scale >= c_scale - 1 THEN
48
+            n_scale <= 0;
49
+        ELSE
50
+            n_scale <= r_scale + 1;
51
+        END IF;
52
+    END PROCESS p_scale;
53
+
54
+    p_sample: PROCESS(pin_i_switches, r_scale, r_states)
24 55
     BEGIN
56
+        IF r_scale = 0 THEN
57
+            n_states(0) <= io_switches_to_slv(pin_i_switches);
58
+            FOR i IN 1 TO c_states - 1 LOOP
59
+                n_states(i) <= r_states(i - 1);
60
+            END LOOP;
61
+        ELSE
62
+            n_states <= r_states;
63
+        END IF;
64
+    END PROCESS p_sample;
65
+
66
+    p_debounce: PROCESS(r_states, r_debounced)
67
+        VARIABLE v_or:  t_state;
68
+        VARIABLE v_and: t_state;
69
+    BEGIN
70
+        v_or  := r_states(0);
71
+        v_and := r_states(0);
72
+        FOR i IN 1 TO c_states - 1 LOOP
73
+            v_or  := v_or OR r_states(i);
74
+            v_and := v_and AND r_states(i);
75
+        END LOOP;
76
+        n_debounced <= (r_debounced AND v_or) OR v_and;
77
+    END PROCESS p_debounce;
25 78
 
26
-    p_sample: PROCESS(pin_i_switches)
79
+    p_de_gray: PROCESS(r_debounced)
80
+        VARIABLE v_debounced: t_io_switches_pins;
27 81
     BEGIN
28 82
         -- de-gray-code rotary inputs
29
-        IF pin_i_switches.rot_b = '1' THEN
30
-            IF pin_i_switches.rot_a = '1' THEN
31
-                n_sample <= "00";
83
+        v_debounced := io_switches_from_slv(r_debounced);
84
+        IF v_debounced.rot_b = '1' THEN
85
+            IF v_debounced.rot_a = '1' THEN
86
+                n_rot_val <= "00";
32 87
             ELSE
33
-                n_sample <= "11";
88
+                n_rot_val <= "11";
34 89
             END IF;
35 90
         ELSE
36
-            IF pin_i_switches.rot_a = '1' THEN
37
-                n_sample <= "01";
91
+            IF v_debounced.rot_a = '1' THEN
92
+                n_rot_val <= "01";
38 93
             ELSE
39
-                n_sample <= "10";
94
+                n_rot_val <= "10";
40 95
             END IF;
41 96
         END IF;
42
-    END PROCESS p_sample;
97
+    END PROCESS p_de_gray;
43 98
 
44
-    p_cnt: PROCESS(r_sample, r_prev, r_cnt)
99
+    p_rot_cnt: PROCESS(r_rot_val, r_rot_prev, r_rot_cnt)
45 100
         VARIABLE v_delta: signed(1 DOWNTO 0);
46 101
     BEGIN
47
-        v_delta := signed(r_sample) - signed(r_prev);
48
-        n_cnt <= std_logic_vector(signed(r_cnt) + v_delta);
49
-    END PROCESS p_cnt;
102
+        v_delta := signed(r_rot_val) - signed(r_rot_prev);
103
+        n_rot_cnt <= std_logic_vector(signed(r_rot_cnt) + v_delta);
104
+    END PROCESS p_rot_cnt;
50 105
 
51 106
     p_sync: PROCESS(rst, clk)
52 107
     BEGIN
53 108
         IF rst = '1' THEN
54
-            r_sample <= (OTHERS => '0');
55
-            r_prev   <= (OTHERS => '0');
56
-            r_cnt    <= (OTHERS => '0');
109
+            r_scale     <= 0;
110
+            r_states    <= c_states_def;
111
+            r_debounced <= c_state_def;
112
+            r_rot_val   <= (OTHERS => '0');
113
+            r_rot_prev  <= (OTHERS => '0');
114
+            r_rot_cnt   <= (OTHERS => '0');
57 115
         ELSIF rising_edge(clk) THEN
58
-            r_sample <= n_sample;
59
-            r_prev   <= r_sample;
60
-            r_cnt    <= n_cnt;
116
+            r_scale     <= n_scale;
117
+            r_states    <= n_states;
118
+            r_debounced <= n_debounced;
119
+            r_rot_val   <= n_rot_val;
120
+            r_rot_prev  <= r_rot_val;
121
+            r_rot_cnt   <= n_rot_cnt;
61 122
         END IF;
62 123
     END PROCESS p_sync;
63 124
 
... ...
@@ -67,20 +128,9 @@ BEGIN
67 128
             o_rd_data <= (OTHERS => '0');
68 129
         ELSIF rising_edge(clk) THEN
69 130
             IF i_addr = "0" THEN
70
-                o_rd_data( 3 DOWNTO  0) <= pin_i_switches.sw;
71
-                o_rd_data( 7 DOWNTO  4) <= (OTHERS => '0');
72
-                o_rd_data( 8)           <= pin_i_switches.east;
73
-                o_rd_data( 9)           <= pin_i_switches.north;
74
-                o_rd_data(10)           <= pin_i_switches.south;
75
-                o_rd_data(11)           <= pin_i_switches.west;
76
-                o_rd_data(15 DOWNTO 12) <= (OTHERS => '0');
77
-                o_rd_data(16)           <= pin_i_switches.center;
78
-                o_rd_data(23 DOWNTO 17) <= (OTHERS => '0');
79
-                o_rd_data(24)           <= pin_i_switches.rot_a;
80
-                o_rd_data(25)           <= pin_i_switches.rot_b;
81
-                o_rd_data(31 DOWNTO 26) <= (OTHERS => '0');
131
+                o_rd_data <= r_debounced;
82 132
             ELSE
83
-                o_rd_data <= r_cnt;
133
+                o_rd_data <= r_rot_cnt;
84 134
             END IF;
85 135
         END IF;
86 136
     END PROCESS p_read;
... ...
@@ -16,5 +16,59 @@ PACKAGE io_switches_pins IS
16 16
             rot_b:  std_logic;
17 17
         END RECORD;
18 18
 
19
+    CONSTANT c_io_switches_pins_default: t_io_switches_pins := (
20
+            sw     => "0000",
21
+            east   => '0',
22
+            north  => '0',
23
+            south  => '0',
24
+            west   => '0',
25
+            center => '0',
26
+            rot_a  => '1',
27
+            rot_b  => '1'
28
+        );
29
+
30
+    FUNCTION io_switches_to_slv(switches: t_io_switches_pins)
31
+        RETURN std_logic_vector;
32
+
33
+    FUNCTION io_switches_from_slv(slv: std_logic_vector(31 DOWNTO 0))
34
+        RETURN t_io_switches_pins;
35
+
19 36
 END PACKAGE io_switches_pins;
20 37
 
38
+PACKAGE BODY io_switches_pins IS
39
+
40
+    FUNCTION io_switches_to_slv(switches: t_io_switches_pins)
41
+        RETURN std_logic_vector IS
42
+        VARIABLE v_slv: std_logic_vector(31 DOWNTO 0);
43
+    BEGIN
44
+        v_slv( 3 DOWNTO  0) := switches.sw;
45
+        v_slv( 7 DOWNTO  4) := (OTHERS => '0');
46
+        v_slv( 8)           := switches.east;
47
+        v_slv( 9)           := switches.north;
48
+        v_slv(10)           := switches.south;
49
+        v_slv(11)           := switches.west;
50
+        v_slv(15 DOWNTO 12) := (OTHERS => '0');
51
+        v_slv(16)           := switches.center;
52
+        v_slv(23 DOWNTO 17) := (OTHERS => '0');
53
+        v_slv(24)           := switches.rot_a;
54
+        v_slv(25)           := switches.rot_b;
55
+        v_slv(31 DOWNTO 26) := (OTHERS => '0');
56
+        RETURN v_slv;
57
+    END FUNCTION io_switches_to_slv;
58
+
59
+    FUNCTION io_switches_from_slv(slv: std_logic_vector(31 DOWNTO 0))
60
+        RETURN t_io_switches_pins IS
61
+        VARIABLE v_switches: t_io_switches_pins;
62
+    BEGIN
63
+        v_switches.sw     := slv( 3 DOWNTO  0);
64
+        v_switches.east   := slv( 8);
65
+        v_switches.north  := slv( 9);
66
+        v_switches.south  := slv(10);
67
+        v_switches.west   := slv(11);
68
+        v_switches.center := slv(16);
69
+        v_switches.rot_a  := slv(24);
70
+        v_switches.rot_b  := slv(25);
71
+        RETURN v_switches;
72
+    END FUNCTION io_switches_from_slv;
73
+
74
+END PACKAGE BODY io_switches_pins;
21 75