-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathkeyboard_controller.vhd
121 lines (96 loc) · 3.77 KB
/
keyboard_controller.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity KEYBOARD_CONTROLLER is
port(
clock : in STD_LOGIC;
clear : in STD_LOGIC;
--
ps2_clk : in STD_LOGIC;
ps2_data : in STD_LOGIC;
--
key_code : out STD_LOGIC_VECTOR (7 downto 0);
key_event : out STD_LOGIC
);
end entity;
architecture BEHV of KEYBOARD_CONTROLLER is
type STATE_TYPE is (start, wait_clock_low, wait_clock_high, get_key_code);
signal state : STATE_TYPE;
signal ps2_clk_f : STD_LOGIC;
signal ps2_data_f : STD_LOGIC;
signal ps2_clk_reg : STD_LOGIC_VECTOR (7 downto 0);
signal ps2_data_reg : STD_LOGIC_VECTOR (7 downto 0);
signal ps2_word_reg : STD_LOGIC_VECTOR (10 downto 0);
signal bit_counter : STD_LOGIC_VECTOR (3 downto 0);
constant BIT_COUNTER_MAX : STD_LOGIC_VECTOR (3 downto 0) := "1011";
begin
-- filters clock and data signals of the keyboard using shift registers
filter_process : process (clock, clear)
begin
if clear = '1' then
ps2_clk_reg <= X"00";
ps2_data_reg <= X"00";
ps2_clk_f <= '1';
ps2_data_f <= '1';
elsif clock'event and clock = '1' then
ps2_clk_reg <= ps2_clk & ps2_clk_reg(7 downto 1);
ps2_data_reg <= ps2_data & ps2_data_reg(7 downto 1);
if ps2_clk_reg = X"FF" then
ps2_clk_f <= '1';
elsif ps2_clk_reg = X"00" then
ps2_clk_f <= '0';
end if;
if ps2_data_reg = X"FF" then
ps2_data_f <= '1';
elsif ps2_data_reg = X"00" then
ps2_data_f <= '0';
end if;
end if;
end process;
-- revieves the series data coming from the keyboard,
-- when the data transfer is complete,
-- key_event is set to high for one clock cycle indicating that the data is available
state_machine : process (clock, clear)
begin
if clear = '1' then
state <= start;
bit_counter <= "0000";
ps2_word_reg <= (others => '0');
key_code <= (others => '0');
key_event <= '0';
elsif clock'event and clock = '1' then
key_event <= '0';
case state is
when start =>
if ps2_data_f = '1' then
state <= start;
else
state <= wait_clock_low;
end if;
when wait_clock_low =>
if bit_counter < BIT_COUNTER_MAX then
if ps2_clk_f = '1' then
state <= wait_clock_low;
else
state <= wait_clock_high;
ps2_word_reg <= ps2_data_f & ps2_word_reg(10 downto 1);
end if;
else
state <= get_key_code;
end if;
when wait_clock_high =>
if ps2_clk_f = '0' then
state <= wait_clock_high;
else
state <= wait_clock_low;
bit_counter <= bit_counter + 1;
end if;
when get_key_code =>
key_code <= ps2_word_reg(9 downto 2);
key_event <= '1';
bit_counter <= "0000";
state <= wait_clock_low;
end case;
end if;
end process;
end architecture;