Forum: FPGA, VHDL & Co. UART-Transmitter in VHDL


von Volker D. (volker_d)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche einen UART-Transmitter in VHDL zu beschreiben. Dazu habe 
ich ein Modul "Baudratengenerator" beschrieben der mit einer Frequenz 
von 9600Hz das nächste Datenbit an txd anlegen soll. Desweiteren habe 
ich ein Modul "Transmitter" beschrieben, der letzlich den 
UART-Transmitter realisieren soll und dabei den Baudratengenerator 
benutzt. Allerdings gibt mir die Synthese einen Fehler aus, da txd an 
den Baudratengenerator gebunden und den Transmitter gebunden ist. Wie 
kann ich das beheben? Rein logisch müsste mein Code funktionieren. Siehe 
dazu die Anhänge.

Im folgenden der Code für den Baudratengenerator:
1
entity Baudratengenerator is
2
    Port ( clk : in  STD_LOGIC;
3
           rst : in  STD_LOGIC;
4
           tick : out  STD_LOGIC);
5
end Baudratengenerator;
6
7
architecture Behavioral of Baudratengenerator is
8
signal counter : integer;
9
begin
10
  P1: Process(clk, rst)
11
  begin
12
    if clk'event and clk = '1' then
13
      if rst = '1' then
14
        tick <= '0';
15
        counter <= 0;
16
      else
17
        counter <= counter + 1;
18
        if counter = 5208 then
19
          tick <= '1';
20
          counter <= 0;
21
        else 
22
          tick <= '0';
23
        end if;
24
      end if;
25
    end if;
26
  end Process;
27
end Behavioral;
und hier der Code für den Transmitter
1
entity Transmitter is
2
    Port ( din : in  std_logic_vector (7 downto 0);
3
           send : in  STD_LOGIC;
4
           clk : in  STD_LOGIC;
5
           rst : in  STD_LOGIC;
6
           txd : out  STD_LOGIC);
7
end Transmitter;
8
9
architecture Behavioral of Transmitter is
10
  component Baudratengenerator is
11
    port ( clk : in std_logic;
12
         rst : in std_logic;
13
         tick : out std_logic);
14
  end component;
15
  signal gesendet : boolean:= false;
16
  signal bitcounter : integer:= 0;
17
  type STATE_T is (Warte, Sende); --Aufzählungstyp
18
  signal state : STATE_T;        --Zustandssignal
19
begin
20
ba: Baudratengenerator port map(clk=>clk, rst=>rst, tick=>txd);
21
22
FSM : process (din, send, clk, rst) is
23
begin
24
  if rst = '1' then
25
    state <= Warte;
26
  elsif clk'event and clk = '1' then
27
    case state is
28
      when Warte =>
29
        if send = '1' then --Transition "Taster gedrückt"
30
          state <= Sende;
31
        end if;
32
      when Sende =>
33
        if bitcounter = 0 then
34
          txd <= '0';  --start bit
35
        end if;
36
        if bitcounter < 8 then
37
          txd <= din(bitcounter); --Daten nacheinander an txd anlegen
38
        else
39
          txd <= '1'; --stopp bit
40
          gesendet <= true;  --Transition "Zeichen gesendet"
41
          bitcounter <= 0;
42
        end if;
43
        if gesendet = true then
44
          state <= Warte;
45
          gesendet <= false;
46
        end if;
47
      end case;
48
  end if;
49
end process;
50
end architecture;

dabei bin ich mir sicher, den Baudratengenerator richtig beschrieben zu 
haben und auch richtig im Transmitter verwendet zu haben, da es ja 
eigentlich keine andere Möglichkeit gibt.

Ich hoffe mir kann jemand weiterhelfen.
Vielen Dank im voraus.

Grüße, Volker

von Lattice User (Gast)


Lesenswert?

Volker D. schrieb:
>
> richtig im Transmitter verwendet zu haben, da es ja
> eigentlich keine andere Möglichkeit gibt.
>

Nein hast du nicht richtig verwendet, und es gibt immer mehere 
Möglichkeiten.

Da es wohl eine Hausaufgabe ist, nur ein kurzer Tipp: Lern mal wozu 
Clockenables da sind.

von Volker D. (volker_d)


Lesenswert?

ist denn die Einbindung über die Port map korrekt? Clockenable gibt mir 
ja eigentlich nur an, wann clock auf 1 ist.

von Volker D. (volker_d)


Lesenswert?

