OpenCores
URL https://opencores.org/ocsvn/keypad_scanner/keypad_scanner/trunk

Subversion Repositories keypad_scanner

[/] [keypad_scanner/] [web_uploads/] [keypad_scanner.v] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 root
//---------------------------------------------------------------------------
2
// keypad_scanner.v  -- Small keypad scanner module
3
//
4
//
5
// Description: See description below (which suffices for IP core
6
//                                     specification document.)
7
//
8
// Copyright (C) 2002 John Clayton and OPENCORES.ORG (this Verilog version)
9
//
10
// This source file may be used and distributed without restriction provided
11
// that this copyright statement is not removed from the file and that any
12
// derivative work contains the original copyright notice and the associated
13
// disclaimer.
14
//
15
// This source file is free software; you can redistribute it and/or modify
16
// it under the terms of the GNU Lesser General Public License as published
17
// by the Free Software Foundation;  either version 2.1 of the License, or
18
// (at your option) any later version.
19
//
20
// This source is distributed in the hope that it will be useful, but WITHOUT
21
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
22
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
23
// License for more details.
24
//
25
// You should have received a copy of the GNU Lesser General Public License
26
// along with this source.
27
// If not, download it from http://www.opencores.org/lgpl.shtml
28
//
29
//-----------------------------------------------------------------------------
30
//
31
// Author: John Clayton
32
// Date  : Jan. 30, 2003
33
// Update: Mar. 24, 2003  Copied this file from "serial_divide_uu.v"
34
//                        Stripped out extraneous stuff.
35
// Update: Mar. 31, 2003  Finished coding, added function "one_low_among_z"
36
//                        and tested in hardware.
37
//
38
//-----------------------------------------------------------------------------
39
// Description:
40
//
41
// This module is for reading keypresses on a small matrix-style keypad,
42
// keyboard or game controller.
43
//
44
// In the interest of keeping things simple and generic, this module does not
45
// attempt to look at multiple keypresses, whether the key is being depressed
46
// or else released, N-key rollover or any other such complicated ideas.
47
//
48
// In fact, with an X-Y matrix of keys if multiple keys are pressed in
49
// different rows of the matrix, which share the same column(s), a situation
50
// arises in which it is impossible to detect which keys are pressed...
51
// These ambiguous cases do not occur with only 2 keys pressed, but can
52
// always happen with 3 keys pressed simultaneously.  Please be aware of this!
53
//
54
// For cases which are not ambiguous, this unit provides a "1" for keys that
55
// are pressed, and "0" for keys not pressed.  In the ambiguous cases, extra
56
// "1" bits appear in the output, even though the corresponding key may not
57
// have been pressed.
58
//
59
// So if all the keys are pressed in one whole row and one whole column,
60
// then the output will consist of all "1" bits.
61
//
62
// The module is termed a "keypad_scanner" because the output, while useful
63
// in real-time, is a sampling of the keypad matrix.  Each scan produces a
64
// single "snapshot" of data containing a unique bit for each key.  Each
65
// scan is initiated by providing a pulse on the scan_i input.  When the
66
// scan is complete, the new sampled data is produced on the dat_o bus,
67
// and the stb_o output pulses for one clock.  The scan_i input is ignored
68
// during a scan.  If the stb_o output is tied to the scan_i input, then the
69
// unit will scan continuously, as fast as it can proceed.  Each full scan
70
// requires one clock per row scanned.
71
//
72
// Although the keys are scanned row-by-row, the row data are stored and the
73
// results are presented in parallel at a given instant in time.  The speed
74
// of scanning is programmable by parameters.
75
//
76
// If the scan speed is reduced to a low enough rate (say 50 full scans per
77
// second) then this can also provide a "free" debouncing function.
78
// Well, honestly it is not a completely fool-proof switch debounce, since
79
// the scan may happen to pick up a bounce as a reading, but most bounce is
80
// less than 20ms in duration, so that the chances of anyone caring about this
81
// are very slim indeed.
82
//
83
// In fact, one could launch from here into a full scale discussion of the
84
// nature of debouncing, flip-flop metastability issues and the like.
85
// But I will forego such a philosophical discussion in order to concentrate
86
// on more practical issues.
87
//
88
// IN ORDER FOR THIS MODULE TO WORK PROPERLY, the column inputs must have
89
// pullup resistors on them.  The rows simply provide a "low" output which can
90
// overcome the pullups and provide for a valid reading at the column inputs.
91
// Obviously, the value of the pullups is not critical as long as the row
92
// scanning rate is slow enough that the pullups can charge the parasitic
93
// capacitance of the keypad column wires in between row scans.
94
// Many programmable logic families provide built in pullup resistors which
95
// can be selected in the pin-constraints file.  These will be more than
96
// adequate for the use of this module.  Just don't forget to add them, or
97
// you will most likely get all "0" output.
98
//
99
// There are parameters provided in order to set the size of the X-Y key
100
// matrix.  However, the author was envisioning a small sized keyboard for use
101
// with this module.  Perhaps the number of keys in the matrix would range
102
// from 8 (min.) to about 64 or so. (max.)
103
//
104
// A matrix larger than this might still work, but there would be a very large
105
// bus of outputs coming from the module... so just be aware of it.
106
//
107
// Parameters are:
108
//
109
// ROWS_PP        -- The number of rows in the keypad matrix
110
// COLS_PP        -- The number of columns in the keypad matrix
111
// ROW_BITS_PP    -- The number of bits needed to hold ROWS_PP-1
112
// TMR_CLKS_PP    -- The number of clk_i edges before the next
113
//                   row is scanned.
114
// TMR_BITS_PP    -- The number of bits needed to hold TMR_CLKS_PP-1
115
//
116
//-----------------------------------------------------------------------------
117
 
