|
目前需要使用MAXII 1270 做PS/2 Keyboard控制,在網路上找到了用VHDL寫PS/2介面,經過測試後正常,但輸出是8個Pin輸出(並聯),但我希望輸出為1個Pin(串聯)輸出,請問我該如果修改程式呢?請大家幫幫忙,給個意見,或者提供任何資料參考...thx
5 T( S, \( m+ L( ?8 Q5 E
* ^* C+ u! y- E7 k程式如下:- ?* t& U/ x" W. s1 Z
-- PS2_Ctrl.vhd* V. y. N, b" ?+ g, e% F
-- ------------------------------------------------ p6 b2 A" B& N+ n6 N+ I8 B% U8 C
-- Simplified PS/2 Controller (kbd, mouse...)
5 q1 D, G; B0 j" Q" C( K* I# x6 t1 u-- ------------------------------------------------
* h/ s. ]9 C8 ^+ g+ h# w-- Only the Receive function is implemented !% c! f3 Y" p5 t
-- (c) ALSE. http://www.alse-fr.com
% S" i' I/ O% S K8 M2 ~library IEEE;4 o; m5 f0 `5 o7 P
use IEEE.STD_LOGIC_1164.all;
( a) j) g# N( W Z7 l- ^0 o" [5 tuse IEEE.Numeric_std.all;4 L" `/ k: N2 `$ V* W8 z
-- --------------------------------------
1 h3 D; X! e3 s, p# b8 VEntity PS2_Ctrl is
+ g$ y, d. ~) R F' B* `-- --------------------------------------- _% v0 i7 n& u* _0 T# O
generic (FilterSize : positive := 8);
& u) f' v S( @ u' c- _port( Clk : in std_logic; -- System Clock. d( |& O& ^$ z e) j, B- {9 K- {
Reset : in std_logic; -- System Reset6 T! a5 ]& t* U# J8 t
PS2_Clk : in std_logic; -- Keyboard Clock Line
" G% l$ R3 O7 f2 G" n( l% IPS2_Data : in std_logic; -- Keyboard Data Line
8 m: x: i, e' dDoRead : in std_logic; -- From outside when reading the scan code/ v# N' s. b8 w7 v
Scan_Err : out std_logic; -- To outside : Parity or Overflow error
; P% V& J8 g, h. CScan_DAV : out std_logic; -- To outside when a scan code has arrived
/ `9 |4 u0 b; K7 A! {* |" kScan_Code : out std_logic_vector(7 downto 0) -- Eight bits Data Out
/ W* L# Z; L4 x' ]);
, G: I6 d I {( f( eend PS2_Ctrl;
8 x% P2 i- w/ @7 R$ {-- --------------------------------------' J, T9 G1 Q6 q) ?! J1 X# f
Architecture ALSE_RTL of PS2_Ctrl is$ t2 T8 D# V( H# n- m5 E
-- --------------------------------------1 A6 V( m$ d8 A( y2 x2 {
-- (c) ALSE. http://www.alse-fr.com
+ h- {& @1 o9 N-- Author : Bert Cuzeau.
# K ~! ~/ n( W% H-- Fully synchronous solution, same Filter on PS2_Clk.
/ b# u4 O0 y7 w-- Still as compact as "Plain_wrong"...
* b, F- S% _2 H) |) m( u-- Possible improvement : add TIMEOUT on PS2_Clk while shifting
0 A5 X: [. j. z( E" ]-- Note: PS2_Data is resynchronized though this should not be
( U n* V: b+ @+ I0 F; E) t-- necessary (qualified by Fall_Clk and does not change at that time).
( M; b6 t% ]! L- G5 V/ z) d# c; h-- Note the tricks to correctly interpret 'H' as '1' in RTL simulation.
4 S# \( I: H6 P/ A9 S5 jsignal PS2_Datr : std_logic;
' b4 k' \1 X% ^! _: x9 O; F; T, osubtype Filter_t is std_logic_vector(FilterSize-1 downto 0);- ~9 Q3 R8 V- t+ V0 X
signal Filter : Filter_t;
. f% ~2 Q3 w3 }! S, z* G( Rsignal Fall_Clk : std_logic;
. B, ]5 l; h+ E' v ysignal Bit_Cnt : unsigned (3 downto 0);
7 S( }% U( X v1 p- i' H3 y' x5 O1 Wsignal Parity : std_logic;0 ]/ [/ j* t7 ]
signal Scan_DAVi : std_logic;
7 Y, c' z0 H/ Y& d, T9 {6 r; k! Usignal S_Reg : std_logic_vector(8 downto 0);# E/ @& o# X2 A* T; |9 e4 d# U
signal PS2_Clk_f : std_logic;
* r1 n& W! m! n3 z: @# lType State_t is (Idle, Shifting);
+ R1 R3 H' N0 t" q$ X$ g' }, ysignal State : State_t;
* r8 H a. ^4 V( mbegin
# C/ Z- c. U8 P- a1 AScan_DAV <= Scan_DAVi;$ I' i D8 \9 y: H7 V- C9 w
-- This filters digitally the raw clock signal coming from the keyboard :! X! ?1 [: Q- j
-- * Eight consecutive PS2_Clk=1 makes the filtered_clock go high7 {, n: p) L2 B
-- * Eight consecutive PS2_Clk=0 makes the filtered_clock go low
0 T) f( U9 M. J-- Implies a (FilterSize+1) x Tsys_clock delay on Fall_Clk wrt Data
; b% E/ F/ _9 @/ B7 y+ w1 u-- Also in charge of the re-synchronization of PS2_Data7 m" v$ t, x. q6 U
process (Clk,Reset)) b' _# e& [0 B9 f' r3 g1 T7 W
begin& I) E& [0 h3 n, w+ t D, ~
if Reset='0' then- C4 a, P- o% Q7 X6 x- k/ A" c& z2 ]
PS2_Datr <= '0';
) Q8 j5 e- U- n, ]PS2_Clk_f <= '0';' R6 W0 G2 z: X2 O# v( m
Filter <= (others=>'0');
* M. C! \7 h" c/ A0 S8 nFall_Clk <= '0';
7 `1 @" e# N: R, n- Gelsif rising_edge (Clk) then
2 a0 {' ]& ?& KPS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'; p9 f* K: y9 P
Fall_Clk <= '0';2 A) L" V S" O8 l, D8 ^0 L
Filter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);) \9 ?1 ?: {* m: h# h4 f3 ?$ E
if Filter = Filter_t'(others=>'1') then- v. U1 w/ P/ H1 P
PS2_Clk_f <= '1';
- `, z- F& D/ Q4 L* {elsif Filter = Filter_t'(others=>'0') then- r4 t7 A s5 }! ], \
PS2_Clk_f <= '0';2 a. F- Z- w2 Z8 C' u% p" i0 t
if PS2_Clk_f = '1' then7 L# t$ A& q% Y6 e! R% `
Fall_Clk <= '1';
3 S7 H* ? F @2 ?9 ?$ ^+ yend if;
: }; Z; ~) S$ Y3 E* z' m# yend if;% K! i$ s# Z: H9 j- |% }
end if;" Q" C( O0 G; k) S: P( z1 W0 p
end process;! S; A) ^+ {; t* _ Z
-- This simple State Machine reads in the Serial Data/ f; h0 n& {. \
-- coming from the PS/2 peripheral.
+ t& V/ @1 y; w6 b( X, Bprocess(Clk,Reset)0 ?& J( O; p( A1 E5 o
begin
" d( i* ]+ a8 X9 _& `8 n( i& b) iif Reset='0' then
5 a* h0 z8 V, R+ _1 A# P) {8 bState <= Idle;
& l7 w- S- f2 E# p v) z9 DBit_Cnt <= (others => '0');4 y; V$ F1 _6 g8 C, ^" v
S_Reg <= (others => '0');1 C5 W, o9 \, e' v8 e2 E& @
Scan_Code <= (others => '0');
% e# ^7 R( _8 x! a- b# }Parity <= '0';) V, z4 U2 D# h, |$ s
Scan_Davi <= '0';9 p! m( B+ Z; J$ ^! H" u- O
Scan_Err <= '0';
" c8 w% Q+ r; q# e/ F" qelsif rising_edge (Clk) then" I; B( J- A$ } _* b
if DoRead='1' then4 p2 U+ h" V+ `$ ?! H: z- h) O, b
Scan_Davi <= '0'; -- note: this assgnmnt can be overriden
1 N5 b, c6 @1 Cend if;5 T7 ^* V8 d' h. Y7 J$ R# V
case State is
/ L& b% m/ g5 }when Idle =>. ~' d& a( P( T8 C
Parity <= '0';2 V( @0 C9 ]( D
Bit_Cnt <= (others => '0');; l; y R. |0 ^. r5 G' W e% a, t
-- note that we dont need to clear the Shift Register
0 A( R' l- s0 w N! J' ?if Fall_Clk='1' and PS2_Datr='0' then -- Start bit; F: G# B% X, u- S, U: g5 D
Scan_Err <= '0';6 Q% Q' \8 d: E7 ^' I5 ~
State <= Shifting;8 _2 s( M ^# R1 W
end if;
& K9 v& I( W9 ~ t# f @3 |when Shifting =>
8 B' I5 h. x0 zif Bit_Cnt >= 9 then
) `" _3 d2 k" h! v. Q5 T' K* t: j+ A0 H7 zif Fall_Clk='1' then -- Stop Bit2 r! J# }0 J% P5 ]% _
-- Error is (wrong Parity) or (Stop='0') or Overflow
6 U: {/ K. `& R% f# jScan_Err <= (not Parity) or (not PS2_Datr) or Scan_DAVi;
; w2 W5 V. r7 ~+ m+ q4 v2 {; J- f" W- mScan_Davi <= '1';
" i+ G$ ]' F$ T# ?" PScan_Code <= S_Reg(7 downto 0);
+ Q( j( [1 ~9 K$ _" o. U3 o% oState <= Idle;3 y& U" Z) _1 v: C0 D/ Q& C* k
end if;
; T+ n- J/ I& S# X" z; d, y; b0 _elsif Fall_Clk='1' then
3 X p* k* j' [5 a8 QBit_Cnt <= Bit_Cnt + 1;
; z2 i0 t( Z7 ]' x; W& L/ XS_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
- H5 y6 u! g" O7 e/ F" T0 {" |Parity <= Parity xor PS2_Datr;+ l3 s1 x9 K, U* _
end if;( P* Y" Y0 T4 i1 o, F
when others => -- never reached+ X5 }; a* `% i# b! q
State <= Idle;
5 m) }" c0 z8 ^/ l; ^. d, j! Bend case;
. n5 F; s; G. z$ _end if;8 r% b+ X) @4 }0 {
end process;8 P9 t" \: ~* y" m" G) I
end ALSE_RTL; |
|