Forum: FPGA, VHDL & Co. RS232 und Tastatur zusammenbringen?


von peter (Gast)


Lesenswert?

Hallo, guten Tag.
Ich habe mit diesen beiden Programmen Schwierigkeiten, diese miteinander 
zu verbinden.

Tastatur abfragen und die Daten zu versenden zum PC? Bekomme das 
combinatorisch nicht hin.

Im ersten Programm gebe ich mit dem Switch ein Byte ein (TX_Data) und 
Sende es zum PC mit der Taste key.
Das funktioniert auch.
Im zweiten Programm werte ich die Daten von der Tastaur aus und gebe den 
ASCII-Wert(RxData) auf 8-LED am DE-1 aus.
Auch hier funktioniert es wunderbar.

Ich weiss nicht , wie ich diese beiden Programme verbinde damit sie 
funktionieren.
Beim RS2322 wird ja erst gesendet nach dem Key-Druck und das muss ja 
jetzt geschehen wenn die Tastatur die
Daten ablegt in TX_Data ohne ein Druckschalter zu betätigen.

Wer kann mir mal bitte ausführlich helfen?

Danke.
Gruss

RS232:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity RS232_tx is
6
7
Generic ( Quarz_Taktfrequenz : integer   := 50000000;  -- Hertz 
8
          Baudrate           : integer   :=  9600      -- Bits/Sec
9
          ); 
10
           
11
port (  TXD     : out  STD_LOGIC;
12
        CLK     : in   STD_LOGIC; 
13
        key     : in   std_logic_vector(0 downto 0);  
14
        TX_Data : in STD_LOGIC_VECTOR (7 downto 0) := (others => '0')
15
         );
16
end RS232_tx;
17
18
architecture Behavioral of RS232_tx is
19
20
signal txstart  : std_logic := '0';
21
signal txsr     : std_logic_vector  (9 downto 0) := "1111111111";  -- Startbit, 8 Datenbits, Stopbit
22
signal txbitcnt : integer range 0 to 10 := 10;
23
signal txcnt    : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1;
24
signal tx_start  : STD_LOGIC :='0';
25
26
begin
27
28
-- Senden
29
process(clk)
30
begin
31
if rising_edge(clk) then
32
  
33
  if key(0) = '0' then
34
     tx_start <= '1' ;
35
  else
36
     tx_start <= '0';
37
  end if;
38
  
39
  txstart <= TX_Start;
40
  if (TX_Start='1' and txstart='0') then -- steigende Flanke, los gehts
41
    txcnt    <= 0;                       -- Zähler initialisieren
42
    txbitcnt <= 0;                      
43
    txsr     <= '1' & TX_Data & '0';     -- Stopbit, 8 Datenbits, Startbit, rechts gehts los
44
  else
45
    if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
46
      txcnt <= txcnt+1;
47
    else  -- nächstes Bit ausgeben  
48
      if (txbitcnt<10) then
49
        txcnt    <= 0;
50
        txbitcnt <= txbitcnt+1;
