www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Anfängerfrage: Übertragung starten


Autor: M. P. (warranty)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute,
bin noch ein VHDL Anfänger und habe -wie ihr euch wohl denken könnt- 
eine Frage.

Und zwar bastel ich gerade am Code um Seriell Daten vom FPGA zum PC zu 
senden. Also ein UART über RS-232 Schnittstelle. Das ganze hab ich in 
einen process gepackt dieser hat in seiner sensivity list den clock (50 
Mhz) und einen Reset. Der process ist wie ein Zustandsautomat aufgebaut 
und funktioniert im soweit auch ganz anständig. Die Bits werden jeweils 
für 2600 durchläufe gehalten, also eine Bitrate von 19200.

Nun will ich aber nur senden wenn ein neues Byte zum senden ankommt, und 
dann auch nur einmal. Das heißt nur wenn tx_start high wird. In die 
sensivity list kann ichs ja nicht reinpacken. Und nur mit der if 
Überprüfung kommt mir das ganze nicht sehr elegant vor.

Hat jemand einen Tipp wie man das elegant und sauber bewerkstelligt?
uart: process(clk, clr)
begin 

if clr = '1' then 
  (...)
elsif (clk'event and clk = '1') then 
  case UART_Status is 
    when idle =>  -- Es wird gewartet bis tx_start high wird
      if (tx_start = '1') then
        tx_data <= data;
        UART_Status <= start;
      else
        UART_Status <= idle;
      end if;
      
    when start => -- Startbit senden
    (...)
    when hold => -- Hält das Datenbit für eine bestimmte Zeit 
    (...)  
    when next => -- nächstes Datenbit
    (...)  
    when parity => -- Parity bit senden
    (...)
    when stop => -- Stop Bit senden
    (...)
  end case; 
end if; 
end process uart; 

Schonmal im Voraus Danke für alle konstruktiven Antworten.
Marc

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Marc P. (warranty)

>und funktioniert im soweit auch ganz anständig. Die Bits werden jeweils
>für 2600 durchläufe gehalten, also eine Bitrate von 19200.

Hoffentlich mit clock enable, siehe Taktung FPGA/CPLD

>sensivity list kann ichs ja nicht reinpacken. Und nur mit der if
>Überprüfung kommt mir das ganze nicht sehr elegant vor.

Warum? Genau so macht man das.

MfG
Falk

Autor: M. P. (warranty)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Brunner schrieb:
>>und funktioniert im soweit auch ganz anständig. Die Bits werden jeweils
>>für 2600 durchläufe gehalten, also eine Bitrate von 19200.
>
> Hoffentlich mit clock enable, siehe Taktung FPGA/CPLD

Naja die 50 Mhz sind Systemtakt!. Sorry aber ich hab mich glaub nicht 
deutlich genug ausgedrückt. Diser process wird mit 50 Mhz getrieben. Die 
zählschleifen für das halten der bits befinden sich in den jeweiligen 
case anweisungen. Ich glaube du meinst, dass ich einen eigenen dafür 
habe, oder?

Falk Brunner schrieb:
>>sensivity list kann ichs ja nicht reinpacken. Und nur mit der if
>>Überprüfung kommt mir das ganze nicht sehr elegant vor.
>
> Warum? Genau so macht man das.

Naja also sollte ich mir in einer Variable merken ob das letzte bit 
schon gesendet wurde, und erst wieder die data einlesen bzw. die 
variable rücksetzen wenn tx_start low geworden ist, zb. so:
uart: process(clk, clr)
variable x: boolean:= false;
begin 

if clr = '1' then 
  (...)
elsif (clk'event and clk = '1') then 
  case UART_Status is 
    when idle =>  -- Es wird gewartet bis tx_start high wird
      if (tx_start = '1') then
        if not x then  -- wenn x true, dann wurde das byte schon ausgegeben
        UART_Status <= start;
        end if;
      else
        x := false;
        tx_data <= data;
        UART_Status <= idle;
      end if;
      
    when start => -- Startbit senden, counter löschen, Parity Bit berechnen
      x := true;
(...)
(...)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marc P. schrieb:
> Naja also sollte ich mir in einer Variable merken ob das letzte bit
> schon gesendet wurde, und erst wieder die data einlesen bzw. die
> variable rücksetzen wenn tx_start low geworden ist, zb. so:
So ein Handshake wäre auch meine bevorzugte Methode, aber die 
Implementierung ist viel einfacher:
uart: process(clk, clr)
begin 

if clr = '1' then 
  (...)
elsif (clk'event and clk = '1') then 
  case UART_Status is 
    when idle =>  -- Es wird gewartet bis tx_start high wird
      if (tx_start = '1') then
        tx_data <= data;
        UART_Status <= start;  --<<<< das brauchst du nicht wenn sich UART_Status sowieso nicht ändert....
      else
        UART_Status <= idle;
      end if;
      
    when start => -- Startbit senden
    (...)
    when hold => -- Hält das Datenbit für eine bestimmte Zeit 
    (...)  
    when next => -- nächstes Datenbit
    (...)  
    when parity => -- Parity bit senden
    (...)
    when stop => -- Stop Bit senden
    (...)
    when check_start =>
      if (tx_start = '0') then --<<<< warten, bis tx_start wieder inaktiv
        UART_Status <= idle;
      end if;
  end case; 
end if; 
end process uart;

BTW:
Du hast eine recht aufwendige Implementierung über eine FSM. Lade doch 
einfach den kompletten Frame incl. Start,Daten und Stopbit in ein 
Schieberegister und takte das Bit für Bit raus. So etwa: 
http://www.lothar-miller.de/s9y/categories/42-RS232

Das mit dem (vermutlich) asynchronen clr ist unschön und 
wahrscheinlich unnötig...

Autor: René D. (Firma: www.dossmatik.de) (dose)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe einen Transmitter mit einer State Machine, die wiederum einen 
Multiplexer füttert und so die Bitreihenfolge erzeugt wird. Diese 
Implementierung ist entspechend deiner Anfrage.

8N1 bedeutet:
8 Datenbit
No Parity
1 Stoppbit

Wenn du unbedingt ein Paritybit brauchst, dann hänge der State machine 
einen Zustand hinten dran.


Ich sehe gerade.
Der Vergleich   "if tick_counter=tick then" ist vom Typ her nicht ganz 
in Ordnung. Es hatte bei mir funktioniert. Sauberer wäre beide Operanden 
vom gleichem Typ.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ René D.
entity Uart_8N1_TX is
 --50MHz/115200=434
 --for other system clock cycle or baudrate
 --tick is  to adapted
generic (tick: integer :=434);
:

Lass doch den Synthesizer rechnen:
entity Uart_8N1_TX is
generic (tick: integer := 50000000/115200 ); -- clock frequency / baudrate 
:

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

Bewertung
0 lesenswert
nicht lesenswert
Lass doch den Synthesizer rechnen:

Ja das ist noch besser.


Noch besser wäre
generic( baudrate: integer:=115200;
         clk_freq: integer:=50E6);

und damit rechnen.


Wie kritisch findest du den Vergleich mit den Typen integer und 
unsigned?



Man braucht eine Sammlung von primitiven Elementen. Dafür müsste es eine 
IEEE library geben. So erfindet jeder das Rad neu.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.