Rev Author Line No. Line
2528 kakl 1 ----------------------------------------------------------------------------------
2 -- Company: www.mlab.cz
3 -- Engineer: miho
4 --
5 -- Create Date: 19:31:10 02/20/2011
6 -- Design Name: S3AN01A Test Design
7 -- Module Name: PS2
8 -- Project Name: S3AN01A Test Design
9 -- Target Devices: XILINX FPGA (Spartan3A/3AN)
10 -- Tool versions: ISE 12.4 / 13.1 / 13.3
11 -- Description: Test design for PCB verification
12 --
13 -- Dependencies: None
14 --
15 -- Revision: 0.01 File Created
16 --
17 ----------------------------------------------------------------------------------
18 --
19 -- PS/2 Keyboard Driver
20 -- ====================
21 --
22 -- PS2_Code
23 -- --------
24 --
25 -- Standard PS/2 Scan Code
26 --
27 --
28 -- PS2_Attribs
29 -- -----------
30 --
31 -- Bit 0 - Shift
32 -- Bit 1 - Ctrl
33 -- Bit 2 - Alt
34 -- Bit 3 - Ext0 (arrows, ...)
35 -- Bit 4 - Ext1
36 -- Bit 5 - Shift Num (arrows with NumLock)
37 -- Bit 6
38 -- Bit 7 - Break (key release)
39 --
40 --
41 -- PS2_Shifts
42 -- ----------
43 --
44 -- Bit 0 - Shift Left
45 -- Bit 1 - Shift Right
46 -- Bit 2 - Ctrl Left
47 -- Bit 3 - Ctrl Right
48 -- Bit 4 - Alt Left
49 -- Bit 5 - Alt Right
50 -- Bit 6 - Num Lock
51 -- Bit 7 - Caps Lock
52 -- Bit 8 - Scroll Lock
53 -- Bit 9 - Shift Num (virtual state) - Not to be used
54 --
55 ----------------------------------------------------------------------------------
56  
57  
58 library IEEE;
59 use IEEE.STD_LOGIC_1164.ALL;
60 use IEEE.NUMERIC_STD.ALL;
61  
62 entity PS2 is
63 generic (
64 -- Top Value for 100MHz Clock Counter
65 CLKFREQ: integer -- Frequency in Hz (minimum cca 50_000)
66 );
67 port (
68 -- Main Clock
69 Clk: in std_logic;
70  
71 -- PS/2 Port
72 PS2_Clk: inout std_logic;
73 PS2_Data: inout std_logic;
74  
75 -- Result - valid when PS2_Valid
76 PS2_Valid: out boolean; -- Valid Data (synchronous with Clk)
77 PS2_Code: out std_logic_vector(7 downto 0); -- Key Scan Code
78 PS2_Attribs: out std_logic_vector(7 downto 0); -- State of Shifts for Scan Code
79  
80 -- Immediate State of Shifts
81 PS2_Shifts: out std_logic_vector(9 downto 0) -- Immediate (live) State of Shift/Alt/Ctrl etc.
82 );
83 end entity PS2;
84  
85  
86 library IEEE;
87 use IEEE.STD_LOGIC_1164.ALL;
88 package PS2_pkg is
89 component PS2
90 generic (
91 -- Top Value for 100MHz Clock Counter
92 CLKFREQ: integer -- Frequency in Hz (minimum cca 50_000)
93 );
94 port (
95 -- Main Clock
96 Clk: in std_logic;
97  
98 -- PS/2 Port
99 PS2_Clk: inout std_logic;
100 PS2_Data: inout std_logic;
101  
102 -- Result - valid when PS2_Valid
103 PS2_Valid: out boolean; -- Valid Data (synchronous with Main Clock)
104 PS2_Code: out std_logic_vector(7 downto 0); -- Key Scan Code
105 PS2_Attribs: out std_logic_vector(7 downto 0); -- State of Shifts for Scan Code
106  
107 -- Immediate State of Shifts
108 PS2_Shifts: out std_logic_vector(9 downto 0) -- Immediate (live) State of Shift/Alt/Ctrl etc.
109 );
110 end component PS2;
111 end package;
112  
113  
114 architecture PS2_a of PS2 is
115  
116 function to_std_logic(State: boolean) return std_logic is
117 begin
118 if State then
119 return '1';
120 else
121 return '0';
122 end if;
123 end function to_std_logic;
124  
125 -- Sampled PS/2 Clock and Data
126 signal PS2_Clk_d: std_logic := '0'; -- For sync with systerm clock
127 signal PS2_Clk_dd: std_logic := '0'; -- For falling edge detection
128 signal PS2_Data_d: std_logic := '0'; -- For sync with systerm clock
129  
130 -- Level 0 - Read Byte from PS/2 Interface
131 type ReadByte_t is ( -- Read Byte FSM State Type
132 Idle, -- Inactive State
133 D0, D1, D2, D3, D4, D5, D6, D7, -- Receiving Bits
134 Parity, -- Receiving Parity
135 Final -- Receiving Stop Bit and Sending ReadByte_rdy
136 );
137 signal ReadByteState: ReadByte_t := Idle; -- Read Byte FSM State
138 signal ReadByte: std_logic_vector(7 downto 0) := (others => '0'); -- Read Byte (Raw Scan Code Byte)
139 signal ReadByte_rdy: boolean := false; -- Read Byte Ready (synchronous with Clk)
140  
141 -- Level 1 - Process Raw Scan Codes E0,F1 and F0 - valid only when Level1_rdy
142 signal FlagE0: boolean := false; -- E0 - Ext0 Key
143 signal FlagE1: boolean := false; -- E1 - Ext1 Key
144 signal FlagF0: boolean := false; -- F0 - Break (release) Key
145 signal Level1_rdy: boolean := false; -- Send Data and Flags to the next level
146  
147 -- Level 2 - Process Raw Scan Codes and Shift-Like Atributes E0, E1 and F0 - valid only when Level2_rdy
148 signal FlagBreak: boolean := false; -- F0 - Break (depress) Key
149 signal FlagAltR: boolean := false; -- E0 11 - State of Right Alt Key
150 signal FlagAltL: boolean := false; -- 11 - State of Left Alt Key
151 signal FlagShiftNum: boolean := false; -- E0 12 - State of Ext Left Shift (pseudo key)
152 signal FlagShiftL: boolean := false; -- 12
153 signal FlagShiftR: boolean := false; -- 59
154 signal FlagCtrlR: boolean := false; -- E0 14
155 signal FlagCtrlL: boolean := false; -- 14
156 signal FlagExt0: boolean := false; -- E0 Keys (extended keys)
157 signal FlagExt1: boolean := false; -- E1 Keys (extended keys - Prt_Scr and Pause_Brk)
158 signal FlagNumLock: boolean := false; -- 77 Num Lock State
159 signal FlagScrollLock: boolean := false; -- 7E Scroll Lock State
160 signal FlagCapsLock: boolean := false; -- 58 Caps Lock State
161 signal Level2_rdy: boolean := false; -- Send Data and Flags to the next level
162 signal Level2a_rdy: boolean := false; -- Send Read Ack for Write Byte
163  
164 -- Write Byte
165 type WriteByteState_t is ( -- Write Byte FSM State Type
166 Idle, -- Idle State
167 WriteStart, -- Start (pull PS2_Clk down)
168 WaitStart, -- Wait
169 SendBits, -- Send Data Bits
170 WriteParity, -- Send Parity
171 WriteStop, -- Send Stop Bit
172 AckBit, -- Wait for Ack Bit from Keyboard
173 Final, -- Wait for Idle on PS2_Clk and PS2_Data
174 WaitAckByte -- Wait for Ack Byte from Keyboard
175 );
176 signal WriteByteState: WriteByteState_t := Idle; -- Write Byte FSM State
177 signal WriteCode: std_logic_vector(7 downto 0) := (others =>'0'); -- What to Write
178 signal WriteByte: boolean := false; -- Init Write Byte Sequence
179 signal SendingData: boolean := false; -- Block Receiver when Sending Data
180 signal WriteByte_ack: boolean := false; -- Ack Writen Byte
181  
182 signal WriteReg: std_logic_vector(7 downto 0) := (others =>'0'); -- Transmit Shift Register
183 signal ParityBit: std_logic := '0'; -- Parity Bit
184 signal StartTime: unsigned(31 downto 0) := (others =>'0'); -- Timer for Start of Write (PS2_Clk low)
185 signal WriteBits: unsigned(3 downto 0) := (others =>'0'); -- Bit Counter
186  
187 -- Update LED Indicators
188 type UpdState_t is ( -- Update Led Indicators FSM State Type
189 Idle, -- Inactive State
190 SendReset, -- For Debug - Reset Keyboard
191 SendLed1, -- Send FD
192 SendLed2, -- Send New LED State
193 SendFinal --
194 );
195 signal UpdState: UpdState_t := Idle; -- Update Led Indicators FSM State
196 signal UpdateLed: boolean := false; -- Send new LED State to the Keyboard
197 signal UpdateLed_ack: boolean := false; -- Ack (1 clock pulse)
198  
199 begin
200  
201 -- Sync External Signals with Clock
202 process (Clk)
203 begin
204 if rising_edge(Clk) then
205 -- Sync
206 PS2_Clk_d <= PS2_Clk;
207 PS2_Data_d <= PS2_Data;
208 -- For Falling Edge Detection
209 PS2_Clk_dd <= PS2_Clk_d;
210 end if;
211 end process;
212  
213 -- Level 0 - Read Byte from PS/2 Interface
214 process (Clk)
215 begin
216 if rising_edge(Clk) then
217 ReadByte_rdy <= false;
218 if PS2_Clk_dd='1' and PS2_Clk_d='0' and not SendingData then
219 -- Falling Edge of PS2_Clk
220 case ReadByteState is
221 when Idle =>
222 -- Test Start Bit
223 if PS2_Data='0' then
224 ReadByteState <= D0;
225 end if;
226 when D0 =>
227 -- Bit 0
228 ReadByte <= PS2_Data & ReadByte(7 downto 1);
229 ReadByteState <= D1;
230 when D1 =>
231 -- Bit 1
232 ReadByte <= PS2_Data & ReadByte(7 downto 1);
233 ReadByteState <= D2;
234 when D2 =>
235 -- Bit 2
236 ReadByte <= PS2_Data & ReadByte(7 downto 1);
237 ReadByteState <= D3;
238 when D3 =>
239 -- Bit 3
240 ReadByte <= PS2_Data & ReadByte(7 downto 1);
241 ReadByteState <= D4;
242 when D4 =>
243 -- Bit 4
244 ReadByte <= PS2_Data & ReadByte(7 downto 1);
245 ReadByteState <= D5;
246 when D5 =>
247 -- Bit 5
248 ReadByte <= PS2_Data & ReadByte(7 downto 1);
249 ReadByteState <= D6;
250 when D6 =>
251 -- Bit 6
252 ReadByte <= PS2_Data & ReadByte(7 downto 1);
253 ReadByteState <= D7;
254 when D7 =>
255 -- Bit 7
256 ReadByte <= PS2_Data & ReadByte(7 downto 1);
257 ReadByteState <= Parity;
258 when Parity =>
259 -- Check Parity Here...
260 ReadByteState <= Final;
261 when Final =>
262 -- End of Byte
263 ReadByteState <= Idle;
264 ReadByte_rdy <= true; -- Scan Code Ready (8 bit word)
265 end case;
266 end if;
267 end if;
268 end process;
269  
270 -- Level 1 - Process Raw Scan Codes and ESC Atributes E0, E1 and F0
271 process (Clk)
272 begin
273 if rising_edge(Clk) then
274 if Level1_rdy then
275 -- Clean State when Sent Data from Level1 processing
276 Level1_rdy <= false;
277 FlagE0 <= false;
278 FlagE1 <= false;
279 FlagF0 <= false;
280 else
281 if ReadByte_rdy then
282 -- Process Scan Code Byte from Level 0
283 if ReadByte=X"E0" then
284 -- Ext Code
285 FlagE0 <= true;
286 elsif ReadByte=X"E1" then
287 -- Special Ext Code
288 FlagE1 <= true;
289 elsif ReadByte=X"F0" then
290 -- Break Flag
291 FlagF0 <= true;
292 else
293 -- Scan Code
294 Level1_rdy <= true;
295 end if;
296 end if;
297 end if;
298 end if;
299 end process;
300  
301 -- Level 2 - Process Shift (left and right shift, alt and ctrl) and Num Lock (numeric virtual shift)
302 process (Clk)
303 begin
304 if rising_edge(Clk) then
305 -- Clear Comands to Higher Level
306 UpdateLed <= false;
307 Level2a_rdy <= false;
308 Level2_rdy <= false;
309 -- Process Read Byte
310 if Level1_rdy then
311 if ReadByte=X"11" then
312 -- Alt Key
313 if FlagE0 then
314 FlagAltR <= not FlagF0;
315 else
316 FlagAltL <= not FlagF0;
317 end if;
318 elsif ReadByte=X"12" then
319 -- Left Shift
320 if FlagE0 then
321 FlagShiftNum <= not FlagF0;
322 else
323 FlagShiftL <= not FlagF0;
324 end if;
325 elsif ReadByte=X"59" then
326 -- Right Shift
327 FlagShiftR <= not FlagF0;
328 elsif ReadByte=X"14" then
329 -- Ctrl
330 if FlagE0 then
331 FlagCtrlR <= not FlagF0;
332 else
333 FlagCtrlL <= not FlagF0;
334 end if;
335 elsif ReadByte=X"77" and not FlagCtrlL and not FlagCtrlR and not FlagAltL and not FlagAltR then
336 -- Num Lock On/Off
337 if not FlagF0 then
338 FlagNumLock <= not FlagNumLock;
339 UpdateLed <= true; -- Set UpdateLed Request
340 end if;
341 elsif ReadByte=X"58" then
342 -- Caps Lock
343 if not FlagF0 then
344 FlagCapsLock <= not FlagCapsLock;
345 UpdateLed <= true; -- Set UpdateLed Request
346 end if;
347 elsif ReadByte=X"7E" then
348 if not FlagF0 then
349 FlagScrollLock <= not FlagScrollLock;
350 UpdateLed <= true; -- Set UpdateLed Request
351 end if;
352 else
353 -- Send Data to the next Level
354 FlagExt0 <= FlagE0;
355 FlagExt1 <= FlagE1;
356 FlagBreak <= FlagF0;
357 if WriteByteState=WaitAckByte then
358 -- Send Data (Ack Byte) to WriteByte
359 Level2a_rdy <= true;
360 else
361 -- Send Scan Code to the next Level
362 Level2_rdy <= true;
363 end if;
364 end if;
365 end if;
366 end if;
367 end process;
368  
369 -- Send Data
370 PS2_Valid <= Level2_rdy;
371  
372 -- Scan COde
373 PS2_Code(7 downto 0) <= ReadByte;
374  
375 -- Attribs
376 PS2_Attribs(0) <= '1' when FlagShiftL or FlagShiftR else '0'; -- Bit 0 - Shift
377 PS2_Attribs(1) <= '1' when FlagCtrlL or FlagCtrlR else '0'; -- Bit 1 - Ctrl
378 PS2_Attribs(2) <= '1' when FlagAltL or FlagAltR else '0'; -- Bit 2 - Alt
379 PS2_Attribs(3) <= '1' when FlagExt0 else '0'; -- Bit 3 - Ext Code E0
380 PS2_Attribs(4) <= '1' when FlagExt1 else '0'; -- Bit 4 - Ext Code E1
381 PS2_Attribs(5) <= '1' when FlagShiftNum else '0'; -- Bit 5 - Shift Num (Arrows,...) - only if NumLock Led is Off
382 PS2_Attribs(6) <= '0';
383 PS2_Attribs(7) <= '1' when FlagBreak else '0'; -- Bit 7 - Break (release) Key
384  
385 -- Immediate State of Shift Like Keys
386 PS2_Shifts(0) <= '1' when FlagShiftL else '0'; -- Bit 0 - Shift Left
387 PS2_Shifts(1) <= '1' when FlagShiftR else '0'; -- Bit 1 - Shift Right
388 PS2_Shifts(2) <= '1' when FlagCtrlL else '0'; -- Bit 2 - Ctrl Left
389 PS2_Shifts(3) <= '1' when FlagCtrlR else '0'; -- Bit 3 - Ctrl Right
390 PS2_Shifts(4) <= '1' when FlagAltL else '0'; -- Bit 4 - Alt Left
391 PS2_Shifts(5) <= '1' when FlagAltR else '0'; -- Bit 5 - Alt Right
392 PS2_Shifts(6) <= '1' when FlagNumLock else '0'; -- Bit 7 - Num Lock
393 PS2_Shifts(7) <= '1' when FlagCapsLock else '0'; -- Bit 8 - Caps Lock
394 PS2_Shifts(8) <= '1' when FlagScrollLock else '0'; -- Bit 9 - Scroll Lock
395 PS2_Shifts(9) <= '1' when FlagShiftNum else '0'; -- Bit 6 - Shift Num (virtual state) - Not to be used
396  
397 -- Write Byte to PS/2 Interface
398 -- Init By: WriteByte
399 -- Finish Indication: WriteByte_ack
400 process (Clk)
401 begin
402 if rising_edge(Clk) then
403 WriteByte_ack <= false;
404 case WriteByteState is
405 when Idle =>
406 PS2_Clk <= 'Z';
407 PS2_Data <= 'Z';
408 if WriteByte then
409 WriteByteState <= WriteStart;
410 WriteReg <= WriteCode;
411 end if;
412 when WriteStart =>
413 if PS2_Data_d='1' and PS2_Clk_d='1' then
414 -- PS2 Interface in Idle State
415 PS2_Clk <= '0'; -- Start of Write (PS2_Clk=L)
416 StartTime <= to_unsigned(CLKFREQ/16000, StartTime'length); -- cca 60us Start
417 WriteBits <= to_unsigned(7, WriteBits'length); -- 8 bits
418 WriteByteState <= WaitStart;
419 SendingData <= true;
420 end if;
421 when WaitStart =>
422 if StartTime>0 then
423 StartTime <= StartTime - 1;
424 else
425 PS2_Data <= '0'; -- Start Bit
426 PS2_Clk <= 'Z'; -- Release Clk
427 ParityBit <= '1'; -- Init Parity Generator (code 1111_1111 has parity 1)
428 WriteByteState <= SendBits;
429 end if;
430 when SendBits =>
431 if PS2_Clk_dd='1' and PS2_Clk_d='0' then
432 PS2_Data <= WriteReg(0);
433 ParityBit <= ParityBit xor WriteReg(0);
434 WriteReg <= '1' & WriteReg(7 downto 1);
435 if WriteBits>0 then
436 WriteBits <= WriteBits - 1;
437 else
438 WriteByteState <= WriteParity;
439 end if;
440 end if;
441 when WriteParity =>
442 if PS2_Clk_dd='1' and PS2_Clk_d='0' then
443 PS2_Data <= ParityBit;
444 WriteByteState <= WriteStop;
445 end if;
446 when WriteStop =>
447 if PS2_Clk_dd='1' and PS2_Clk_d='0' then
448 PS2_Data <= '1';
449 WriteByteState <= AckBit;
450 end if;
451 when AckBit =>
452 PS2_Data <= 'Z';
453 if PS2_Clk_dd='1' and PS2_Clk_d='0' then
454 WriteByteState <= Final;
455 end if;
456 when Final =>
457 if PS2_Clk_d='1' then
458 WriteByteState <= WaitAckByte;
459 SendingData <= false;
460 end if;
461 when WaitAckByte =>
462 if Level2a_rdy then
463 WriteByteState <= Idle;
464 WriteByte_ack <= true;
465 end if;
466 end case;
467 end if;
468 end process;
469  
470 -- Level 3 - Update LED Indicators
471 -- Init By: UpdateLed or Level2_rdy(with scan code and attrib)
472 -- Finish Indication: UpdateLed_ack (not used)
473 process (Clk)
474 begin
475 if rising_edge(Clk) then
476 UpdateLed_ack <= false; -- 1 Clock Pulse
477 WriteByte <= false;
478 case UpdState is
479 when Idle =>
480 -- Register the request
481 if Level2_rdy and ReadByte=X"07" and not FlagBreak then
482 WriteCode <= X"FF";
483 WriteByte <= true;
484 elsif UpdateLed then
485 UpdateLed_ack <= true;
486 UpdState <= SendLed1;
487 end if;
488 when SendReset =>
489 if WriteByteState=Idle then
490 -- Send Keyborad Reset
491 WriteCode <= X"FF";
492 WriteByte <= true;
493 UpdState <= SendFinal;
494 end if;
495 when SendLed1 =>
496 if WriteByteState=Idle then
497 -- Send LED Command
498 WriteCode <= X"ED";
499 WriteByte <= true;
500 UpdState <= SendLed2;
501 end if;
502 when SendLed2 =>
503 if WriteByte_ack then
504 -- Send LED State
505 WriteCode <= "00000" & to_std_logic(FlagCapsLock)
506 & to_std_logic(FlagNumLock)
507 & to_std_logic(FlagScrollLock);
508 WriteByte <= true;
509 UpdState <= SendFinal;
510 end if;
511 when SendFinal =>
512 if WriteByte_ack then ---WriteByteState=Idle then
513 -- Last Data has been Send
514 UpdState <= Idle;
515 end if;
516 end case;
517 end if;
518 end process;
519  
520 end architecture PS2_a;