51
        txsr     <= '1' & txsr(txsr'left downto 1);
52
      end if;
53
    end if;
54
  end if;
55
end if;
56
end process;
57
58
TXD  <= txsr(0);  -- LSB first  
59
end Behavioral;

Tastatur:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity PS2_Keyboard is
6
    Port ( PS2_Data    : in  std_logic;
7
           PS2_Clk     : in  std_logic;
8
           CLK         : in  std_logic;
9
           RxData      : out std_logic_vector(7 downto 0);
10
           RxActive    : out std_logic;
11
           DataReady   : out std_logic -- Handshake-Signal: Daten bereit     
12
          );           
13
end PS2_Keyboard;
14
15
architecture Behavioral of PS2_Keyboard is
16
17
signal RxTimeout   : integer range 0 to 500000 := 0; -- max. 10ms
18
signal RxRegister  : std_logic_vector(10 downto 0) := (others=>'1');
19
signal DataSR      : std_logic_vector(1 downto 0)  := (others=>'1');
20
signal ClkSR       : std_logic_vector(1 downto 0)  := (others=>'1');
21
signal DataFetched : std_logic :='1'; -- Handshake-signal: Daten übernommen
22
23
type PS2RXStateType is (IDLE, RECEIVE, READY); 
24
signal PS2RXState : PS2RXStateType := IDLE;
25
26
begin
27
process(clk) 
28
begin
29
if rising_edge(clk)then
30
  RxTimeout <= RxTimeout+1;
31
  
32
  DataSR    <= DataSR(0) & PS2_Data;
33
  ClkSR     <= ClkSR(0)  & PS2_Clk;
34
  
35
  if (ClkSR = "10") then -- fallende Flanke am PS2_CLK
36
    RxRegister <= DataSR(1) & RxRegister(10 downto 1);
37
  end if;
38
39
  case PS2RXState is
40
  when IDLE =>
41
    RxRegister <= (others=>'1');
42
    RxActive   <= '0';
43
    DataReady  <= '0';
44
    RxTimeout  <= 0;
45
    if (DataSR(1) = '0' and ClkSR(1) = '1') then -- STARTBIT erkannt
46
      PS2RXState <= RECEIVE;
47
      RxActive   <= '1';       
48
    end if;
49
    
50
  when RECEIVE =>
51
    if (RxTimeout = 500000) then     -- 10 ms
52
      PS2RXState <= IDLE;
53
    elsif (RxRegister(0) = '0') then -- Startbit ganz durchgeschoben?
54
      DataReady  <= '1';             -- SCANCODE empfangen
55
      RxData     <= RxRegister(8 downto 1);
56
      PS2RXState <= READY;
57
    end if;
58
    
59
  when READY =>                      -- warten, bis Daten abgeholt sind
60
    if (DataFetched='1') then
61
      PS2RXState <= IDLE;
62
      DataReady  <= '0';
63
      RxActive   <= '0';            
64
     end if;
65
  end case;
66
end if;    
67
end process;
68
 
69
end Behavioral;

von Uwe (Gast)


Lesenswert?

Indem du in der PS2 Statemachine im RECEIVE State in einen weiteren 
State weiterschaltest der darauf wartet das Jemand die Daten abholt. 
Dieses muß dieser Jemand aber Signalisieren (das die Daten abgeholt 
wurden), erst dann wird wieder in den READY State weitergeschaltet. Die 
RS232 sollte auch als Statemachine implemtiert werden, diese wartet auf 
DataReady=1 und holt die Daten ab und Signalisiert, daß sie die Daten 
abgeholt hat.
Dies könnte man noch mit einem FIFO erweitern damit keine Daten verloren 
gehen, aber soweit ich weiß hat ne PS2 Tastatur schon einen FIFO drin.
Dann solltest du noch nen Busy Signal  (bzw. Ready Signal) in der RS232 
drin haben damit die PS2 solange wartet bis die RS232 ihre Daten 
gesendet hat.

von peter (Gast)


Lesenswert?

Hmm.., danke.
Das hört sich ja nicht einfach an.


Gruss

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

peter schrieb:
> Ich weiss nicht , wie ich diese beiden Programme verbinde damit sie
> funktionieren.
Es sind keine Programme und sie funktionieren ja schon. Du könntest 
übrigens wenigstens erwähnen, woher du die Beschreibungen kopiert hast, 
dann müsste man nicht raten...
http://www.lothar-miller.de/s9y/archives/48-RS232.html
http://www.lothar-miller.de/s9y/archives/75-PS2-Tastatur.html

> Ich weiss nicht , wie ich diese beiden Programme verbinde damit sie
> funktionieren.
Du brauchst jetzt ein Toplevel Modul, in dem diese beiden Komponenten 
instantiiert werden (Zu finden im VHDL Buch unter dem Stichwort 
"component").

> Beim RS2322 wird ja erst gesendet nach dem Key-Druck und das muss ja
> jetzt geschehen wenn die Tastatur die
> Daten ablegt in TX_Data ohne ein Druckschalter zu betätigen.
Ich würde es mit meinen originalen Beschreibungen im ersten Anlauf so 
probieren:
1
  TX_Data     <= RxData;    -- Daten vom PS2 an RS232 geben
2
  Tx_Start    <= DataReady; -- Übertragung starten, wenn PS2 Daten hat
3
  DataFetched <= DataReady; -- PS2 gibt sich selber den Handshake

: Bearbeitet durch Moderator
von peter (Gast)


Lesenswert?

Jup danke.
Es kommen jetzt Daten am PC an, aber noch nicht der gedrückte ASCII.

Danke.

GRuss

von Uwe (Gast)


Lesenswert?

Jo ne Tastatur gibt Scancodes aus.
http://www.marjorie.de/ps2/ps2_keyboard.htm

von peter (Gast)


Lesenswert?

JUp danke Lothar, deine 3 Zeilen waren entscheidend.
Es kommt am PC der "Keyboard Scan Codes: Set 2" von hier (Hilfe von Uwe) 
http://www.marjorie.de/ps2/scancode-set2.htm an.
Dauertastendruck funktioniert sauber und beim loslassen kommt Hex"F0".

Danke.
Gruss
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;

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.