|
CPLD MAXII 1270 PS/2 Keyboard 程式問題
7 p- C1 K# }. U+ S2 x( [我在網路上收尋到FPGA 收 PS/2 Keyboard程式,將程式套用在CPLD上,Compiler後,無問題,依照程式將Pin腳定義,提供系統CLK,Reset,和PS/2 CLK,PS/2 Data,將DoRead和Scan_DAV(偵測PS/2是否送出信號)相接,Scan_Err接一顆LED(險示Overflow錯誤),Scan_Code接8顆LED(顯示PS/2 8bit Data),但燒錄後,CPLD啟動後,按鍵按下,毫無反應,並且PS/2 CLOCK信號已被降至低準位,似乎鍵盤已被抑制送出信號,請高手們幫忙提供意見好嗎?感謝......* N9 g) ]% A/ l2 h* D
程式:
+ ^5 F% W7 ~! M' n) Y4 Z! w2 T-- PS2_Ctrl.vhd
* G( z$ F! A- R- V# @ f; Z8 [' Q9 N-- ------------------------------------------------1 \8 C9 G- z8 r: M' _, Z
-- Simplified PS/2 Controller (kbd, mouse...)
$ a- L7 k" v2 v* y-- ------------------------------------------------; X$ z5 X7 `# v7 {; W. T3 N
-- Only the Receive function is implemented !/ Q, f/ u |9 V1 @/ i
-- (c) ALSE. http://www.alse-fr.com
5 `. u5 J2 j+ U/ y1 z& elibrary IEEE;: _6 C) E. q% Z5 M
use IEEE.STD_LOGIC_1164.all;8 L* s6 S: C- L5 o' w
use IEEE.Numeric_std.all;. T9 J8 ^! H! M$ E+ f( j. o
-- --------------------------------------
( I7 y3 U& ~ Z& c* NEntity PS2_Ctrl is
+ R8 [( C5 E6 F9 @2 N7 E. e-- --------------------------------------
Q" t2 }0 V' V- S6 W$ Egeneric (FilterSize : positive := 8);
( R3 T9 P+ `! B0 k0 U$ a( N; @port( Clk : in std_logic; -- System Clock2 O: y7 `' \8 R' E
Reset : in std_logic; -- System Reset$ k2 U4 M& P1 }& l; N
PS2_Clk : in std_logic; -- Keyboard Clock Line
, X2 R, b6 Y/ ?+ ^PS2_Data : in std_logic; -- Keyboard Data Line
- Q8 A$ Z3 }( s" L! fDoRead : in std_logic; -- From outside when reading the scan code
9 |) Q2 S3 A: w! r% j1 D" w% b; TScan_Err : out std_logic; -- To outside : Parity or Overflow error3 b$ H7 j! m5 T9 n! ?) \8 a
Scan_DAV : out std_logic; -- To outside when a scan code has arrived
' ?) n) u/ Y& m- o" pScan_Code : out std_logic_vector(7 downto 0) -- Eight bits Data Out
( ~8 u' G f: y7 l! t);
4 s {8 R. K. tend PS2_Ctrl;
9 B8 X. I% t4 ~( ^! B% n-- --------------------------------------3 Q; e! Q9 x6 d' ~9 r% t3 F
Architecture ALSE_RTL of PS2_Ctrl is
2 t# t0 m; @, o9 x! D-- --------------------------------------
8 i( [4 P( ?5 e3 a' l; ^1 S$ u6 H-- (c) ALSE. http://www.alse-fr.com
! Z, c0 A3 G: d; c! ^* Q! H9 @# l-- Author : Bert Cuzeau." I& h( b0 g& P4 x3 j
-- Fully synchronous solution, same Filter on PS2_Clk.
$ M1 Y& G. h' a1 {-- Still as compact as "Plain_wrong"...
6 V( U- d! G1 A7 M% l! W-- Possible improvement : add TIMEOUT on PS2_Clk while shifting, X: h o9 W: z& @4 x0 n8 H
-- Note: PS2_Data is resynchronized though this should not be
1 Q+ J1 O4 n8 N4 s; x* [-- necessary (qualified by Fall_Clk and does not change at that time).( d" Y; P3 m( D5 _
-- Note the tricks to correctly interpret 'H' as '1' in RTL simulation.
$ l: ^( o- n; t6 esignal PS2_Datr : std_logic;* f" J, {1 x8 y0 m; z
subtype Filter_t is std_logic_vector(FilterSize-1 downto 0);
$ |2 }0 T) ?' wsignal Filter : Filter_t;
" v. F( U: K; ~) p1 z3 asignal Fall_Clk : std_logic;
b/ d( ] C0 _1 }$ l2 B0 g9 Xsignal Bit_Cnt : unsigned (3 downto 0);$ n3 k7 }( Y* _4 [, L
signal Parity : std_logic;! K, X% |6 O7 _, x( m" I
signal Scan_DAVi : std_logic;- h$ I x; o7 K
signal S_Reg : std_logic_vector(8 downto 0);
, }* L/ S- x' C' {" jsignal PS2_Clk_f : std_logic;! t6 ^$ \6 b4 J! G( f ?
Type State_t is (Idle, Shifting);( {* n- K# q/ R7 S2 i5 b6 |6 z
signal State : State_t;4 `5 ]4 i2 D. ^
begin
- q" I3 [' P" v! a. S6 G, mScan_DAV <= Scan_DAVi;
2 ]6 @% i @6 d4 d% M-- This filters digitally the raw clock signal coming from the keyboard :4 N4 L$ \+ a& b$ P8 i- t7 I" e- F& o
-- * Eight consecutive PS2_Clk=1 makes the filtered_clock go high
/ u. }, u) ]$ g, ^ r3 a-- * Eight consecutive PS2_Clk=0 makes the filtered_clock go low' h' F4 A2 a# L2 L: r; R- j% y$ `, E
-- Implies a (FilterSize+1) x Tsys_clock delay on Fall_Clk wrt Data" O- T6 _/ `5 H- D" Q
-- Also in charge of the re-synchronization of PS2_Data
, J4 f$ m/ D3 x! t) U0 l% D7 c! Pprocess (Clk,Reset)5 G4 q8 s1 S& |# G8 }
begin
* O. A! n2 Y, F3 O/ w9 aif Reset='1' then* ~! Q( R! a4 U# T5 R) q
PS2_Datr <= '0';* T) Z: `4 T6 m' S% u
PS2_Clk_f <= '0';
, j) G0 f$ Q* C1 OFilter <= (others=>'0');% h+ `( S2 R: r2 N% s0 c
Fall_Clk <= '0';
* q* \4 e+ D1 O% J, t& W0 v$ d5 Velsif rising_edge (Clk) then# Y) b5 X; V* Y. U9 K* H! Y. B
PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'" F% s9 i+ i0 W# X
Fall_Clk <= '0';
3 B9 D, o8 k( {7 @4 fFilter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);
1 q$ {2 i/ B3 Y8 \/ z! P& M; y" @3 Uif Filter = Filter_t'(others=>'1') then
! `9 f5 Q& r4 J) c1 a6 MPS2_Clk_f <= '1';7 o9 Y9 p: h: s3 S% T1 P
elsif Filter = Filter_t'(others=>'0') then' U7 `/ d% v/ H# U% J
PS2_Clk_f <= '0';
6 d6 l' a7 _; P3 yif PS2_Clk_f = '1' then: R% y$ D4 s% |. l
Fall_Clk <= '1';9 ^8 k, k7 k, l5 ?
end if;$ X ^# q" A8 O+ p! f# a+ s
end if; q* z) b- }% ~9 I6 z$ I
end if;
+ B1 H/ o- i/ bend process;) A; y( C; O# _9 }* B" @, U
-- This simple State Machine reads in the Serial Data
: e" e) ]% g. d/ X' \$ n- f-- coming from the PS/2 peripheral./ x3 P4 d' L) w0 w: d- d' A# W, K {
process(Clk,Reset)' J! U; l( i, P; B
begin
3 [* R- M0 p1 W* t# u( C1 S; hif Reset='1' then8 M: {) `: U% C; ^* c, q
State <= Idle;
2 O3 g, d& h$ FBit_Cnt <= (others => '0');; ]* E" Q3 J# x( w3 B
S_Reg <= (others => '0');6 R% w& H+ K* p, x% ?
Scan_Code <= (others => '0');
/ z2 r6 }% M# d$ i+ n( e6 E3 AParity <= '0';3 m/ e3 u* {% U- ?
Scan_Davi <= '0';: P2 L; {# U. n9 d( j' L4 V
Scan_Err <= '0';% W% R3 f: E, o1 e6 D c' J/ G; m* U
elsif rising_edge (Clk) then) n S- j3 r! U( x
if DoRead='1' then
4 |! `; E1 ~: lScan_Davi <= '0'; -- note: this assgnmnt can be overriden) @: Z0 W6 \0 Z- V$ p/ e
end if;
+ ^& r& H3 v# u- |% Y a* Qcase State is
- Y7 I: k: G \; h+ rwhen Idle =>. \8 _+ x/ ~1 G! P" [
Parity <= '0';
- U1 I2 f- n* D: k. u% Q; |$ JBit_Cnt <= (others => '0');
7 `$ a* `5 d" t M* U" g2 ?-- note that we dont need to clear the Shift Register0 p( |' j% _* L& C" Q' K' E$ T8 s
if Fall_Clk='1' and PS2_Datr='0' then -- Start bit, |5 e$ a8 b0 H! }3 V) q2 X
Scan_Err <= '0';. ]: }' y2 I; ^' G) n5 P
State <= Shifting;
6 f6 P. \- `% Q2 f* oend if;. X5 z0 }* O. l- e
when Shifting =>7 m' Y7 R) Q; }( K U
if Bit_Cnt >= 9 then
3 b; d/ u% o+ Sif Fall_Clk='1' then -- Stop Bit
( Y4 {" ?' P P6 k2 g-- Error is (wrong Parity) or (Stop='0') or Overflow
9 ]$ S3 H1 ^2 T: V' sScan_Err <= (not Parity) or (not PS2_Datr) or Scan_DAVi;3 |, p. `$ O; s, O+ s" P
Scan_Davi <= '1';. Q/ r( q% t3 s2 M ?. S7 r5 {
Scan_Code <= S_Reg(7 downto 0);
( k# }* U. b3 h8 M6 FState <= Idle;
+ E( P" H5 |3 Pend if;
0 V2 Q) w- o) m1 celsif Fall_Clk='1' then
) @1 c5 G, Z) s4 Q a/ I7 V UBit_Cnt <= Bit_Cnt + 1;) ~) r( ?8 \* |) R
S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
* a7 b, |; m5 ~0 X% T. M0 HParity <= Parity xor PS2_Datr;; ^$ x) T( k. n
end if;# B: _6 w/ \7 ?2 |% }1 v `
when others => -- never reached
" I. n r1 e+ w1 J) o, B3 W! d" AState <= Idle;
0 Z ^' x& B5 k2 Hend case;
* W) m3 g9 D7 U+ f6 ^( hend if;
, _7 q$ Z6 U. B- n8 eend process;% h& ]0 ~- N! p! g
end ALSE_RTL; |
|