ich galube, ich weiß jetzt, was ich falsch gemacht habe. Im Transmitter 
selber, wird der Baudratengenerator gar nicht eingebunden, sondern nur 
der Transmitter beschrieben. Das heißt also, dass beim Transmitter die 
Component Baudratengenerator und die dazugehörige Port map entfernt 
wird. In einem dritten VHDL-Modul, was ich dann z.B. UART nennen kann, 
wird der Transmitter und der Baudratengenerator über die Port maps 
verbunden und gegebenenfalls ein Signal zum verdrahten eingeführt. Bin 
ich damit auf dem richtigen Weg?

von Schlumpf (Gast)


Lesenswert?

Die Synthese hat schon recht, wenn sie meckert.
Was wolltest du erreichen? Einen "tick", der vom Baudratengenerator 
kommt und ein "txd", welches das eigentliche Datum darstellt.
Soweit ist der Gedanke korrekt. Aber was würde passieren, wenn du für 
den Baudratengenerator und den eigentlichen Sender zwei reale Bauelemnte 
hättest und deren Ausgänge, so wie du es gemacht hast, einfach 
zusammenschaltest?

Richtig: Das kann nicht gehen! Sagt der eine "1" und der andere "0", 
dann hättest du einen Kurzschluss. Und genau das erkennt die Synthese 
und meckert (zurecht)

Es kann immer nur einen geben (wie beim Highlander), der direkt auf ein 
Signal treibt.

Was du eigentlich brauchst, ist eine Art Steuereingang für den 
Transmitter, über den der Baudratengenerator ihm sagt: "so, jetzt bitte 
nächstes Bit ausgeben" und der Transmitter muss dann so geschrieben 
werden, dass er immer brav wartet, bis er vom Baudratengenerator die 
Erlaubnis bekommt, das nächste Bit zu senden.

von Schlumpf (Gast)


Lesenswert?

Volker D. schrieb:
> Bin ich damit auf dem richtigen Weg?

Exakt! ;-)

von Volker D. (volker_d)


Lesenswert?

danke für die Antwort. Die Erklärung klingt logisch (einen Kurzschluss 
möchte ich natürlich nicht beschreiben). Ich versuch es dann erst mal 
weiter und wenn weitere Probleme auftreten meld ich mich wieder.

Grüße, Volker

von Volker D. (Gast)


Lesenswert?

hallo,

ich denke, ich habe den UART-Transmitter jetzt richtig beschrieben. Den 
Baudratengenerator habe ich so gelassen, wie in meinem ersten Post. Im 
folgenden der überarbeitete Transmitter und die Gesamtschaltung. Ich 
würd mich freuen, wenn jemand schauen könnte, ob die Codes so korrekt 
sind.

Transmitter:
1
entity Transmitter is
2
    Port ( din : in  std_logic_vector (7 downto 0);
3
           send : in  STD_LOGIC;
4
           clk : in  STD_LOGIC;
5
           rst : in  STD_LOGIC;
6
           txd : out  STD_LOGIC);
7
end Transmitter;
8
9
architecture Behavioral of Transmitter is
10
  signal gesendet : boolean:= false;
11
  signal bitcounter : integer:= 0;
12
  type STATE_T is (Warte, Sende); --Aufzählungstyp
13
  signal state : STATE_T;        --Zustandssignal
14
begin
15
16
FSM : process (din, send, clk, rst) is
17
begin
18
  if rst = '1' then
19
    state <= Warte;
20
    bitcounter <= 0;
21
  elsif clk'event and clk = '1' then
22
    case state is
23
      when Warte =>
24
        gesendet <= false;
25
        if send = '1' then --Transition "Taster gedrückt"
26
          state <= Sende;
27
        end if;
28
      when Sende =>
29
        if bitcounter = 0 then
30
          txd <= '0';  --start bit
31
        elsif bitcounter < 9 then
32
          txd <= din(bitcounter - 1); --Daten nacheinander an txd anlegen
33
        elsif bitcounter = 9 then
34
          txd <= '1'; --stopp bit
35
          gesendet <= true;  --Transition "Zeichen gesendet"
36
        end if;
37
        bitcounter <= bitcounter + 1;
38
        if gesendet = true then
39
          bitcounter <= 0;
40
          state <= Warte;
41
        end if;
42
      end case;
43
  end if;
44
end process;
45
end architecture;

und die Gesamtschaltung:
1
entity UART_Transmitter is
2
    Port ( din : in  std_logic_vector (7 downto 0);
3
           send : in  STD_LOGIC;
4
           clk : in  STD_LOGIC;
5
           rst : in  STD_LOGIC;
6
           txd : out  STD_LOGIC;
7
           tick : out  STD_LOGIC);
