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

Subversion Repositories forth-cpu

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

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

powered by: WebSVN 2.1.0

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