|
目前需要使用MAXII 1270 做PS/2 Keyboard控制,在網路上找到了用VHDL寫PS/2介面,經過測試後正常,但輸出是8個Pin輸出(並聯),但我希望輸出為1個Pin(串聯)輸出,請問我該如果修改程式呢?請大家幫幫忙,給個意見,或者提供任何資料參考...thx
7 u1 e" ~2 |: o, ^ f, L+ X! ^7 E0 a5 ^# Q1 W, u* x
程式如下:8 c% U# u0 b- C9 M4 k8 X
-- PS2_Ctrl.vhd! t$ ` j0 F1 w, E
-- ------------------------------------------------
6 _6 ]/ ~) u b+ {. B( v-- Simplified PS/2 Controller (kbd, mouse...)3 A6 `9 I' S0 C4 K6 M+ o
-- ------------------------------------------------' g% E; O0 O/ e
-- Only the Receive function is implemented !
3 h+ W; q0 ?( B-- (c) ALSE. http://www.alse-fr.com( p% I8 ]& u4 G
library IEEE;* h _% K- {" g$ e* o* ^4 j+ Q: O
use IEEE.STD_LOGIC_1164.all;7 q8 y* U9 W! R
use IEEE.Numeric_std.all;# W/ F) {8 r7 v2 j3 J6 E
-- --------------------------------------
# r& H9 Q- J7 `4 i* GEntity PS2_Ctrl is
" f2 U7 `* z" Z% T7 Q-- --------------------------------------
8 S8 ]6 R% z/ h, Dgeneric (FilterSize : positive := 8);+ e5 d, H* y0 `0 T9 |3 J5 X u
port( Clk : in std_logic; -- System Clock
. A8 O; B+ W- e" V' IReset : in std_logic; -- System Reset3 |+ W8 J1 G; y6 D7 y& X W0 |
PS2_Clk : in std_logic; -- Keyboard Clock Line( x9 P+ \. B: E) c6 _
PS2_Data : in std_logic; -- Keyboard Data Line$ ^! `" u. k) h+ A
DoRead : in std_logic; -- From outside when reading the scan code
# q! U; M3 A; O) e7 bScan_Err : out std_logic; -- To outside : Parity or Overflow error
1 `* r# X, x# v. lScan_DAV : out std_logic; -- To outside when a scan code has arrived* Y% p' K5 r9 r S5 r0 k
Scan_Code : out std_logic_vector(7 downto 0) -- Eight bits Data Out
3 E, Y8 |- C$ E$ J); @% N- U0 E+ H1 E
end PS2_Ctrl;
' s8 r$ t! n- H+ \/ x: B$ d* i$ {-- --------------------------------------
. j: ` @7 x, i$ ~2 |Architecture ALSE_RTL of PS2_Ctrl is
: B( I( k8 b- W5 I' K4 @-- --------------------------------------3 }8 ~; |6 s3 n7 ~$ z& `
-- (c) ALSE. http://www.alse-fr.com
2 X$ a9 f* c$ G) M2 X-- Author : Bert Cuzeau.
5 c. ?. i- i# s: \( @& h' l-- Fully synchronous solution, same Filter on PS2_Clk.
, }; t/ k. X! T$ C-- Still as compact as "Plain_wrong"...6 q' R k- d$ C6 {, r
-- Possible improvement : add TIMEOUT on PS2_Clk while shifting* w( k! r4 B( l8 z
-- Note: PS2_Data is resynchronized though this should not be
+ x7 ?$ Z) F' `! ` ]( D-- necessary (qualified by Fall_Clk and does not change at that time).! _' ~- R5 p8 O$ E! j
-- Note the tricks to correctly interpret 'H' as '1' in RTL simulation.
: E3 L3 \+ ?3 v. D$ O+ T. bsignal PS2_Datr : std_logic;4 K Q8 Z5 t/ ` C: f
subtype Filter_t is std_logic_vector(FilterSize-1 downto 0);8 p8 \6 {: q' U; B. E
signal Filter : Filter_t;" m% [# r8 F% w: v& J6 U
signal Fall_Clk : std_logic;
0 C6 S+ T$ b. t, N+ M* P! n/ [signal Bit_Cnt : unsigned (3 downto 0);/ v& K: L4 a b5 ~. ]( P
signal Parity : std_logic;
, }& B) [+ Z, q* e4 i* wsignal Scan_DAVi : std_logic;+ J; m: n9 @2 a
signal S_Reg : std_logic_vector(8 downto 0);, G Q' J. @! @4 ~5 r
signal PS2_Clk_f : std_logic;: s/ b& i& X1 q, p+ Y
Type State_t is (Idle, Shifting);
, ?3 ?7 P4 b l/ Z7 Q. }% Esignal State : State_t;$ e8 r( @0 T: Z
begin
4 J2 O" s P2 Z) i$ ]' F: i+ {Scan_DAV <= Scan_DAVi;
" p/ m7 D# J, n-- This filters digitally the raw clock signal coming from the keyboard :' E, z: C7 g6 `% R+ n' v" e
-- * Eight consecutive PS2_Clk=1 makes the filtered_clock go high* q5 O3 ?; G$ J5 z) V2 l8 k! H5 f) S& R
-- * Eight consecutive PS2_Clk=0 makes the filtered_clock go low
5 o# P1 k* O) d2 Y-- Implies a (FilterSize+1) x Tsys_clock delay on Fall_Clk wrt Data" `' [( E! N& L* b# ]
-- Also in charge of the re-synchronization of PS2_Data* r8 D2 n% a. L$ ?; L
process (Clk,Reset)
% [1 c) m3 p: y) j, A( F& _* R! |begin
, u( |/ @8 a' c/ i! g# Sif Reset='0' then
- g* ~2 u2 f6 j9 H) s7 nPS2_Datr <= '0';! l7 w; F& z. V8 e' E: M) u; E
PS2_Clk_f <= '0';' P) Q2 ~2 y/ X
Filter <= (others=>'0');' A! B" [9 ^' o8 t
Fall_Clk <= '0';2 y. N& S- W( P" j
elsif rising_edge (Clk) then/ M3 m0 z& i i, w _8 c
PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'
3 G* h/ B* w1 ]& V, M; lFall_Clk <= '0';2 _6 t0 p) {% |% M# n+ l2 o
Filter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);
" o7 [- z P: U- r7 W8 yif Filter = Filter_t'(others=>'1') then
5 v& K- m$ j, f1 ~2 O4 t8 bPS2_Clk_f <= '1';
- A8 \$ I$ H! [& Q, {8 j/ G1 _elsif Filter = Filter_t'(others=>'0') then
" J/ U& M/ z2 l/ J9 |PS2_Clk_f <= '0';, \9 b0 X, R' B
if PS2_Clk_f = '1' then( R0 G- Y$ p1 k0 e8 f9 P
Fall_Clk <= '1'; I% ~, X5 t4 }$ f" M m
end if;# Q0 ?' E. }2 ~! ?; t, ?
end if;
2 h" b$ U+ R# w* gend if;) ^6 Y5 A Q3 D/ [& T1 P
end process;7 _* g. N. Q$ T7 V' v2 ^
-- This simple State Machine reads in the Serial Data8 U# k8 ^' W- e
-- coming from the PS/2 peripheral.
5 W5 _0 C' x6 [- L# Y; x' F$ Uprocess(Clk,Reset)7 K" y4 h/ A5 e! y
begin
1 \& d$ ^0 i; o& r$ S9 M5 M( ?if Reset='0' then
T( ?* B: a$ h* _State <= Idle;' V0 g$ \ A7 F, j3 L' w% B
Bit_Cnt <= (others => '0');, F, G- P3 D! n7 ?
S_Reg <= (others => '0');; @# K& D: |- Z6 x+ H) _
Scan_Code <= (others => '0');; Z/ d; {" a$ d2 i% \
Parity <= '0';% a* J/ i+ F" A9 X3 C
Scan_Davi <= '0';8 b6 j$ F) k# C4 o" k8 Y
Scan_Err <= '0';4 S8 N9 r; ?0 K! y
elsif rising_edge (Clk) then8 r o+ { A& }2 v4 O
if DoRead='1' then. z; Z; f9 X4 m% p
Scan_Davi <= '0'; -- note: this assgnmnt can be overriden4 n" d1 j$ r) C0 i
end if;6 h4 r, P# I: K) `2 ~: [( u
case State is3 b+ j7 A0 }. p! u5 ^9 Z! O
when Idle =>
' I7 k& v9 l# d, i7 Z( i( I3 GParity <= '0';
& y1 m9 ?; i, {( j F- {Bit_Cnt <= (others => '0');
' J9 }' [" n7 L. M0 \6 h-- note that we dont need to clear the Shift Register7 L: u \0 X# ^' s
if Fall_Clk='1' and PS2_Datr='0' then -- Start bit
6 [# O$ M! F3 TScan_Err <= '0';
3 Z6 Q; D" V) i& G2 L# kState <= Shifting;/ k2 v% A! o; {$ e5 x8 {' V/ Q
end if;
3 [: e+ j" W( ]; j# U6 A4 fwhen Shifting =>" V5 _$ i% e* h- ^6 ` X R& m
if Bit_Cnt >= 9 then+ C7 E/ \. E- B! E9 b$ L+ `
if Fall_Clk='1' then -- Stop Bit/ T" u; B* s' n
-- Error is (wrong Parity) or (Stop='0') or Overflow% D7 C; L# h1 B" x5 j. H- F
Scan_Err <= (not Parity) or (not PS2_Datr) or Scan_DAVi;
' ?6 c) S3 O) W3 ], A7 T! H. F% [Scan_Davi <= '1';
7 i$ l6 R( ~5 P- `Scan_Code <= S_Reg(7 downto 0);
( D* F$ H& ~4 _% I, P. eState <= Idle;( L0 M2 H3 s P# @. t1 E, H, ^; Z
end if;
' H% x# h2 B/ K m% w9 {! p( ?. qelsif Fall_Clk='1' then
, I+ a2 V/ f1 _2 kBit_Cnt <= Bit_Cnt + 1;! x4 Q9 @4 m& @+ t+ p3 I
S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
7 Z. W' u$ V. V7 ?$ lParity <= Parity xor PS2_Datr;
: F/ v' n; Y' o- Y. N% R# j4 i8 Tend if;1 V g9 W- \) [4 V
when others => -- never reached
3 J9 j1 t7 {+ }! `8 w9 U! G4 p6 k3 AState <= Idle;
! Z+ q' E( t, t, O2 ^end case;1 L d1 }1 ]6 `* z( f
end if; M, `$ h+ q! V0 r. `
end process;
$ F7 z% q2 [( W ?end ALSE_RTL; |
|