OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [kbd.vhd] - Blame information for rev 3

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 howe.r.j.8
--------------------------------------------------------------------------------
2
--
3
--    FileName:         kbd.vhd
4
--    Dependencies:     debounce.vhd
5
--    Design Software:  Quartus II 32-bit Version 12.1 Build 177 SJ Full Version
6
--
7
--    HDL CODE is PROVIDED "AS IS."  DIGI-KEY EXPRESSLY DISCLAIMS ANY
8
--    WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
9
--    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
10
--    PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
11
--    BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
12
--    DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
13
--    PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
14
--    BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
15
--    ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
16
--
17
--    Version History
18
--    Version 1.0 11/29/2013 Scott Larson
19
--      Initial Public Release
20
--
21
--  See https://eewiki.net/pages/viewpage.action?pageId=28279002
22
--
23
--  @note This file has been renamed and updated from the original.
24
--------------------------------------------------------------------------------
25
library ieee;
26
use ieee.std_logic_1164.all;
27
 
28
package kbd_pkg is
29
 
30
        component ps2_kbd_top is
31
                generic(
32
                        clock_frequency:           integer := 50000000; -- system clock frequency in hz
33
                        ps2_debounce_counter_size: integer := 8);       -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
34
                port(
35
                        clk:        in  std_ulogic;                     -- system clock input
36
                        ps2_clk:    in  std_ulogic;                     -- clock signal from PS2 keyboard
37
                        ps2_data:   in  std_ulogic;                     -- data signal from PS2 keyboard
38
                        ascii_new:  out std_ulogic := '0';              -- output flag indicating new ascii value
39
                        ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value
40
        end component;
41
 
42
        component ps2_kbd_core is
43
        generic(
44
                clock_frequency: integer := 50000000;  -- system clock frequency in hz
45
                debounce_counter_size: integer := 8);  -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50mhz)
46
        port(
47
                clk:          in  std_ulogic; -- system clock
48
                ps2_clk:      in  std_ulogic; -- clock signal from PS/2 keyboard
49
                ps2_data:     in  std_ulogic; -- data signal from PS/2 keyboard
50
                ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus
51
                ps2_code:     out std_ulogic_vector(7 downto 0)); -- code received from PS/2
52
        end component;
53
 
54
        component ps2_debounce is
55
                generic(counter_size:  integer := 19); --counter size (19 bits gives 10.5ms with 50mhz clock)
56
                port(
57
                        clk:    in  std_ulogic;
58
                        button: in  std_ulogic;  --input signal to be debounced
59
                        result: out std_ulogic := '0'); --debounced signal
60
        end component;
61
 
62
        component keyboard is
63
                generic(
64
                        clock_frequency:           integer := 50000000; -- system clock frequency in hz
65
                        ps2_debounce_counter_size: integer := 8);       -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
66
                port(
67
                        clk:              in  std_ulogic;        -- system clock input
68
                        rst:              in  std_ulogic;        -- system reset
69
 
70
                        ps2_clk:          in  std_ulogic;        -- clock signal from PS2 keyboard
71
                        ps2_data:         in  std_ulogic;        -- data signal from PS2 keyboard
72
 
73
                        kbd_char_re:      in  std_ulogic;        -- acknowledge kbd_char_buf_new
74
                        kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value
75
                        kbd_char_buf:     out std_ulogic_vector(6 downto 0)); -- ASCII value
76
        end component;
77
end package;
78
 
79
------ Keyboard ----------------------------------------------------------------
80
library ieee;
81
use ieee.std_logic_1164.all;
82
use work.kbd_pkg.all;
83
 
84
entity keyboard is
85
        generic(
86
                clock_frequency:           integer := 50000000; -- system clock frequency in hz
87
                ps2_debounce_counter_size: integer := 8);       -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
