|
目前需要使用MAXII 1270 做PS/2 Keyboard控制,在網路上找到了用VHDL寫PS/2介面,經過測試後正常,但輸出是8個Pin輸出(並聯),但我希望輸出為1個Pin(串聯)輸出,請問我該如果修改程式呢?請大家幫幫忙,給個意見,或者提供任何資料參考...thx
8 H; S; j4 [& q. Z0 Q1 P$ ?, v6 G8 d3 k3 _* F8 z/ [3 }/ \3 }7 E
程式如下:
0 i/ ?& p( q* `7 u! D, f8 k, F-- PS2_Ctrl.vhd
3 G; N3 h- }5 \. B! K5 L7 J( y5 p-- ------------------------------------------------4 ^0 p4 t4 q8 k0 O7 t3 k
-- Simplified PS/2 Controller (kbd, mouse...)
& n! h, E/ h; Q; o, e. I7 K& Y# W-- ------------------------------------------------5 {% ~* g: i/ i5 l
-- Only the Receive function is implemented !
" U/ m7 `6 t: M# ^0 _% ?-- (c) ALSE. http://www.alse-fr.com0 `4 X6 O1 m! _- K: H! X0 V
library IEEE;
' I( F5 @9 D ?0 juse IEEE.STD_LOGIC_1164.all;
) w+ F0 R3 G1 F4 g5 cuse IEEE.Numeric_std.all;$ }" ~% d$ s; U4 A% v7 ^
-- --------------------------------------
7 }; B+ a) m; L) S1 C9 K' cEntity PS2_Ctrl is* M2 Z+ O# g9 I! u& H
-- --------------------------------------0 X" F1 ]' A3 x! s% ^3 Y1 l
generic (FilterSize : positive := 8);+ Q& b7 n3 Y5 z1 |8 Y7 t
port( Clk : in std_logic; -- System Clock
" _/ ~6 `2 j# k/ a* LReset : in std_logic; -- System Reset, z( M/ }) ]: n
PS2_Clk : in std_logic; -- Keyboard Clock Line
% l' Q# c% G; ?PS2_Data : in std_logic; -- Keyboard Data Line
' W! ]! Q4 |( B! `DoRead : in std_logic; -- From outside when reading the scan code
- {! Y: {$ N& V% A1 p/ l, e- b: H+ f! |Scan_Err : out std_logic; -- To outside : Parity or Overflow error
; I; s& x8 G6 S9 r, Y6 \9 l) FScan_DAV : out std_logic; -- To outside when a scan code has arrived/ s- Q+ N* l/ w" \% Z6 E
Scan_Code : out std_logic_vector(7 downto 0) -- Eight bits Data Out
+ X1 Q) o% Z0 U7 {);6 W1 O0 T# q( A, x' D( M' `* ^: @
end PS2_Ctrl;3 B8 |4 H7 m8 x
-- --------------------------------------
) l; B1 O/ q( y7 g# `/ c/ e& V0 r6 KArchitecture ALSE_RTL of PS2_Ctrl is1 X, G* j% C5 y7 X# l: G8 Z
-- --------------------------------------
# F; r2 Y* M$ N-- (c) ALSE. http://www.alse-fr.com8 _9 n2 w: F6 F- q
-- Author : Bert Cuzeau.
$ A4 I8 O; R. D2 r. o-- Fully synchronous solution, same Filter on PS2_Clk.
& L! _: u, p, ?/ G. \# {-- Still as compact as "Plain_wrong"..., _& n3 n+ E( }
-- Possible improvement : add TIMEOUT on PS2_Clk while shifting8 a% k/ p C- h) e+ a- J5 x
-- Note: PS2_Data is resynchronized though this should not be
* E) e9 y/ o) N, U# L/ w6 u B-- necessary (qualified by Fall_Clk and does not change at that time)." V( Z3 n. }8 Q! r2 ~
-- Note the tricks to correctly interpret 'H' as '1' in RTL simulation.
6 x: Q9 F; c, D3 D1 U ? n& usignal PS2_Datr : std_logic;- V: Z! c) t7 M, V
subtype Filter_t is std_logic_vector(FilterSize-1 downto 0);
9 w* e+ B, ? E- w( B0 Esignal Filter : Filter_t;
V- r# c: I6 o( K0 n% a9 osignal Fall_Clk : std_logic;, f) p' c+ u# j* i
signal Bit_Cnt : unsigned (3 downto 0);
1 f. g& S( X5 G7 Fsignal Parity : std_logic;
# q' c8 D- U3 @* K5 f/ E* _signal Scan_DAVi : std_logic;
8 y, k }) Z8 G6 nsignal S_Reg : std_logic_vector(8 downto 0);: d+ j0 Y0 `2 G2 F5 _
signal PS2_Clk_f : std_logic;
6 L3 ~- C; q# @( @Type State_t is (Idle, Shifting);
/ N- \% `- b; f |3 usignal State : State_t;9 z+ Q" [5 B- ~: {
begin
$ G5 Z8 w3 |4 j: XScan_DAV <= Scan_DAVi;' c. m% s7 Q0 U8 G
-- This filters digitally the raw clock signal coming from the keyboard :8 i3 g3 d/ ^9 b% i3 ] ~/ p- S
-- * Eight consecutive PS2_Clk=1 makes the filtered_clock go high- Y1 z* q2 [1 @; `: s# S
-- * Eight consecutive PS2_Clk=0 makes the filtered_clock go low
( T2 X( ?: b" ?: r' }! u6 a-- Implies a (FilterSize+1) x Tsys_clock delay on Fall_Clk wrt Data
" v; N. L' x$ h M-- Also in charge of the re-synchronization of PS2_Data
7 u9 D" v; p) D0 O( r6 N' \8 k3 Cprocess (Clk,Reset)2 f2 Z1 |+ c# n) W" a$ d; ?
begin4 ]9 z$ t6 I: d# V# V6 `' n: W# V
if Reset='0' then
2 ]* T' w. M# V' ~& q9 J4 ]/ j6 CPS2_Datr <= '0';6 z! {) ^0 G J! |
PS2_Clk_f <= '0';( c/ O8 r, k L7 E
Filter <= (others=>'0');
- r( V! @( m( O( U' n( ^Fall_Clk <= '0';
% e* ]& j3 i1 o% Qelsif rising_edge (Clk) then4 _% p' B4 B* M! Y6 p% \) m
PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'( S) E5 _$ x+ ]& q, |0 Z) T
Fall_Clk <= '0';
# p8 ?, V* `' T2 m$ K! [: vFilter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);
. \+ h/ q& z3 Yif Filter = Filter_t'(others=>'1') then% ^( j( g" g9 `, g& N
PS2_Clk_f <= '1';8 m6 z' V$ W5 b
elsif Filter = Filter_t'(others=>'0') then
4 Z) s" M: _+ p- m8 k; [- X+ pPS2_Clk_f <= '0';) k6 e9 T+ j: f8 S
if PS2_Clk_f = '1' then9 L: \( [; o3 I( a2 a8 G
Fall_Clk <= '1';
* ~2 f! e: p: \: I2 Bend if;
: N8 [% l4 h! @/ ]. g0 [0 V+ Mend if;: {. l" B) U* W+ G; o- {/ m7 _
end if;9 B# K+ ]) Z: K& _
end process;
3 y, I+ D+ R0 U5 N2 r-- This simple State Machine reads in the Serial Data! J% ]( e6 ~4 A3 y( z& i' i H3 a
-- coming from the PS/2 peripheral.' B4 s5 L+ m, f6 ~$ N
process(Clk,Reset)7 {* K% S# s# p4 C$ k2 x3 C
begin
4 K0 S9 b {5 l& K4 O1 W9 @* Kif Reset='0' then" M6 S' u: x/ t5 v$ [1 d5 k
State <= Idle;4 S5 @1 {6 \) ~: f" Y" z; Z
Bit_Cnt <= (others => '0');. f; f/ g) }, {
S_Reg <= (others => '0');: W, t* {5 W/ a6 Z( Q6 I4 F
Scan_Code <= (others => '0');
. p1 O/ B3 U5 c% r' ?- d$ |) DParity <= '0';& }. w: i8 G# j% L: a% _
Scan_Davi <= '0';6 X0 P" Z! n E- P l1 X* e8 Z
Scan_Err <= '0';
2 V% g" v" N# R, r" D8 a! Oelsif rising_edge (Clk) then% E5 A& K2 J; Z4 D4 j
if DoRead='1' then' S2 j4 K* V+ V- e! l8 f
Scan_Davi <= '0'; -- note: this assgnmnt can be overriden7 `" x8 A) g$ c% G) Y
end if;: d" v. } T0 @
case State is
0 i* i9 [0 R8 I, u' z1 ~2 _when Idle =>
+ a( g% l5 C( B9 S) oParity <= '0';
1 S! m7 u9 T, I* W9 vBit_Cnt <= (others => '0');
' [! s* c* e! L) D8 e' J3 J-- note that we dont need to clear the Shift Register
y9 F, {; o5 Z% Fif Fall_Clk='1' and PS2_Datr='0' then -- Start bit
) ?6 n+ C' q3 g6 m6 eScan_Err <= '0';, r$ W/ C( G; R$ c
State <= Shifting;4 J1 g$ z9 T3 R2 c0 P5 k
end if;1 U+ Q& \8 Y. G6 k$ R
when Shifting =>- p4 S4 N, E1 l$ l1 Y# G# F
if Bit_Cnt >= 9 then
) z" t c' i" kif Fall_Clk='1' then -- Stop Bit
# I/ ?$ j" e$ F% ~-- Error is (wrong Parity) or (Stop='0') or Overflow& E& t* f5 x" c- w0 n2 e1 ~- T
Scan_Err <= (not Parity) or (not PS2_Datr) or Scan_DAVi;, z1 |2 J6 Y! b1 K/ s$ s
Scan_Davi <= '1';1 \% z ^8 v5 {. j* D
Scan_Code <= S_Reg(7 downto 0);
0 D2 I( G/ _9 u$ |State <= Idle;
; F& Y1 i! L# N: r4 _# g% Jend if;$ Q4 j+ o$ M: o' ~
elsif Fall_Clk='1' then
* Z, z, ?% E9 k5 x8 O4 ZBit_Cnt <= Bit_Cnt + 1;' W, ]6 k* w A; a5 W/ s9 Y
S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
- \0 Z: \7 d: g u& O8 VParity <= Parity xor PS2_Datr;
2 d6 p3 m( ?% F, P% X5 J# Gend if;: `) N2 H' x4 H8 e! A u
when others => -- never reached
, c) n# {7 m& h# i& o8 c/ [State <= Idle;
* G0 K6 {2 \8 v! [1 A/ tend case;. |* ?& |4 n' i1 ~
end if;
3 ~8 X9 ~& h" y' q7 t; x' yend process;
3 a6 L) V Y1 H% T1 ]0 lend ALSE_RTL; |
|