VHDL RS232 Spartan 3A

Gast #2259891
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;
Gast #2259922
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"?
Gast #2259934
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.
Gast #2260040
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.
Moderator (Firma: Titel) Persönliche Seite #2260214
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.
Angehängte Dateien:
Gast #2260596
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.
Moderator (Firma: Titel) Persönliche Seite #2260634
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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren