Forum: FPGA, VHDL & Co. [Anfänger] RS232 Modul in VHDL - Kritik erwünscht


von Robert S. (razer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo an alle,

als VHDL Anfänger hatte ich in den letzten Tagen wieder ein Wenig Zeit. 
Ziel war es ein einfaches UART Modul zu entwickeln. Der Source Code 
(UART + Testbench + TCL-Skript zum Starten der Simulation).

Die Simulation funktioniert soweit :) Als Anfänger ist es jedoch nicht 
immer so einfach zu beurteilen, wie "gut" das Design ist, ob grobe 
Fallstricken übersehen wurden oder ob das Design einfach schlecht ist 
;-)

Ich hoffe ihr könnt mir ein paar nützliche Kommentare zu meinem Design 
geben bzw. über konstruktive Kritik würde ich mich sehr freuen.

Danke im Voraus,
lg Robert

: Bearbeitet durch User
von Duke Scarring (Gast)


Lesenswert?

Sieht gut aus.

Mir fällt nur auf, daß Dein Vektor ein Bit zu breit ist:
1
    WIDTH              : integer := 8;
2
...
3
4
 signal rx_data_in : std_logic_vector(WIDTH downto 0) := (others => '0');

Die Exponentenschreibweise hast Du nur mit dem Simulationstool getestet?
1
    CLK_FREQ           : integer := 100e6;
Geth das auch durch die aktuellen Synthesizer?

Wird das Signal rx_busy wirklich benötigt?

Duke

von Robert S. (razer) Benutzerseite


Lesenswert?

Duke Scarring schrieb:
> Mir fällt nur auf, daß Dein Vektor ein Bit zu breit ist:

Nein, dass ist gewollt so. Es wird hier das Stop-Bit mit reingetaktet 
und im letzten State nur mehr 8-bits auf den Ausgangsport.

Duke Scarring schrieb:
> Geth das auch durch die aktuellen Synthesizer?

Funktioniert mit ISE 14.7.

Duke Scarring schrieb:
> Wird das Signal rx_busy wirklich benötigt?

Ja, das stimmt. Das ist eigentlich nicht nötig. Mit rx_ready ist 
eindeutig bestimmt wann ein gültiger Lesezugriff möglich ist.

von greg (Gast)


Lesenswert?

Gibt's einen Grund, warum rx_in drei Bits breit ist? Um eine Flanke zu 
erkennen, reichen doch zwei Bits, oder?

von Robert S. (razer) Benutzerseite


Lesenswert?

greg schrieb:
> Gibt's einen Grund, warum rx_in drei Bits breit ist? Um eine Flanke zu
> erkennen, reichen doch zwei Bits, oder?

Das stimmt eigentlich - Danke!

Was eigentlich noch nicht ganz stimmt ist die Auswertung des Start-Bits. 
Bei fallender Flanke verlässt die Statemachine zwar IDLE, das Start-Bit 
wird aber erst danach gesampelt. Es muss ausgewertet werden, ob das 0 
ist, dann sonst war es nur ein "Wackler" auf der RX-Leitung.

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

> Die Simulation funktioniert soweit :) Als Anfänger ist es jedoch nicht
> immer so einfach zu beurteilen, wie "gut" das Design ist, ob grobe
> Fallstricken übersehen wurden oder ob das Design einfach schlecht ist
> ;-)

Es ist schon mal nicht schlecht als Anfänger.
Du will aber auch etwas Kritik.

Versuche für die Übersichtlichkeit einen Prozesse für die Statemaschine 
und einen oder mehrere Prozesse für das Datenhändling.

das Signal "TX_Start" würde ich "wr" für write nennen. (write ist ein 
reserviertes VHDL Wort).
Das ist dann einfacher auszustauschen wenn du mal den UART gegen einen 
SPI einfach austauschen musst. Dann hast du keine spezielle Signalnamen 
in Top Level Code files.

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

und dann schau dir das Beispiel für die Testbench von Lothar Miller an
Beitrag "Procedure Beispiele"


Erspart dir die Zeiten, einzeln hinzufummeln.

von Lattice User (Gast)


Lesenswert?

Robert S. schrieb:
> greg schrieb:
>> Gibt's einen Grund, warum rx_in drei Bits breit ist? Um eine Flanke zu
>> erkennen, reichen doch zwei Bits, oder?
>
> Das stimmt eigentlich - Danke!
>

