Forum: FPGA, VHDL & Co. VHDL RS232 Spartan 3A


von Michael (Gast)


Lesenswert?

Hallo Zusammen!

Hab hier mal einen Code für die RS232 Schnittstelle geschrieben. Das 
Empfangen funktioniert nur das Senden noch nicht. Weiss nicht woran das 
liegt, könnte mir jemand weiterhelfen? Bin noch Neuling.
Gruß Michael

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity RS232 is
6
    Generic ( Quarz_Taktfrequenz : integer   := 50000000;  -- Hertz 
7
              Baudrate           : integer   :=  9600      -- Bits/Sec
8
             ); 
9
    Port ( RXD      : in   STD_LOGIC;
10
           TXD      : out  STD_LOGIC;
11
           CLK      : in   STD_LOGIC;
12
        LED     : out  STD_LOGIC_VECTOR (7 downto 0)
13
        
14
           );
15
end RS232;
16
17
architecture Behavioral of RS232 is
18
19
signal txstart : std_logic;
20
signal txsr    : std_logic_vector  (9 downto 0) := "1111111111";  -- Startbit, 8 Datenbits, Stopbit
21
signal txbitcnt : integer range 0 to 10 := 10;
22
signal txcnt    : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1;
23
24
signal rxd_sr  : std_logic_vector (3 downto 0) := "1111";         -- Flankenerkennung und Eintakten
25
signal rxsr    : std_logic_vector (7 downto 0) := "00000000";     -- 8 Datenbits
26
signal rxbitcnt : integer range 0 to 9 := 9;
27
signal rxcnt   : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1; 
28
29
---------------------------------------------------------------------------
30
signal counter: integer range 0 to 50000000 :=0;
31
--
32
--     
33
signal RX_Data  :   STD_LOGIC_VECTOR (7 downto 0);
34
signal RX_Busy  :   STD_LOGIC;
35
signal TX_Data  :    STD_LOGIC_VECTOR (7 downto 0):= "10101010";
36
signal TX_Start :    STD_LOGIC;
37
signal TX_Busy  :   STD_LOGIC;
38
39
---------------------------------------------------------------------------
40
41
begin
42
   
43
process (CLK)begin
44
  If rising_edge(CLK) then
45
    If counter < Quarz_Taktfrequenz/2 then
46
      TX_Start <= '1';
47
--      txstart <= '0';
48
                  
49
    elsif counter = Quarz_Taktfrequenz then
50
      counter <= 0;
51
    else
52
                  --LED(1) <= '1';
53
      TX_Start <= '0';
54
--      txstart <= '1';
55
    end if;
56
  end if;
57
end process;  
58
  
59
  -- Senden
60
   process begin
61
      wait until rising_edge(CLK);
62
      txstart <= TX_Start;
63
      if (TX_Start='1' and txstart='0') then -- steigende Flanke, los gehts
64
        
65
      txcnt    <= 0;                      -- Zähler initialisieren
66
         txbitcnt <= 0;                      
67
         txsr     <= '1' & TX_Data & '0';    -- Stopbit, 8 Datenbits, Startbit, rechts gehts los
68
                  --LED(0) <= '1';
69
      else
70
         if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
71
            txcnt <= txcnt+1;
72
         else  -- nächstes Bit ausgeben  
73
            if (txbitcnt<10) then
74
          
75
              txcnt    <= 0;
76
              txbitcnt <= txbitcnt+1;