88
        port(
89
                clk:              in  std_ulogic;        -- system clock input
90
                rst:              in  std_ulogic;        -- system reset
91
 
92
                ps2_clk:          in  std_ulogic;        -- clock signal from PS2 keyboard
93
                ps2_data:         in  std_ulogic;        -- data signal from PS2 keyboard
94
 
95
                kbd_char_re:      in  std_ulogic;        -- acknowledge kbd_char_buf_new
96
                kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value
97
                kbd_char_buf:     out std_ulogic_vector(6 downto 0)); -- ASCII value
98
end entity;
99
 
100
architecture rtl of keyboard  is
101
        signal kbd_new_c, kbd_new_n:  std_ulogic := '0';
102
        signal kbd_new_edge: std_ulogic := '0';
103
        signal kbd_new:      std_ulogic := '0';                                -- new ASCII char available
104
        signal kbd_char:     std_ulogic_vector(kbd_char_buf'range) := (others => '0'); -- ASCII char
105
        signal kbd_char_o:   std_ulogic_vector(kbd_char_buf'range) := (others => '0'); -- ASCII char
106
begin
107
        kbd_char_buf_new <= kbd_new_c;
108
 
109
        ps2_next: process(clk, rst)
110
        begin
111
                if rst = '1' then
112
                        kbd_new_c  <= '0';
113
                elsif rising_edge(clk) then
114
                        kbd_new_c   <= kbd_new_n;
115
                end if;
116
        end process;
117
 
118
        new_char: entity work.reg
119
        generic map(N => kbd_char'high+1)
120
        port map(
121
                clk => clk,
122
                rst => rst,
123
                di  => kbd_char,
124
                we  => kbd_new_edge,
125
                do  => kbd_char_o);
126
 
127
        char_buf: entity work.reg
128
        generic map(N => kbd_char'high+1)
129
        port map(
130
                clk => clk,
131
                rst => rst,
132
                di  => kbd_char_o,
133
                we  => kbd_char_re,
134
                do  => kbd_char_buf);
135
 
136
        ps2_proc: process(kbd_new_edge, kbd_new_c, kbd_char_re)
137
        begin
138
                if kbd_new_edge = '1' then
139
                        kbd_new_n  <= '1';
140
                elsif kbd_char_re = '1' then
141
                        kbd_new_n  <= '0';
142
                else
143
                        kbd_new_n  <= kbd_new_c;
144
                end if;
145
        end process;
146
 
147
        -- Process a kbd_new into a single edge for the rest of the
148
        -- system.
149
        ps2_edge_new_character_0: entity work.rising_edge_detector
150
        port map(
151
                clk => clk,
152
                rst => rst,
153
                di  => kbd_new,
154
                do  => kbd_new_edge);
155
 
156
        ps2_0: work.kbd_pkg.ps2_kbd_top
157
        generic map(
158
                clock_frequency => clock_frequency,
159
                ps2_debounce_counter_size => ps2_debounce_counter_size)
160
        port map(
161
                clk        => clk,
162
                ps2_clk    => ps2_clk,
163
                ps2_data   => ps2_data,
164
                ascii_new  => kbd_new,
165
                ascii_code => kbd_char);
166
end architecture;
167
------ Keyboard ----------------------------------------------------------------
168
 
169
------ PS2 KBD TOP -------------------------------------------------------------
170
 
171
library ieee;
172
use ieee.std_logic_1164.all;
173
use work.kbd_pkg.all;
174
 
175
entity ps2_kbd_top is
176
        generic(
177
                clock_frequency:           integer := 50000000; -- system clock frequency in hz
178
                ps2_debounce_counter_size: integer := 8);       -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz)
179
        port(
180
                clk:        in  std_ulogic;                     -- system clock input
181
                ps2_clk:    in  std_ulogic;                     -- clock signal from PS2 keyboard
182
                ps2_data:   in  std_ulogic;                     -- data signal from PS2 keyboard
183
                ascii_new:  out std_ulogic := '0';              -- output flag indicating new ascii value
184
                ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value
185
end entity;
186
 
187
architecture rtl of ps2_kbd_top is
188
        type machine is(ready, new_code, translate, output); -- needed states
189
        signal state: machine;                               -- state machine
190
        signal ps2_code_new: std_ulogic;                      -- new PS2 code flag from ps2_kbd_core component
191
        signal ps2_code:     std_ulogic_vector(7 downto 0);   -- PS2 code input form ps2_kbd_core component
192
        signal prev_ps2_code_new: std_ulogic := '1';          -- value of ps2_code_new flag on previous clock
193
        signal break:        std_ulogic := '0';               -- '1' for break code, '0' for make code
194
        signal e0_code:      std_ulogic := '0';               -- '1' for multi-code commands, '0' for single code commands
195
        signal caps_lock:    std_ulogic := '0';               -- '1' if caps lock is active, '0' if caps lock is inactive
196
        signal control_r:    std_ulogic := '0';               -- '1' if right control key is held down, else '0'
197
        signal control_l:    std_ulogic := '0';               -- '1' if left control key is held down, else '0'
198
        signal shift_r:      std_ulogic := '0';               -- '1' if right shift is held down, else '0'
199
        signal shift_l:      std_ulogic := '0';               -- '1' if left shift is held down, else '0'
200
        signal ascii:        std_ulogic_vector(7 downto 0) := x"FF"; -- internal value of ASCII translation
201
 
202
begin
203
 
204
        -- instantiate PS2 keyboard interface logic
205
        ps2_kbd_core_0: work.kbd_pkg.ps2_kbd_core
206
                generic map(
207
                        clock_frequency       => clock_frequency,
208
                        debounce_counter_size => ps2_debounce_counter_size)
209
                port map(
210
                        clk                   => clk,
211
                        ps2_clk               => ps2_clk,
212
                        ps2_data              => ps2_data,
213
                        ps2_code_new          => ps2_code_new,
214
                        ps2_code              => ps2_code);
215
 
216
        process(clk)
217
        begin
218
        if rising_edge(clk) then
219
                prev_ps2_code_new <= ps2_code_new; -- keep track of previous ps2_code_new values to determine low-to-high transitions
220
                case state is
221
 
222
                        -- ready state: wait for a new PS2 code to be received
223
                        when ready =>
224
                                if(prev_ps2_code_new = '0' AND ps2_code_new = '1') then -- new PS2 code received
225
                                        ascii_new <= '0';                               -- reset new ASCII code indicator
226
                                        state <= new_code;                              -- proceed to new_code state
227
                                else                                                    -- no new PS2 code received yet
228
                                        state <= ready;                                 -- remain in ready state
229
                                end if;
230
 
231
                        -- new_code state: determine what to do with the new PS2 code
232
                        when new_code =>
233
                                if(ps2_code = x"F0") then    -- code indicates that next command is break
234
                                        break <= '1';        -- set break flag
235
                                        state <= ready;      -- return to ready state to await next PS2 code
236
                                elsif(ps2_code = x"E0") then -- code indicates multi-key command
237
                                        e0_code <= '1';      -- set multi-code command flag
238
                                        state <= ready;      -- return to ready state to await next PS2 code
239
                                else                         -- code is the last PS2 code in the make/break code
240
                                        ascii(7) <= '1';     -- set internal ascii value to unsupported code (for verification)
241
                                        state <= translate;  -- proceed to translate state
242
                                end if;
243
 
244
                        -- translate state: translate PS2 code to ASCII value
245
                        when translate =>
246
                                        break <= '0';    -- reset break flag
247
                                        e0_code <= '0';  -- reset multi-code command flag
248
 
249
                                        -- handle codes for control, shift, and caps lock
250
                                        case ps2_code is
251
                                                when x"58" =>                   -- caps lock code
252
                                                        if(break = '0') then    -- if make command
253
                                                                caps_lock <= NOT caps_lock; -- toggle caps lock
254
                                                        end if;
255
                                                when x"14" =>                   -- code for the control keys
256
                                                        if(e0_code = '1') then          -- code for right control
257
                                                                control_r <= NOT break; -- update right control flag
258
                                                        else                            -- code for left control
259
                                                                control_l <= NOT break; -- update left control flag
260
                                                        end if;
261
                                                when x"12" =>                   -- left shift code
262
                                                        shift_l <= NOT break;   -- update left shift flag
263
                                                when x"59" =>                   -- right shift code
264
                                                        shift_r <= NOT break;   -- update right shift flag
265
                                                when others => null;
266
                                        end case;
267
 
268
                                        -- translate control codes (these do not depend on shift or caps lock)
269
                                        if(control_l = '1' OR control_r = '1') then
270
                                                case ps2_code is
271
                                                        when x"1E" => ascii <= x"00"; -- ^@  NUL
272
                                                        when x"1C" => ascii <= x"01"; -- ^A  SOH
273
                                                        when x"32" => ascii <= x"02"; -- ^B  STX
274
                                                        when x"21" => ascii <= x"03"; -- ^C  ETX
275
                                                        when x"23" => ascii <= x"04"; -- ^D  EOT
276
                                                        when x"24" => ascii <= x"05"; -- ^E  ENQ
277
                                                        when x"2B" => ascii <= x"06"; -- ^F  ACK
278
                                                        when x"34" => ascii <= x"07"; -- ^G  BEL
279
                                                        when x"33" => ascii <= x"08"; -- ^H  BS
280
                                                        when x"43" => ascii <= x"09"; -- ^I  HT
281
                                                        when x"3B" => ascii <= x"0A"; -- ^J  LF
282
                                                        when x"42" => ascii <= x"0B"; -- ^K  VT
283
                                                        when x"4B" => ascii <= x"0C"; -- ^L  FF
284
                                                        when x"3A" => ascii <= x"0D"; -- ^M  CR
285
                                                        when x"31" => ascii <= x"0E"; -- ^N  SO
286
                                                        when x"44" => ascii <= x"0F"; -- ^O  SI
287
                                                        when x"4D" => ascii <= x"10"; -- ^P  DLE
288
                                                        when x"15" => ascii <= x"11"; -- ^Q  DC1
289
                                                        when x"2D" => ascii <= x"12"; -- ^R  DC2
290
                                                        when x"1B" => ascii <= x"13"; -- ^S  DC3
291
                                                        when x"2C" => ascii <= x"14"; -- ^T  DC4
292
                                                        when x"3C" => ascii <= x"15"; -- ^U  NAK
293
                                                        when x"2A" => ascii <= x"16"; -- ^V  SYN
294
                                                        when x"1D" => ascii <= x"17"; -- ^W  ETB
295
                                                        when x"22" => ascii <= x"18"; -- ^X  CAN
296
                                                        when x"35" => ascii <= x"19"; -- ^Y  EM
297
                                                        when x"1A" => ascii <= x"1A"; -- ^Z  SUB
298
                                                        when x"54" => ascii <= x"1B"; -- ^[  ESC
299
                                                        when x"5D" => ascii <= x"1C"; -- ^\  FS
300
                                                        when x"5B" => ascii <= x"1D"; -- ^]  GS
301
                                                        when x"36" => ascii <= x"1E"; -- ^^  RS
302
                                                        when x"4E" => ascii <= x"1F"; -- ^_  US
303
                                                        when x"4A" => ascii <= x"7F"; -- ^?  DEL
304
                                                        when others => null;
305
                                                end case;
306
                                        else -- if control keys are not pressed
307
 
308
                                                -- translate characters that do not depend on shift, or caps lock
309
                                                case ps2_code is
310
                                                        when x"29" => ascii <= x"20"; -- space
311
                                                        when x"66" => ascii <= x"08"; -- backspace (BS control code)
312
                                                        when x"0D" => ascii <= x"09"; -- tab (HT control code)
313
                                                        when x"5A" => ascii <= x"0D"; -- enter (CR control code)
314
                                                        when x"76" => ascii <= x"1B"; -- escape (ESC control code)
315
                                                        when x"71" =>
316
                                                                if(e0_code = '1') then  -- ps2 code for delete is a multi-key code
317
                                                                        ascii <= x"7F"; -- delete
318
                                                                end if;
319
                                                        when others => null;
320
                                                end case;
321
 
322
                                                -- translate letters (these depend on both shift and caps lock)
323
                                                if((shift_r = '0' AND shift_l = '0' AND caps_lock = '0') OR
324
                                                        ((shift_r = '1' OR shift_l = '1') AND caps_lock = '1')) then  -- letter is lowercase
325
                                                        case ps2_code is
326
                                                                when x"1C" => ascii <= x"61"; -- a
327
                                                                when x"32" => ascii <= x"62"; -- b
328
                                                                when x"21" => ascii <= x"63"; -- c
329
                                                                when x"23" => ascii <= x"64"; -- d
330
                                                                when x"24" => ascii <= x"65"; -- e
331
                                                                when x"2B" => ascii <= x"66"; -- f
332
                                                                when x"34" => ascii <= x"67"; -- g
333
                                                                when x"33" => ascii <= x"68"; -- h
334
                                                                when x"43" => ascii <= x"69"; -- i
335
                                                                when x"3B" => ascii <= x"6A"; -- j
336
                                                                when x"42" => ascii <= x"6B"; -- k
337
                                                                when x"4B" => ascii <= x"6C"; -- l
338
                                                                when x"3A" => ascii <= x"6D"; -- m
339
                                                                when x"31" => ascii <= x"6E"; -- n
340
                                                                when x"44" => ascii <= x"6F"; -- o
341
                                                                when x"4D" => ascii <= x"70"; -- p
342
                                                                when x"15" => ascii <= x"71"; -- q
343
                                                                when x"2D" => ascii <= x"72"; -- r
344
                                                                when x"1B" => ascii <= x"73"; -- s
345
                                                                when x"2C" => ascii <= x"74"; -- t
346
                                                                when x"3C" => ascii <= x"75"; -- u
347
                                                                when x"2A" => ascii <= x"76"; -- v
348
                                                                when x"1D" => ascii <= x"77"; -- w
349
                                                                when x"22" => ascii <= x"78"; -- x
350
                                                                when x"35" => ascii <= x"79"; -- y
351
                                                                when x"1A" => ascii <= x"7A"; -- z
352
                                                                when others => null;
353
                                                        end case;
354
                                                else                                     -- letter is uppercase
355
                                                        case ps2_code is
356
                                                                when x"1C" => ascii <= x"41"; -- A
357
                                                                when x"32" => ascii <= x"42"; -- B
358
                                                                when x"21" => ascii <= x"43"; -- C
359
                                                                when x"23" => ascii <= x"44"; -- D
360
                                                                when x"24" => ascii <= x"45"; -- E
361
                                                                when x"2B" => ascii <= x"46"; -- F
362
                                                                when x"34" => ascii <= x"47"; -- G
363
                                                                when x"33" => ascii <= x"48"; -- H
364
                                                                when x"43" => ascii <= x"49"; -- I
365
                                                                when x"3B" => ascii <= x"4A"; -- J
366
                                                                when x"42" => ascii <= x"4B"; -- K
367
                                                                when x"4B" => ascii <= x"4C"; -- L
368
                                                                when x"3A" => ascii <= x"4D"; -- M
369
                                                                when x"31" => ascii <= x"4E"; -- N
370
                                                                when x"44" => ascii <= x"4F"; -- O
371
                                                                when x"4D" => ascii <= x"50"; -- P
372
                                                                when x"15" => ascii <= x"51"; -- Q
373
                                                                when x"2D" => ascii <= x"52"; -- R
374
                                                                when x"1B" => ascii <= x"53"; -- S
375
                                                                when x"2C" => ascii <= x"54"; -- T
376
                                                                when x"3C" => ascii <= x"55"; -- U
377
                                                                when x"2A" => ascii <= x"56"; -- V
378
                                                                when x"1D" => ascii <= x"57"; -- W
379
                                                                when x"22" => ascii <= x"58"; -- X
380
                                                                when x"35" => ascii <= x"59"; -- Y
381
                                                                when x"1A" => ascii <= x"5A"; -- Z
382
                                                                when others => null;
383
                                                        end case;
384
                                                end if;
385
 
386
                                                -- translate numbers and symbols (these depend on shift but not caps lock)
387
                                                if(shift_l = '1' OR shift_r = '1') then  -- key's secondary character is desired
388
                                                        case ps2_code is
389
                                                                when x"16" => ascii <= x"21"; -- |
390
                                                                when x"52" => ascii <= x"22"; -- "
391
                                                                when x"26" => ascii <= x"23"; -- #
392
                                                                when x"25" => ascii <= x"24"; -- $
393
                                                                when x"2E" => ascii <= x"25"; -- %
394
                                                                when x"3D" => ascii <= x"26"; -- &
395
                                                                when x"46" => ascii <= x"28"; -- (
396
                                                                when x"45" => ascii <= x"29"; -- )
397
                                                                when x"3E" => ascii <= x"2A"; -- *
398
                                                                when x"55" => ascii <= x"2B"; -- +
399
                                                                when x"4C" => ascii <= x"3A"; -- :
400
                                                                when x"41" => ascii <= x"3C"; -- <
401
                                                                when x"49" => ascii <= x"3E"; -- >
402
                                                                when x"4A" => ascii <= x"3F"; -- ?
403
                                                                when x"1E" => ascii <= x"40"; -- @
404
                                                                when x"36" => ascii <= x"5E"; -- ^
405
                                                                when x"4E" => ascii <= x"5F"; -- _
406
                                                                when x"54" => ascii <= x"7B"; -- {
407
                                                                when x"5D" => ascii <= x"7C"; -- |
408
                                                                when x"5B" => ascii <= x"7D"; -- }
409
                                                                when x"0E" => ascii <= x"7E"; -- ~
410
                                                                when others => null;
411
                                                        end case;
412
                                                else -- key's primary character is desired
413
                                                        case ps2_code is
414
                                                                when x"45" => ascii <= x"30"; -- 0
415
                                                                when x"16" => ascii <= x"31"; -- 1
416
                                                                when x"1E" => ascii <= x"32"; -- 2
417
                                                                when x"26" => ascii <= x"33"; -- 3
418
                                                                when x"25" => ascii <= x"34"; -- 4
419
                                                                when x"2E" => ascii <= x"35"; -- 5
420
                                                                when x"36" => ascii <= x"36"; -- 6
421
                                                                when x"3D" => ascii <= x"37"; -- 7
422
                                                                when x"3E" => ascii <= x"38"; -- 8
423
                                                                when x"46" => ascii <= x"39"; -- 9
424
                                                                when x"52" => ascii <= x"27"; -- '
425
                                                                when x"41" => ascii <= x"2C"; -- ,
426
                                                                when x"4E" => ascii <= x"2D"; -- -
427
                                                                when x"49" => ascii <= x"2E"; -- .
428
                                                                when x"4A" => ascii <= x"2F"; -- /
429
                                                                when x"4C" => ascii <= x"3B"; -- ;
430
                                                                when x"55" => ascii <= x"3D"; -- =
431
                                                                when x"54" => ascii <= x"5B"; -- [
432
                                                                when x"5D" => ascii <= x"5C"; -- \
433
                                                                when x"5B" => ascii <= x"5D"; -- ]
434
                                                                when x"0E" => ascii <= x"60"; -- `
435
                                                                when others => null;
436
                                                        end case;
437
                                                end if;
438
 
439
                                        end if;
440
 
441
                                if(break = '0') then  -- the code is a make
442
                                        state <= output;      -- proceed to output state
443
                                else                  -- code is a break
444
                                        state <= ready;       -- return to ready state to await next PS2 code
445
                                end if;
446
 
447
                        -- output state: verify the code is valid and output the ASCII value
448
                        when output =>
449
                                if(ascii(7) = '0') then            -- the PS2 code has an ASCII output
450
                                        ascii_new <= '1';                  -- set flag indicating new ASCII output
451
                                        ascii_code <= ascii(6 downto 0);   -- output the ASCII value
452
                                end if;
453
                                state <= ready;                    -- return to ready state to await next PS2 code
454
 
455
                end case;
456
        end if;
457
        end process;
458
 
459
end;
460
 
461
--------------------------------------------------------------------------------
462
--
463
--   FileName:         ps2_kbd_core.vhd
464
--   Dependencies:     debounce.vhd
465
--   Design Software:  Quartus II 32-bit Version 12.1 Build 177 SJ Full Version
466
--
467
--   HDL CODE IS PROVIDED "AS IS."  DIGI-KEY EXPRESSLY DISCLAIMS ANY
468
--   WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
469
--   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
470
--   PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
471
--   BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
472
--   DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
473
--   PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
474
--   BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
475
--   ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
476
--
477
--   Version History
478
--   Version 1.0 11/25/2013 Scott Larson
479
--     Initial Public Release
480
--
481
--   @note This file has been modified from the original one found at
482
--   <https://eewiki.net/pages/viewpage.action?pageId=28279002>
483
--------------------------------------------------------------------------------
484
 
485
library ieee;
486
use ieee.std_logic_1164.all;
487
 
488
entity ps2_kbd_core is
489
        generic(
490
                clock_frequency: integer := 50000000;  -- system clock frequency in hz
491
                debounce_counter_size: integer := 8);  -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50mhz)
492
        port(
493
                clk:          in  std_ulogic; -- system clock
494
                ps2_clk:      in  std_ulogic; -- clock signal from PS/2 keyboard
495
                ps2_data:     in  std_ulogic; -- data signal from PS/2 keyboard
496
                ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus
497
                ps2_code:     out std_ulogic_vector(7 downto 0)); -- code received from PS/2
498
end entity;
499
 
500
architecture rtl of ps2_kbd_core is
501
 
502
        signal sync_ffs: std_ulogic_vector(1 downto 0);        -- synchronizer flip-flops for PS/2 signals
503
        signal ps2_clk_int: std_ulogic;                        -- debounced clock signal from PS/2 keyboard
504
 
505
        attribute buffer_type: string;
506
        attribute buffer_type of ps2_clk_int: signal is "BUFG";
507
 
508
        signal ps2_data_int: std_ulogic;                       -- debounced data signal from PS/2 keyboard
509
        signal ps2_word: std_ulogic_vector(10 downto 0);       -- stores the ps2 data word
510
        signal parity_error: std_ulogic;                       -- validate parity, start, and stop bits
511
        signal count_idle: integer range 0 to clock_frequency/18000; --counter to determine PS/2 is idle
512
 
513
begin
514
 
515
        --synchronizer flip-flops
516
        process(clk)
517
        begin
518
                if rising_edge(clk) then         -- rising edge of system clock
519
                        sync_ffs(0) <= ps2_clk;  -- synchronize PS/2 clock signal
520
                        sync_ffs(1) <= ps2_data; -- synchronize PS/2 data signal
521
                end if;
522
        end process;
523
 
524
        -- debounce ps2 input signals
525
        debounce_ps2_clk: work.kbd_pkg.ps2_debounce
526
        generic map(counter_size => debounce_counter_size)
527
        port map(clk => clk, button => sync_ffs(0), result => ps2_clk_int);
528
 
529
        debounce_ps2_data: work.kbd_pkg.ps2_debounce
530
        generic map(counter_size => debounce_counter_size)
531
        port map(clk => clk, button => sync_ffs(1), result => ps2_data_int);
532
 
533
        -- input ps2 data
534
        process(ps2_clk_int)
535
        begin
536
                if(ps2_clk_int'event and ps2_clk_int = '0') then          -- falling edge of ps2 clock
537
                        ps2_word <= ps2_data_int & ps2_word(10 downto 1); -- shift in ps2 data bit
538
                end if;
539
        end process;
540
 
541
        -- verify that parity, start, and stop bits are all correct
542
        parity_error <= not (not ps2_word(0) and ps2_word(10) and (ps2_word(9) xor ps2_word(8) xor
543
            ps2_word(7) xor ps2_word(6) xor ps2_word(5) xor ps2_word(4) xor ps2_word(3) xor
544
            ps2_word(2) xor ps2_word(1)));
545
 
546
        -- determine if ps2 port is idle (i.e. last transaction is finished) and output result
547
        process(clk)
548
        begin
549
                if rising_edge(clk) then                           -- rising edge of system clock
550
                        if(ps2_clk_int = '0') then                 -- low ps2 clock, PS/2 is active
551
                                count_idle <= 0;                   -- reset idle counter
552
                        elsif(count_idle /= clock_frequency/18_000) then  -- ps2 clock has been high less than a half clock period (<55us)
553
                                count_idle <= count_idle + 1;      -- continue counting
554
                        end if;
555
 
556
                        if(count_idle = clock_frequency/18_000 and parity_error = '0') then  -- idle threshold reached and no errors detected
557
                                ps2_code_new <= '1';                           -- set flag that new PS/2 code is available
558
                                ps2_code <= ps2_word(8 downto 1);              -- output new PS/2 code
559
                        else                                                   -- PS/2 port active or error detected
560
                                ps2_code_new <= '0';                           -- set flag that PS/2 transaction is in progress
561
                        end if;
562
                end if;
563
        end process;
564
 
565
end;
566
 
567
--------------------------------------------------------------------------------
568
--
569
--   FileName:         (originally) debounce.vhd
570
--   Dependencies:     none
571
--   Design Software:  Quartus II 32-bit Version 11.1 Build 173 SJ Full Version
572
--
573
--   HDL CODE IS PROVIDED "AS IS."  DIGI-KEY EXPRESSLY DISCLAIMS ANY
574
--   WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
575
--   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
576
--   PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
577
--   BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
578
--   DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
579
--   PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
580
--   BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
581
--   ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
582
--
583
--   Version History
584
--   Version 1.0 3/26/2012 Scott Larson
585
--     Initial Public Release
586
--
587
-- @note This file has been modified from the original one found
588
-- on the web from: <https://eewiki.net/pages/viewpage.action?pageId=28279002>
589
--
590
--------------------------------------------------------------------------------
591
 
592
library ieee;
593
use ieee.std_logic_1164.all;
594
use ieee.numeric_std.all;
595
 
596
entity ps2_debounce is
597
        generic(counter_size:  integer := 19); --counter size (19 bits gives 10.5ms with 50mhz clock)
598
        port(
599
                clk:    in  std_ulogic;
600
                button: in  std_ulogic;  --input signal to be debounced
601
                result: out std_ulogic := '0'); --debounced signal
602
end entity;
603
 
604
architecture rtl of ps2_debounce is
605
        signal flipflops:   std_ulogic_vector(1 downto 0); --input flip flops
606
        signal counter_set: std_ulogic;                    --sync reset to zero
607
        signal counter_out: unsigned(counter_size downto 0) := (others => '0'); --counter output
608
begin
609
 
610
        counter_set <= flipflops(0) xor flipflops(1);   --determine when to start/reset counter
611
 
612
        process(clk)
613
        begin
614
                if rising_edge(clk) then
615
                        flipflops(0) <= button;
616
                        flipflops(1) <= flipflops(0);
617
                        if(counter_set = '1') then                  --reset counter because input is changing
618
                                counter_out <= (others => '0');
619
                        elsif(counter_out(counter_size) = '0') then --stable input time is not yet met
620
                                counter_out <= counter_out + 1;
621
                        else                                        --stable input time is met
622
                                result <= flipflops(1);
623
                        end if;
624
                end if;
625
        end process;
626
end;
627
 

powered by: WebSVN 2.1.0

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