118
 
119
module keypad_scanner (
120
  clk_i,
121
  clk_en_i,
122
  rst_i,
123
  scan_i,
124
  col_i,
125
  row_o,
126
  dat_o,
127
  done_o
128
  );
129
 
130
parameter ROWS_PP = 4;         // Number of rows to scan
131
parameter COLS_PP = 4;         // Number of columns to read
132
parameter ROW_BITS_PP = 2;     // Number of bits needed to hold ROWS_PP-1
133
parameter TMR_CLKS_PP = 60000; // Set for 200 scans/sec, 4 rows, 48MHz clk_i
134
parameter TMR_BITS_PP = 16;    // Number of bits needed to hold TMR_CLKS_PP-1
135
 
136
// I/O declarations
137
input  clk_i;                           // The clock
138
input  clk_en_i;                        // Used to qualify clk_i input
139
input  rst_i;                           // synchronous reset
140
input  scan_i;                          // Used to start a keypad scan
141
input  [COLS_PP-1:0] col_i;             // The column inputs
142
output [ROWS_PP-1:0] row_o;             // The row outputs
143
output [COLS_PP*ROWS_PP-1:0] dat_o;     // The output bus
144
output done_o;                          // indicates completion of scan
145
 
146
reg  [COLS_PP*ROWS_PP-1:0] dat_o;
147
 
148
// Internal signal declarations
149
reg  [TMR_BITS_PP-1:0] tmr;
150
reg  [ROW_BITS_PP-1:0] row;
151
reg  [COLS_PP*(ROWS_PP-1)-1:0] shift_register;
152
reg  idle_state;
153
 
154
wire keyscan_row_clk;
155
wire end_of_scan;
156
wire [ROWS_PP-1:0] row_output_binary;
157
 
158
//--------------------------------------------------------------------------
159
// Functions & Tasks
160
//--------------------------------------------------------------------------
161
 
162
function [ROWS_PP-1:0] one_low_among_z;
163
  input [ROW_BITS_PP-1:0] row;
164
  integer k;
165
  begin
166
    for (k=0; k<ROWS_PP; k=k+1)
167
      one_low_among_z[k] = (k == row)?1'b0:1'bZ;
168
  end
169
endfunction
170
 
171
 
172
//--------------------------------------------------------------------------
173
// Module code
174
 
175
// This is the inter-row timer.  It advances the row count at a certain rate
176
always @(posedge clk_i)
177
begin
178
  if (rst_i || idle_state) tmr <= 0;
179
  else if (clk_en_i) tmr <= tmr + 1;
180
end
181
assign keyscan_row_clk = (clk_en_i && (tmr == TMR_CLKS_PP-1));
182
 
183
// This is the row counter
184
always @(posedge clk_i)
185
begin
186
  if (rst_i || end_of_scan) row <= 0;
187
  else if (keyscan_row_clk) row <= row + 1;
188
end // End of always block
189
assign end_of_scan = ((row == ROWS_PP-1) && keyscan_row_clk);
190
 
191
// This is the "idle_state" logic
192
always @(posedge clk_i)
193
begin
194
  if (rst_i) idle_state <= 1;     // Begin in idle state
195
  else if (scan_i && idle_state) idle_state <= 0;
196
  else if (end_of_scan && ~scan_i) idle_state <= 1;
197
end
198
assign done_o = (end_of_scan || idle_state);
199
 
200
// This is the shift register.  Whenever the row count advances, this
201
// shift register captures row data, except during "final_scan_row."
202
// When "final_scan_row" is active, then that final row goes directly
203
// to the output for storage.
204
always @(posedge clk_i)
205
begin
206
  if (keyscan_row_clk && ~end_of_scan)
207
  begin
208
    shift_register <= {shift_register,col_i};
209
 
210
    // Alternative coding
211
    //shift_register[COLS_PP*(ROWS_PP-1)-1:COLS_PP] 
212
    //               <= shift_register[COLS_PP*(ROWS_PP-2)-1:0];
213
    //shift_register[COLS_PP-1:0] <= col_i;    
214
  end
215
end
216
 
217
// This is the bank of actual output registers.  It captures the column info
218
// during the final row, and also all of the other column info. stored during
219
// previous row counts (i.e. what is stored in the shift register)
220
always @(posedge clk_i)
221
begin
222
  if (rst_i) dat_o <= 0;
223
  else if (keyscan_row_clk && end_of_scan) dat_o <= {shift_register,col_i};
224
end
225
 
226
// This is the row driver.  It decodes the current row count into a "one low
227
// of N" output.  The rest of the N outputs are high-impedance (Z).
228
assign row_o = one_low_among_z(row);
229
 
230
endmodule
231
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.