77
              txsr     <= '1' & txsr(txsr'left downto 1);
78
            end if;
79
         end if;
80
      end if;
81
   end process;
82
  
83
  TXD     <= txsr(0);  -- LSB first
84
   TX_Busy <= '1' when (TX_Start='1' or txbitcnt<10) else '0';
85
                  --LED(2) <= '1';
86
   -- Empfangen
87
   process begin
88
      wait until rising_edge(CLK);
89
      rxd_sr <= rxd_sr(rxd_sr'left-1 downto 0) & RXD;
90
      if (rxbitcnt<9) then    -- Empfang läuft
91
         if(rxcnt<(Quarz_Taktfrequenz/Baudrate)-1) then 
92
            rxcnt    <= rxcnt+1;
93
         else
94
            rxcnt    <= 0; 
95
            rxbitcnt <= rxbitcnt+1;
96
            rxsr     <= rxd_sr(rxd_sr'left-1) & rxsr(rxsr'left downto 1); -- rechts schieben, weil LSB first         
97
      end if;
98
    else                                    -- warten auf Startbit
99
         if (rxd_sr(3 downto 2) = "10") then                 -- fallende Flanke Startbit
100
            rxcnt    <= ((Quarz_Taktfrequenz/Baudrate)-1)/2; -- erst mal nur halbe Bitzeit abwarten
101
            rxbitcnt <= 0;
102
         end if;
103
      end if;
104
   end process;
105
   RX_Data <= rxsr;
106
  LED      <= RX_Data;
107
   RX_Busy <= '1' when (rxbitcnt<9) else '0';
108
109
end Behavioral;

von Matthias (Gast)


Lesenswert?

Zeile 42!

Ordentliche Fehlermeldung bitte! "Senden geht nicht" ist ein wenig 
ungenau - was genau geht nicht? Kommt nix raus, kommt was unerwartetes 
raus? Haste ne testbench, eine Simulation oder haste das einfach auf den 
FPGA geklatscht? wie hast du festgestellt das es "nicht geht"?

von Michael (Gast)


Lesenswert?

Hab das Board mit der RS232 Schnittstelle am Pc verbunden und mit Hterm 
getestet und es ist nichts angekommen. Senden in Hterm geht. Es gehen 
dann die Leds auf dem Board an. Aber die 10101010 kommt am PC (Hterm) 
net an. Hterm ist ein ähnliches Programm wie Hyperterminal.

von Duke Scarring (Gast)


Lesenswert?

Simuliere das mal. Die Testbench dazu sollte nicht wirklich schwer sein, 
oder?

Duke

von Michael (Gast)


Lesenswert?

Keine Ahnung wie man simuliert. wie gesagt bin noch Neuling.

von Uwe N. (ex-aetzer)


Lesenswert?

Dann musst du dich mit der Thematik auseinandersetzen. Da kommst du 
einfach nicht herum.
Beim µC simulierst du doch auch (o.k., hier muss man keine Testbench 
entwerfen), oder gehst du von einem stets korrektem Code aus ?

Gruss Uwe

von Michael (Gast)


Lesenswert?

Bei so relativ einfachen Codes hatte ich noch kein Sinn gesehn zu 
Simulieren. Die meisten Codes konnte ich dann mit Leds testen. Naja muss 
ich mal schauen wie man simuliert.
Danke für die schnellen Antworten.

von Uwe N. (ex-aetzer)


Lesenswert?

Michael schrieb:
> Bei so relativ einfachen Codes hatte ich noch kein Sinn gesehn zu
> Simulieren.

Jetzt siehst du den Sinn :-)
Eine mutige Aussage als Newbie ...

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


Angehängte Dateien:

Lesenswert?

Michael schrieb:
> Hab hier mal einen Code für die RS232 Schnittstelle geschrieben.
Hast du nicht... :-o
Das habe ich!
http://www.lothar-miller.de/s9y/categories/42-RS232
Fällt dir ein prominentes Beispiel aus der neueren Zeit ein, bei dem das 
mit dem "habe ich selber geschrieben" auch schief ging?

> Bei so relativ einfachen Codes hatte ich noch kein Sinn gesehn zu
> Simulieren.
LOL. Wenn der Code
1. einfach ist, und
2. von dir geschrieben,
dann hast du damit kein Problem. Ich hatte auf jeden Fall keins.

> Naja muss ich mal schauen wie man simuliert.
Zum Beispiel auf meiner HP passt die simple Stimulidatei (eine richtige 
Testbench ist das noch nicht, weil nichts geprüft wird) hier im Anhang.
Viel Spass damit.

von Johann (Gast)


Lesenswert?

Du solltest den Code noch mal überdenken. Ich finde er is viel zu 
umständlich gemacht.

Zudem solltest Du unbedingt mal über bessere Namen nachdenken, die 
eindeutiger sind. Ich habe den Code mal überflogen und bin nicht 
wirklich schlau daraus geworden.

Wenn ich das richtig verstanden habe dann willst Du ein RS232 
Sende-Module schreiben. Dieses Modul benötigt einen TX_INPUT_BUFFER von 
z.B. 8 Bit Datenbreite. Zudem benötigt man ein Flag das dem Anwender 
zeigt das das Sende-Module nicht beschäftige ist. Hier würde ich ein 
TX_BUSY_FLAG benutzen. Zudem muss das Module wissen das neue Daten in 
den TX_Input Buffer geschrieben wurden. Hierzu eignet sich z.B. ein 
NEW_TX_DATA.

Jetzt muss man eine Flankenerkennung für das Signal NEW_TX_DATA 
programmieren. Somit wird die Datenausgabe nur einmal gestartet. Wenn 
eine Flanke erkannt wurde, dann wird der TX_INPUT_BUFFER in den 
TX_TRANSMIT_BUFFER geschrieben.

Dabei ist zu beachten das TX_TRANSMIT_BUFFER aus 10 Bits besteht. Das 
MSB ist 0 und das LSB ist 1. Dies entspricht dem Start und Stop-Bit. 
Diese beiden werden nie überschrieben sondern nur die 8 Datenbits.

Jetzt muss der TX_TRANSMIT_BUFFER seriell über RS232_TX ausgegeben 
werden. Dies wird erreicht indem man das MSB vom TX_TRANSMIT_BUFFER an 
RS232_TX anlegt. Anschließend wird TX_TRANSMIT_BUFFER immer nach links 
geschoben. In dieser Zeit muss natürlich das TX_BUSY_FLAG gesetzt sein. 
Nachdem alle Daten seriell ausgegeben wurde muss man einen Reset-Pulse 
erzeugen der alles wieder in den Urzustand setzt.

von baudi (Gast)


Lesenswert?

Der Code ist um etwa 85 % zu lang!

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


Lesenswert?

baudi schrieb:
> Der Code ist um etwa 85 % zu lang!
Lass sehen. Machs kürzer. Aber genauso generisch.
;-)
Als Ausgangsbasis darfst du gerne die hier nehmen:
http://www.lothar-miller.de/s9y/categories/49-RS232-IO
Die ist nur noch halb so lang...

Johann schrieb:
> Wenn ich das richtig verstanden habe dann willst Du ein RS232
> Sende-Module schreiben.
Er braucht eine normale SIO mit Senden+Empfangen. Nur das it dem Senden 
klappt noch nicht so richtig (das liegt aber nicht am Code).

> Zudem solltest Du unbedingt mal über bessere Namen nachdenken, die
> eindeutiger sind.
Welcher der Namen ist grob fahrlässig falsch oder gar irreführend?
> Ich habe den Code mal überflogen
> und bin nicht wirklich schlau daraus geworden.
:-D

> Jetzt muss man eine Flankenerkennung für das Signal NEW_TX_DATA
> programmieren.
1
      if (TX_Start='1' and txstart='0') then -- steigende Flanke, los gehts
Na sowas...

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.