Aktuální adresář: FITkit /
trunk /
fpga /
ctrls /
ps2 /
ps2full_ctrl.vhd
1 -- ps2full_ctrl.vhd: PS/2 Controller
2 -- Copyright (C) 2006 Brno University of Technology,
3 -- Faculty of Information Technology
4 -- Author(s): Zdenek Vasicek <xvasic11 AT stud.fit.vutbr.cz>
5 --
6 -- LICENSE TERMS
7 --
8 -- Redistribution and use in source and binary forms, with or without
9 -- modification, are permitted provided that the following conditions
10 -- are met:
11 -- 1. Redistributions of source code must retain the above copyright
12 -- notice, this list of conditions and the following disclaimer.
13 -- 2. Redistributions in binary form must reproduce the above copyright
14 -- notice, this list of conditions and the following disclaimer in
15 -- the documentation and/or other materials provided with the
16 -- distribution.
17 -- 3. All advertising materials mentioning features or use of this software
18 -- or firmware must display the following acknowledgement:
19 --
20 -- This product includes software developed by the University of
21 -- Technology, Faculty of Information Technology, Brno and its
22 -- contributors.
23 --
24 -- 4. Neither the name of the Company nor the names of its contributors
25 -- may be used to endorse or promote products derived from this
26 -- software without specific prior written permission.
27 --
28 -- This software or firmware is provided ``as is'', and any express or implied
29 -- warranties, including, but not limited to, the implied warranties of
30 -- merchantability and fitness for a particular purpose are disclaimed.
31 -- In no event shall the company or contributors be liable for any
32 -- direct, indirect, incidental, special, exemplary, or consequential
33 -- damages (including, but not limited to, procurement of substitute
34 -- goods or services; loss of use, data, or profits; or business
35 -- interruption) however caused and on any theory of liability, whether
36 -- in contract, strict liability, or tort (including negligence or
37 -- otherwise) arising in any way out of the use of this software, even
38 -- if advised of the possibility of such damage.
39 --
40 -- $Id$
41 --
42 --
43 library IEEE;
44 use IEEE.STD_LOGIC_1164.ALL;
45 use IEEE.STD_LOGIC_ARITH.ALL;
46 use IEEE.STD_LOGIC_UNSIGNED.ALL;
47
48 architecture full of PS2_controller is
49
50 type FSMstate is (SInit, SRcvData, SRcvParity, SRcvStop,
51 SStart0, SStart1, SStart2, SSndData,
52 SSndParity, SSndStop, SRcvAck);
53
54 signal pstate : FSMstate; -- actual state
55 signal nstate : FSMstate; -- next state
56
57 signal ps2clk_reg : std_logic;
58 signal ps2clk_dreg : std_logic;
59 signal ps2data_reg : std_logic;
60 signal di_en : std_logic; --read from PS/2 data
61 signal do_en : std_logic; --write to PS/2 data
62
63 signal cntr_reg : std_logic_vector(8 downto 0);
64 signal cntr_en : std_logic;
65 signal cntr_rst : std_logic;
66 signal cntr_cmp8 : std_logic;
67 signal cntr_cmp511 : std_logic;
68
69 signal data_reg : std_logic_vector(7 downto 0);
70 signal data_en : std_logic;
71
72 signal parity_reg : std_logic;
73 signal parity_en : std_logic;
74 signal parity_rst : std_logic;
75 signal parity_in : std_logic;
76 signal parity_sel : std_logic;
77
78 signal clk_we : std_logic;
79 signal data_sel : std_logic_vector(1 downto 0);
80 signal busy : std_logic;
81
82 begin
83
84 DATA_OUT <= data_reg;
85
86 -- PS/2 interface
87 PS2_CLK <= '0' when clk_we='1' else 'Z' ;
88
89 PS2_DATA <= data_reg(0) when data_sel="00" else
90 parity_reg when data_sel="01" else
91 '0' when data_sel="10" else
92 'Z';
93
94 -- PS/2 CLK edge detector
95 process (RST, CLK)
96 begin
97 if (RST = '1') then
98 ps2clk_reg <= '1';
99 ps2clk_dreg <= '1';
100 ps2data_reg <= '1';
101 elsif (CLK'event) and (CLK = '1') then
102 ps2clk_reg <= PS2_CLK;
103 ps2clk_dreg <= ps2clk_reg;
104 ps2data_reg <= PS2_DATA;
105 end if;
106 end process;
107
108 di_en <= ps2clk_dreg and (not ps2clk_reg); --Falling edge
109 do_en <= (not ps2clk_dreg) and ps2clk_reg; --Rising edge
110
111 -- Bits counter
112 bitscntr: process(RST, CLK)
113 begin
114 if (RST = '1') then
115 cntr_reg <= (others => '0');
116 elsif (CLK'event) and (CLK='1') then
117 if (cntr_rst = '1') then
118 cntr_reg <= (others => '0');
119 elsif (cntr_en='1') then
120 cntr_reg <= cntr_reg + 1;
121 end if;
122 end if;
123 end process;
124
125 -- Comparators
126 cntr_cmp8 <= '1' when (cntr_reg = 16#008#) else '0';
127 cntr_cmp511 <= '1' when (cntr_reg = 16#1ff#) else '0';
128
129 --Data IN/OUT shift register
130 process (RST, CLK)
131 begin
132 if (RST = '1') then
133 --datain_reg <= (others=>'0');
134 elsif (CLK'event) and (CLK = '1') then
135 if (WRITE_EN='1') and (busy='0') then --load
136 data_reg <= DATA_IN;
137 elsif (data_en='1') then
138 data_reg <= ps2data_reg & data_reg(7 downto 1);
139 end if;
140 end if;
141 end process;
142
143 --Data ODD parity calculator
144 process (RST, CLK)
145 begin
146 if (RST = '1') then
147 parity_reg <= '1';
148 elsif (CLK'event) and (CLK = '1') then
149 if (parity_rst = '1') then
150 parity_reg <= '1';
151 elsif (parity_en='1') then
152 parity_reg <= parity_reg xor parity_in;
153 end if;
154 end if;
155 end process;
156
157 parity_in <= ps2data_reg when parity_sel='0' else data_reg(0); --data bit mx
158
159 --FSM present state
160 process (RST, CLK)
161 begin
162 if (RST = '1') then
163 pstate <= sinit;
164 elsif (CLK'event) and (CLK = '1') then
165 pstate <= nstate;
166 end if;
167 end process;
168
169 --FSM next state logic
170 process (pstate, di_en, do_en, ps2data_reg, parity_reg, cntr_cmp8, cntr_cmp511, WRITE_EN)
171 begin
172 nstate <= SInit;
173 cntr_rst <= '0';
174 cntr_en <= '0';
175 parity_rst <= '0';
176 parity_sel <= '0';
177 parity_en <= '0';
178 data_en <= '0';
179 data_sel <= "11";
180 clk_we <= '0';
181 DATA_ERR <= '0';
182 DATA_VLD <= '0';
183 busy <= '1';
184
185 case pstate is
186 when SInit =>
187 busy <= '0';
188 if (di_en='1') and (ps2data_reg='0') then
189 nstate <= SRcvData;
190 cntr_rst <= '1';
191 parity_rst <= '1';
192 end if;
193 if (WRITE_EN='1') then
194 cntr_rst <= '1';
195 nstate <= SStart0;
196 end if;
197
198 --====================================================================
199 --Receiver
200 --====================================================================
201 -- Receive data bits
202 when SRcvData =>
203 if (cntr_cmp8='0') then
204 nstate <= SRcvData;
205 cntr_en <= di_en;
206 data_en <= di_en;
207 parity_en <= di_en;
208 else
209 nstate <= SRcvParity;
210 end if;
211
212 --Receive parity bit
213 when SRcvParity =>
214 if (di_en='1') then
215 nstate <= SRcvStop;
216
217 assert (ps2data_reg=parity_reg) report "PS/2 Data Parity Error" severity note;
218
219 if (ps2data_reg=parity_reg) then
220 DATA_VLD <= '1';
221 else
222 DATA_ERR <= '1';
223 end if;
224 else
225 nstate <= SRcvParity;
226 end if;
227
228 --Receive stop bit
229 when SRcvStop =>
230 if (di_en='0') then
231 nstate <= SRcvStop;
232 end if;
233
234 --====================================================================
235 -- Transmitter
236 --====================================================================
237 when SStart0 =>
238 clk_we <= '1';
239 if (cntr_cmp511='1') then
240 nstate <= SStart1;
241 cntr_rst <= '1';
242 else
243 nstate <= SStart0;
244 cntr_en <= '1';
245 end if;
246
247 --Init data transfer
248 when SStart1 =>
249 clk_we <= '1';
250 data_sel <= "10";
251 if (cntr_cmp511='1') then
252 nstate <= SStart2;
253 else
254 nstate <= SStart1;
255 cntr_en <= '1';
256 end if;
257
258 --Release CLK
259 when SStart2 =>
260 data_sel <= "10";
261 if (di_en='1') then
262 nstate <= SSndData;
263 cntr_rst <= '1';
264 parity_rst <= '1';
265 else
266 nstate <= SStart2;
267 end if;
268
269 --Transmit data bits
270 when SSndData =>
271 data_sel <= "00";
272 if (cntr_cmp8='0') then
273 nstate <= SSndData;
274 parity_sel <= '1';
275 parity_en <= di_en;
276 data_en <= di_en;
277 cntr_en <= di_en;
278 else
279 nstate <= SSndParity;
280 end if;
281
282 --Transmit parity bit
283 when SSndParity =>
284 data_sel <= "01";
285 if (di_en='1') then
286 nstate <= SSndStop;
287 else
288 nstate <= SSndParity;
289 end if;
290
291 --Transmit stop bit
292 when SSndStop =>
293 data_sel <= "11";
294 if (di_en='1') then
295 nstate <= SRcvAck;
296 else
297 nstate <= SSndStop;
298 end if;
299
300 --Receive acknowledge
301 when SRcvAck =>
302 if (do_en='1') then
303
304 assert (ps2data_reg='0') report "PS/2 ACK Error" severity note;
305
306 if (ps2data_reg='1') then
307 DATA_ERR <= '1';
308 end if;
309 else
310 nstate <= SRcvAck;
311 end if;
312
313 when others =>
314 null;
315 end case;
316 end process;
317 end full;
318
319