1 | library IEEE;
|
2 | use IEEE.STD_LOGIC_1164.ALL;
|
3 | use IEEE.NUMERIC_STD.ALL;
|
4 |
|
5 | entity PS2_Keyboard_tx is
|
6 | Generic ( Quarz_Taktfrequenz : integer := 50000000; -- Hertz
|
7 | Baudrate : integer := 9600 -- Bits/Sec
|
8 | );
|
9 |
|
10 | Port ( PS2_Data : in std_logic;
|
11 | PS2_Clk : in std_logic;
|
12 | CLK : in std_logic;
|
13 | TXD : out STD_LOGIC
|
14 | );
|
15 | end PS2_Keyboard_tx;
|
16 |
|
17 | architecture Behavioral of PS2_Keyboard_tx is
|
18 |
|
19 | signal RxTimeout : integer range 0 to 500000 := 0; -- max. 10ms
|
20 | signal RxRegister : std_logic_vector(10 downto 0) := (others=>'1');
|
21 | signal DataSR : std_logic_vector(1 downto 0) := (others=>'1');
|
22 | signal ClkSR : std_logic_vector(1 downto 0) := (others=>'1');
|
23 | signal DataFetched : std_logic :='1'; -- Handshake-signal: Daten übernommen
|
24 | signal RxActive : std_logic;
|
25 | signal DataReady : std_logic; -- Handshake-Signal: Daten bereit
|
26 | signal RxData : std_logic_vector(7 downto 0);
|
27 |
|
28 | signal txstart : std_logic := '0';
|
29 | signal txsr : std_logic_vector (9 downto 0) := "1111111111"; -- Startbit, 8 Datenbits, Stopbit
|
30 | signal txbitcnt : integer range 0 to 10 := 10;
|
31 | signal txcnt : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1;
|
32 | signal TX_Data : STD_LOGIC_VECTOR (7 downto 0);
|
33 | signal TX_Start : STD_LOGIC;
|
34 | signal TX_Busy : STD_LOGIC;
|
35 |
|
36 | type PS2RXStateType is (IDLE, RECEIVE, READY);
|
37 | signal PS2RXState : PS2RXStateType := IDLE;
|
38 |
|
39 | begin
|
40 |
|
41 | process(clk)
|
42 |
|
43 | begin
|
44 | if rising_edge(clk)then
|
45 | RxTimeout <= RxTimeout+1;
|
46 |
|
47 | DataSR <= DataSR(0) & PS2_Data;
|
48 | ClkSR <= ClkSR(0) & PS2_Clk;
|
49 |
|
50 | if (ClkSR = "10") then -- fallende Flanke am PS2_CLK
|
51 | RxRegister <= DataSR(1) & RxRegister(10 downto 1);
|
52 | end if;
|
53 |
|
54 | case PS2RXState is
|
55 | when IDLE =>
|
56 | RxRegister <= (others=>'1');
|
57 | RxActive <= '0';
|
58 | DataReady <= '0';
|
59 | RxTimeout <= 0;
|
60 | if (DataSR(1) = '0' and ClkSR(1) = '1') then -- STARTBIT erkannt
|
61 | PS2RXState <= RECEIVE;
|
62 | RxActive <= '1';
|
63 | end if;
|
64 |
|
65 | when RECEIVE =>
|
66 | if (RxTimeout = 500000) then -- 10 ms
|
67 | PS2RXState <= IDLE;
|
68 | elsif (RxRegister(0) = '0') then -- Startbit ganz durchgeschoben?
|
69 | DataReady <= '1'; -- SCANCODE empfangen
|
70 | RxData <= RxRegister(8 downto 1);
|
71 | PS2RXState <= READY;
|
72 | end if;
|
73 |
|
74 | when READY => -- warten, bis Daten abgeholt sind
|
75 | if (DataFetched='1') then
|
76 | PS2RXState <= IDLE;
|
77 | DataReady <= '0';
|
78 | RxActive <= '0';
|
79 | end if;
|
80 | end case;
|
81 | end if;
|
82 | end process;
|
83 |
|
84 | process(clk)
|
85 | begin
|
86 | if rising_edge(clk) then
|
87 | txstart <= TX_Start;
|
88 | if (TX_Start='1' and txstart='0') then -- steigende Flanke, los gehts
|
89 | txcnt <= 0; -- Zähler initialisieren
|
90 | txbitcnt <= 0;
|
91 | txsr <= '1' & TX_Data & '0'; -- Stopbit, 8 Datenbits, Startbit, rechts gehts los
|
92 | else
|
93 | if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
|
94 | txcnt <= txcnt+1;
|
95 | else -- nächstes Bit ausgeben
|
96 | if (txbitcnt<10) then
|
97 | txcnt <= 0;
|
98 | txbitcnt <= txbitcnt+1;
|
99 | txsr <= '1' & txsr(txsr'left downto 1);
|
100 | end if;
|
101 | end if;
|
102 | end if;
|
103 | end if;
|
104 | end process;
|
105 |
|
106 | Tx_Start <= DataReady; -- Übertragung starten, wenn PS2 Daten hat
|
107 | DataFetched <= DataReady; -- PS2 gibt sich selber den Handshake
|
108 | TX_Data <= RxData; -- Daten vom PS2 an RS232 geben
|
109 |
|
110 | TXD <= txsr(0); -- LSB first
|
111 | TX_Busy <= '1' when (TX_Start='1' or txbitcnt<10) else '0';
|
112 |
|
113 | end Behavioral;
|