8
end UART_Transmitter;
9
10
architecture Behavioral of UART_Transmitter is
11
component Baudratengenerator is
12
  port ( clk : in std_logic;
13
       rst : in std_logic;
14
       tick : out std_logic);
15
end component;
16
17
component Transmitter is
18
  port ( din : in std_logic_vector (7 downto 0);
19
       send : in std_logic;
20
       clk : in std_logic;
21
       rst : in std_logic;
22
       txd : out std_logic);
23
end component;
24
25
signal sw : std_logic;
26
27
begin
28
tick <= sw;
29
30
ba : Baudratengenerator port map (clk=>clk, rst=>rst, tick=>sw);
31
tr : Transmitter port map (din=>din, send=>send, clk=>sw, rst=>rst, txd=>txd);
32
33
end Behavioral;

vielen Dank im voraus.

Grüße, Volker

von Volker D. (Gast)


Angehängte Dateien:

Lesenswert?

im Anhang noch die Gesamtschaltung. Hatte ich vorhin vergessen.

Grüße

von bko (Gast)


Lesenswert?

In der Sensivity-Liste brauchts nur clk und rst.
>FSM : process (din, send, clk, rst) is
FSM : process ( clk, rst) is

Und hier machst du einen asyncronen Reset,
>FSM : process (din, send, clk, rst) is
>begin
>  if rst = '1' then
Wenn das Signal "rst" eine asyncrone Quelle hat (z.B.: Taster)
das sollte man "rst" einsyncronisieren:
Beitrag "Detailfrage Reset"
sonst sind hier "manchmal gehts nicht" vorprogrammiert.

Und wenn das Ziel ein FPGA ist dann auch mal
 Xilinx- WP272 und den Rest von oben durchlesen.

Und hier vermute ich einen abgeleiteten Takt:
>ba : Baudratengenerator port map (clk=>clk, rst=>rst, tick=>sw);
>tr : Transmitter port map (din=>din, send=>send, clk=>*sw*, rst=>rst, >txd=>txd);

Da Zitiere ich das  Lothar Miller-Postulat:
"Ein Design (insbesondere ein Anfängerdesign) hat genau 1 Takt, der 
immer
auf dieselbe Flanke aktiv ist."
Beitrag "Re: Fehler durch Signalabgreifen"

Besser ists mit einem clock-enable zu arbeiten, hier mit Beispiel:
http://www.mikrocontroller.net/articles/Taktung_FPGA/CPLD

von Duke Scarring (Gast)


Lesenswert?

Volker D. schrieb:
> Ich
> würd mich freuen, wenn jemand schauen könnte, ob die Codes so korrekt
> sind.
Wenn Du noch eine Testbench dazu machst, schau ich mir das Ganze mal im 
Simulator an.

Duke

von Uwe (Gast)


Lesenswert?

Naja man sampled aber bei der Asynchronen Schnittstelle zwischen der 
positiven und der negativen Taktflanke also in der mite eines Taktes. 
Deshalb solle die Taktfrequenz schon mndestens Doppelt so hoch sein.
Moderne und alte UARTs arbeiten normalerweise mit 16fach höheren Takt.
Da kann man dann auch noch sowas wie ne Fehlererkennung einbauen wie nen 
Equivalent oder der vier mittleren Pegel.

von Volker D. (Gast)


Lesenswert?

Danke an alle die geholfen. Die Aufgabe habe ich korrekt gelöst (habe 
ich gestern vorgestellt).Grüße, Volker

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


Lesenswert?

Volker D. schrieb:
> Die Aufgabe habe ich korrekt gelöst
Ich hätte da (mit sehr hoher Wahrscheinlichkeit) einen grundlegenden 
Denkfehler gefunden:
Volker D. schrieb:
>         if counter = 5208 then
Dir ist schon klar, dass dein Zähler hier die Frequenz um 5209 teilt 
(und nicht um 5208, was einen kleineren Fehler in der Baudrate 
darstellen würde)?

Logisch macht das hier den Kohl nicht fett, aber was, wenn deine 
Taktfrequenz 96kHz gewesen wäre? Dann würde es schon was ausmachen, ob 
du durch 10 oder durch 11 teilst...

Uwe schrieb:
> Naja man sampled aber bei der Asynchronen Schnittstelle zwischen der
> positiven und der negativen Taktflanke also in der mite eines Taktes.
Naja, das betrifft aber nur den Empfänger. Der hier beschriebene 
Sender kann von einem Oversampling nicht profitieren...

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.