Die 3 bits sind schon ok,
1 zur Synchronisation mit der System Clock, WICHTIG
2 zur Flanken Erkennung

Man darf aber nur bit 2,1 abfragen.
1
        -- A start bit detected
2
        if rx_in(rx_in'left downto 1) = "10" then

von greg (Gast)


Lesenswert?

Robert S. schrieb:

> Was eigentlich noch nicht ganz stimmt ist die Auswertung des Start-Bits.
> Bei fallender Flanke verlässt die Statemachine zwar IDLE, das Start-Bit
> wird aber erst danach gesampelt. Es muss ausgewertet werden, ob das 0
> ist, dann sonst war es nur ein "Wackler" auf der RX-Leitung.

Und das nennt man dann Framing Error. Genau das gleiche beim Stopbit, 
wenn es nicht passt. Das musst du aber (IMHO) nicht im Idle-Fall 
anfangen. Wenn ein Framing Error erkannt wird, geht's eben einfach 
wieder zurück zu IDLE. Ein Signal für diesen Fehlerfall wäre vielleicht 
auch interessant.

von greg (Gast)


Lesenswert?

Lattice User schrieb:
> 1 zur Synchronisation mit der System Clock, WICHTIG

Warum eigentlich? Um Glitches zu vermeiden? Spielt das eine Rolle, wenn 
rx nur ein einziges mal pro Zyklus gesampled wird?

von Robert S. (razer) Benutzerseite


Lesenswert?

René D. schrieb:
> Es ist schon mal nicht schlecht als Anfänger.
> Du will aber auch etwas Kritik.

Immer her damit ;-)

René D. schrieb:
> Versuche für die Übersichtlichkeit einen Prozesse für die Statemaschine
> und einen oder mehrere Prozesse für das Datenhändling.

Danke für den Tipp. Soetwas in der Art ist mir auch schon aufgefallen. 
Es mag zwar für diese "kleine" FSM noch gehen. Bei etwas größeren wird 
das wirklich kompliziert. Wie sieht das dann genauer aus? Müsssen diese 
impliziten "Substates" ausgerollt werden? Damit meine ich zB. im State 
STATE_RX die paar if.

René D. schrieb:
> das Signal "TX_Start" würde ich "wr" für write nennen. (write ist ein
> reserviertes VHDL Wort).
> Das ist dann einfacher auszustauschen wenn du mal den UART gegen einen
> SPI einfach austauschen musst. Dann hast du keine spezielle Signalnamen
> in Top Level Code files.

Hmm. Das überzeugt mich mich nicht wirklich. Warum nicht einfach 
tx_start lassen und im Top-Level ein Signal "wr" machen? Wenn zB ein 
UART Modul und ein SPI Modul instanziert wird werden doch automatisch 
solche Namen vergeben...

René D. schrieb:
> und dann schau dir das Beispiel für die Testbench von Lothar Miller an
> Beitrag "Procedure Beispiele"

Danke für den Tipp. Echt cool :)

greg schrieb:
> Und das nennt man dann Framing Error. Genau das gleiche beim Stopbit,
> wenn es nicht passt. Das musst du aber (IMHO) nicht im Idle-Fall
> anfangen. Wenn ein Framing Error erkannt wird, geht's eben einfach
> wieder zurück zu IDLE. Ein Signal für diesen Fehlerfall wäre vielleicht
> auch interessant.

Danke für die Anregungen. Das werde ich gleich mal einbauen.

greg schrieb:
> Warum eigentlich? Um Glitches zu vermeiden? Spielt das eine Rolle, wenn
> rx nur ein einziges mal pro Zyklus gesampled wird?

Daran wäre ich auch gerne interessiert.

lg Robert

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


Lesenswert?

greg schrieb:
> Lattice User schrieb:
>> 1 zur Synchronisation mit der System Clock, WICHTIG
> Warum eigentlich? Um Glitches zu vermeiden?
Nein, um Signalinkonsistenzen im FPGA zu vermeiden
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren:

von Robert S. (razer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich habe einmal mein Design angepasst. Es hat nun eine Framing error 
Detection, bei der Daten mit falschem Start- oder Stopbit verworfen 
werden. Dabei wird der Error Ausgang für einen Zyklus auf 1 gesetzt.

Weiters habe ich die Testbench um eine Procedure erweitert - Danke an 
René und an Lothar!

Der Source dazu ist wieder im Anhang.

lg Robert

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.