www.mikrocontroller.net

Forum: FPGA, VHDL & Co. UART + Xilinx + Altera


Autor: Daniel R. (daniel_r)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich will über einen UART im FPGA mit dem PC kommunizieren, um den FPGA 
steuern zu können.
Ich habe dazu nun erst mal ein kleines Testdesign gebastelt(siehe 
Anhang).
Es soll nach dem Senden von „Start“ alle 3 Sekunden(momentan mit 
Vollgas) „Hallo“ senden, bis man „Stop“ schickt.

Auf meinem Xilinx-FPGA läuft das auch ausgezeichnet.
Allerdings läuft genau dieses Design nicht auf meinem Altera-Board.

Der Receiver scheint zu funktionieren, der Transmitter nicht. Über 
herausgeführte Pins habe ich herausgefunden, dass der Transmitter nicht 
bereit zu sein scheint.

Kann mir jemand ein paar Tips geben, woran so was liegen könnte?
Wäre jemand so nett und würde das Ding schnell auf sein Altera bzw. 
Xilinx Board ziehen und berichten, ob es geht?

9600 Baud
keine Parität
8 Datenbits
1 Stopbit

Eingangstakt sollte 40MHz sein. Sonst muss der Clockteiler im Sender und 
Empfänger Modul dementsprechend umgestellt werden.


Danke schon im Voraus.

Daniel

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau mal auf http://www.fpga4fun.com , da ist ein UART beschrieben der 
sicher auf Altera läuft. Ob der auch mit einem Xilinx FPGA funktioniert, 
weiss ich allerdings nicht.

Gruss Andi

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, es wuerde mich sehr interessieren, wieso die Hardwarebeschreibung 
auf einem Xilinx FPGA funktioniert und auf einem Altera FPGA nicht. Ich 
dachte immer das waere der besondere Vorteil von FPGA's, solange man 
nicht Herstellerspezifische Hardware benutzt. Eine Hardwarebeschreibung 
sollte immer gleich funktionieren oder irre ich mich?

Gruß,
Dirk

Autor: Homer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Seltsam. Ich hätte auch immer gedacht dass ein VHDL-Code auf allen FPGAs 
gleich funktioniert. Ich würde es gerne testen. Habe aber auch nur ein 
Spartan-Board.

Autor: high_speed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel

Ich habe es eben auf einem Cyclone EP1C12F324I7 ausprobiert.
Mit einer Taktrate von 40 MHz hat es nicht funktioniert!!
Nachdem ich in den Quellcode geschaut hatte, habe ich es mit 50MHz
ausprobiert und er spuckte "alloallo" aus.

"Start" und "Stop" funktionieren auch.

Dein Zustandsautomat hängst sich nach dem Reset auf.

Hast du auch darauf geachtet, das unterschiedliche Boards mit 
unterschiedlicher Logik arbeiten. Die Taster kann entweder Low- oder 
High-
Aktiv sein.

MfG
Holger

Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du ALLE signale mit im reset?

Du hast einen Zähler, der nicht auf " >= ", sondern nur auf " = " 
abfragt.
Ich mache an solchen Stellen gerne den Vergleich auf >=.
(if cnt >= 5012 then cnt <= 0; else .......  ..... end if;)
Falls er im reset auf größeren Werten als 5012 landet, kann man den 
Zähler auf diese Weise wieder definiert zurückbringen. Wenn man nur auf 
" = " abfragt zählt er evtl. munter weiter (je nachdem was im else-Zweig 
steht).

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

vielen Dank erst mal an alle für die Antworten.
Vorneweg:
Die UART-Module stammen nicht von mir, sondern hier aus dem Forum.

@Andi:
Thx. Ich schau mir den mal an.

@Dirk:
Das ist richtig, dass eine Hardware-Beschreibung immer gehen sollte, 
egal welcher Hersteller.
Aber hier scheint ein Problem vorzuliegen, da genau das gleiche Design 
auf Xilinx läuft und auf Altera nicht.

@Homer: Könntest Du es bitte auf dem Spartan-Board testen? THX.

@high_speed:
Thx fürs Testen.
Erst mal scheint es ja dann nicht an Xilinx/Altera zu liegen, sondern 
vllt. Am Takt. Vllt. Ist es die größere Abweichung...Bei 50MHz sind es 
ca. 0,6Hz und bei 40MHz sind es 0,8Hz Abweichung von 9600Hz. Kann ich 
mir aber nicht vorstellen.

>>Dein Zustandsautomat hängst sich nach dem Reset auf.
Welchen meinst Du? Der in uart_hello.vhd oder im Sender bzw. Empfänger 
Modul?
Dass es nach einem Reset(mit Taster) nicht mehr geht hab ich gemerkt. 
Muss aber an den Modulen liegen, da in uart_hello.vhd gar kein Reset 
verwendet wird.

Auf Taster Low/High Aktiv habe ich geachtet.


@Rainer:
Das könnte die Ursache sein, dass nach einem Reset mit dem Taster gar 
nix mehr geht... Ich werds probieren.


Daniel

Autor: Axel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich mache an solchen Stellen gerne den Vergleich auf >=.
(if cnt >= 5012 then cnt <= 0; else .......  ..... end if;)

Das ist aber im Regelfall nicht besonders effizient und kann ziemliche 
Gattergräber geben.

Gruss
Axel

Autor: high_speed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel

Auf dem Xilinx-Board hast du wahrscheinlich ein wenig Glück gehabt.
40MHz und 50MHz sind aber schon ein extremer Unterschied.

Der Taktteiler für den UART hat den Wert von 5208, das ergibt bei 40MHz
eine Bitrate von 7680 bit/s, bei 50MHz sind es 9600 bit/s .
if count_clk = 5208 then
count_clk <= 0;
Der Fehler im Reset liegt im Transmitter:
..
signal tx_ready_int : std_logic := '1'; -- initalized to 1 for tx_ready = 1 on start
..
begin
-------------------------------------
-- load tx_ready with rx_ready_int --
-----------------------------------
      tx_ready <= tx_ready_int;
..

Ich habe es jetzt umgeschrieben auf:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity transmitter is
   generic (
      CLK_div_bit   : natural := 5208  -- clock = 50 MHz
   );
   port (
      CLK        : in  std_logic;   -- clock
      nReset     : in  std_logic;   -- asynch reset
      Tx         : out std_logic;   -- transmitter output
      Tx_Data    : in  std_logic_vector(7 downto 0); -- data input
      data_ready : in  std_logic := '1';   -- control signal data ready
      tx_ready    : out std_logic  -- transmitter ready for new data
   );
end transmitter;
  

architecture behavior of transmitter is

   signal sending       : boolean; -- sending mode
   signal sent          : boolean; -- sent mode
   signal count_CLK     : std_logic_vector(12 downto 0); --natural range 0 to 4167; -- clock counter for clock divider
   signal count_bit     : natural range 0 to 10; -- bit counter
   signal enable        : std_logic; -- clock enable for sending mode
   signal data_register : std_logic_vector(7 downto 0); -- for storage of  data input to send

begin

   --------------------------------------------------
   -- clock divider for baudrate generation --
   -- sensitive to clock, asynch reset by received --
   -- receiving mode: generate clock enable --
   -- for wished baudrate --
   --------------------------------------------------

   clock_divider : process (CLK, sent) is
   begin
      if sent then
         count_CLK <= (others => '0');
      elsif CLK'event and CLK = '1' then
         if sending then
            enable <= '0';
            if count_CLK = CLK_div_bit then
               count_CLK <= (others => '0');
            elsif count_CLK = 0 then
               enable <= '1';
               count_CLK <= count_CLK + 1;
            else
               count_CLK <= count_CLK + 1;
            end if;
         end if;
      end if;
   end process clock_divider;

   -----------------------------------------------------------
   -- data storage of input data --
   -- sensitive to clock, asynch reset by reset --
   -- storage data in internal register when data_ready = 1
   -----------------------------------------------------------

   data_storage : process (CLK, nReset, sent) is
   begin
      if nReset = '0' or sent then
         data_register <= (others => '0');
         sending <= false;
      elsif CLK'event and CLK = '1' then
         if data_ready = '1' then
            if not sending then
               data_register <= Tx_Data;
               sending <= true;
            end if;
         end if;
      end if;
   end process data_storage;

   -------------------------------------------------------
   -- send storaged data --
   -- sensitive to clock, asynch reset by reset --
   -- load tx with content of data register from 0 to 9 --
   -- when sending complete : ready for new data --
   -------------------------------------------------------

   data_send : process (CLK, nReset) is
   begin
      if nReset = '0' then
         Tx <= '1';
         count_bit <= 0;
         tx_ready <= '1';              
      elsif CLK'event and CLK = '1' then
         sent <= false;
         if enable = '1' then
            tx_ready <= '0';          
            Tx <= '1';

            case count_bit is
               when 0 =>
                  Tx <= '0';
                  count_bit <= count_bit + 1;

               when 9 =>
                  Tx <= '1';
                  count_bit <= count_bit + 1;

               when 10 =>
                  Tx <= '1';
                  count_bit <= 0;
                  sent <= true;
                  tx_ready <= '1';       

               when others => count_bit <= count_bit + 1;
                  Tx <= data_register(count_bit - 1);
                  
            end case;

         end if;
      end if;
   end process data_send;

end architecture behavior;

MfG
Holger

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

>Auf dem Xilinx-Board hast du wahrscheinlich ein wenig Glück gehabt.
>40MHz und 50MHz sind aber schon ein extremer Unterschied.

>Der Taktteiler für den UART hat den Wert von 5208, das ergibt bei 40MHz
>eine Bitrate von 7680 bit/s, bei 50MHz sind es 9600 bit/s .

Warum Glück? Denkst Du, ich habe den Clockteiler nicht eingestellt?? Das 
habe ich. Bei 50MHz auf 5208, bei 40MHz auf 4167.

Da der Teiler eigentlich Nachkommastellen hat gibt das Abweichungen von 
0,6Hz bzw. 0,8Hz.

Thx für den Code. Ich probiers mal damit.

Daniel

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich mich nicht täusche, dürfte der Code von mir stammen. Was hat 
denn da für ein Fehler am Reset vorgelegen? Ich kann ihn in dem Post 
nicht erkennen... Achso, bei mir hat die UART gefunzt, auf einem V2-250 
und einem S2-300E.

T.M.

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Fehler am Reset war, dass nach dem Betätigen des Testers nix mehr 
gesendet wurde. D.h. der Transmitter war nicht mehr "ready"(da der Reset 
nur auf Deine Module geführt wurde). Ich bin der Sache aber nicht näher 
nachgegangen, da das ja nicht das Hauptproblem ist.

THX übrigens für das Einstellen des UARTs ins Forum.

Daniel

Autor: high_speed (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang habe ich mal eine neue Version angehängt, es muss aber noch
einiges verbessert werden. Es sind noch nicht alle Signale im Reset.

Daniel in deiner Version hatten die Tasten noch nicht richtig 
funktioniert,
weil das Eingangsregister nicht gelöscht wurden. Das mit dem Glück bezog
sich aber nicht unbedingt auf die Taktrate. Manchmal hat man auch nur 
Glück, das die Signale nach der Initialisierung den richtigen Zustand
aufweisen. Wo hast du überhaupt den Taktteiler verändert?

Wenn ich das im Code Lese, befürchte ich, dass du nur den Wertebereich
verändert hast.
 signal count_clk : natural range 0 to 4167;
..
> if count_clk = 5208 then
> count_clk <= 0;

T.M. das war nicht direkt ein Fehler in deinem UART, sondern es liegt am
Zusammenspiel der Zustandsautomaten. Daniels Automat wartet auf eine
steigende Flanke von Tx_ready (umbenannt), welche nach dem Reset nicht 
mehr
kommt und schon hat sich der Automat weggehängt.

MfG
Holger

Autor: Daniel R. (daniel_r)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

vielen Dank für Deine Mühe.

Den Taktteiler habe ich selbstverständlich hier geändert:
if count_clk = 5208 then
count_clk <= 0;

Der Bereich wurde auch angepasst.

Leider kommt bei dieser Version bei mir nur ab und zu mal was:

llllllllllllllllllll HHHHHHHHHHHHHHHHH oooooooooooooo

Irgendwie so was halt.

Die LED reagiert auch nicht auf das Senden von „Start“. Takt und Pins 
stimmen. Am Design hab ich nix geändert außer dass der Reset-Taster 
jetzt high-aktiv ist.

Was auch lustig ist: Auf dem Xilinx-Board (Spartan3 Starter Kit) fängt 
bei Deinem Design plötzlich das obere linke Feld der 7-Segment-Anzeige 
an zu spinnen. Beim Reset is es aus, beim Drücken auf den Senden-Knopf 
is es an.
Ich habe die Pins mehrmals überprüft: Kein einziger Pin der 7-Seg. 
Anzeige kommt im UCF-File vor. Ich bin mir zu 100% sicher. Keine Ahnung, 
was da abgeht.

Hab mein UCF-File mal angehängt. Wäre jemand, der ein Xilinx Spartan3 
Starter Kit hat mal so nett und würde das Design von high_speed 
„Uart_neu.zip“ mal mit meinem constraint-File auf dem Board 
ausprobieren(7-Seg. Anzeigen so lassen, wie sie sind).

Senden-Taster: BTN2
Send_enable-LED: LD7
Reset: BTN3
Transmit_out: LD0

Daniel




Autor: Rainer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel,

ich bin jetzt kein Xilinx/ISE-Spezialist, aber in deinem Toplevel hast 
du ein paar Ports, die in deinem UCF nicht auftauchen. Was macht da ISE?

Bei Altera/Quartus werden unplatzierte Pins dann halt irgendwo 
platziert. Das könnte dann das flackern der 7-Seg.Anzeige erklären.

G
Rainer

Autor: high_speed (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo robodriver

Ich habe im Anhang mal ein Bild von der Top-level entity angehängt.
Die Taster sind bei mir low aktiv, die LEDs high aktiv.
Der Takt vom Oszillator sind 32MHz.
Nach der PLL habe ich dann die 50MHz.

MfG
Holger

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Rainer

Die Pins, die nicht auftauchen hab ich extra draußen gelassen, weil ich 
sie vorerst nicht brauche. Was ISE da macht weiß ich nicht. Ich gehe 
davon aus, dass die gar nicht herausgeführt werden. Wenn doch, bitte 
belehrt mich. Ich weise mal alle Pins zu und schau, obs immer noch 
flackert.

@high_speed

Hmm...ich weiß auch net was da los ist. Mein Takt kommt direkt ausm 
50MHz Quarzoszi. LEDs und Taster high_aktiv. Hab ich geändert....

Daniel


Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

also: wie schon beschrieben läuft uart_neu nicht auf meinem Xilinx 
Board.
Vorhin hab ich es auf dem Altera Board getestet: Läuft per Knopfdruck, 
jedoch wird nicht auf die Eingabe von „Start“ oder „Stop“ reagiert.


Ich kann mir das nicht erklären. Hab alles mehrmals überprüft....


Daniel

Autor: TheMason (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@daniel_r

ich belehre dich dann mal : lasse KEINE pins undefiniert (im ucf).

xilinx legt die pinne irgendwohin. wenn du pech hast und zufällig einen 
pin erwischst der (über einen chip z.b.) auf gnd oder vcc liegt kanns 
knallen.
festgestellt hab ich das selbst mal (ohne das es geknallt hat) das mir 
ein von mir erzeugtes vga-signal auf einmal nicht mehr funktionierte. 
habe eine halbe stunde gebraucht um festzustellen das ich das ucf-file 
nicht in meinem design hatte (nachdem ich das projekt neu aufgesetzt 
hatte). nach dem hinzufügen des ucf-files klappte alles wie gehabt.
also : keine pins undefiniert lassen.

ich finde es persönlich auch ziemlich bedenklich das man da noch 
nichtmal eine warnung (eine fehlermeldung wäre besser) bekommt. gerade 
bei großen designs macht es denke ich sinn.
hingegen verstehe ich nicht, das der fitter (bei xilinx) meckert wenn 
man einen definierten (im ucf) pin nicht verwendet. dann meckert der als 
wenns kein morgen mehr gibt ....
schon merkwürdig, aber vielleicht ist das ein fall für "inverse logik" 
:-)

gruß
rene

Autor: Honey (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@high_speed

ich habe mein altes Altera-Board rausgepackt und dein Code mal 
draufgeladen. Es tut bei mir nicht. Auch die LED geht nicht an, wenn ich 
Start eintippe. Ich habe es mit 50MHZ probiert(mit PLL aus 25MHz).

Autor: high_speed (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel

Was für ein Terminalprogramm benutzt du?
Ich benutze RealTerm (jetzt 1.99.0.34).
http://realterm.sourceforge.net
Wie wird der Takt erzeugt? (Oszillator- und PLL- Daten)
Was für EVA-Boards sind es? Schaltplan?

Mein Design geht von einem Eingangstakt von 50MHz aus.
Für andere Taktraten muss man
generic (
    CLK_div_bit   : natural := 5208; -- clock = 50 MHz
    CLK_div_start : natural := 2604  -- clock = 50 Mhz
);
in uart_hello ändern.

CLK_div_start hat ca. den halben Wert von CLK_div_bit.

Die Steuerbefehle sind "Start" und "Stop" mit großem 'S'.

Die Eingangssignale des VHDL-Design:
CLK: rising edge
nReset: low aktiv
Rx: high aktiv
Knopf: high aktiv

Die Ausgangssignale des VHDL-Design:
Tx: high aktiv
led: high aktiv
data_ctrl: high aktiv
clock_out: high aktiv
tx_ready_out: high aktiv
transmit_out: high aktiv


signal test_signal     : std_logic_vector(1 downto 0); -- Taktteilung 
Senden

Ist erstmal ein Hilfssignal, es soll eine Pause generieren, bis Tx_ready
auf '0' geht, so dass das nächste Zeichen erst bei der nächsten '1' in 
den
Sendepuffer des UART geschrieben wird, ansonsten wird bei der nächsten
steigenden Flanke von CLK schon das nächste Zeichen in den Puffer
geschrieben. In deiner Originalversion wurde nach dem Start:
"Halloalloalloallo".. ausgegeben.
Das karm dadurch zustande, das das 'H' anders behandelt wurde als der 
Rest.

MfG
Holger

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Holger,

ich benutze momentan das Windows-Terminal.

Der Takt wird bei beiden Boards über einen Quarzoszillator(50 MHz bei 
dem Xilinx Board und 40 MHz beim Altera Board) erzeugt. Ich benutze 
keine PLL.

Das Xilinx Board ist ein Spartan3 Starter Kit, das Altera Board gehört 
der Firma, in der mein Vater arbeitet. Ich darf den Schaltplan deswegen 
leider nicht posten. Aber ich kann versichern, dass die Hardware OK ist. 
Das Design, welches auf dem Prom ist benutzt auch die RS232 und 
funktioniert.

Die Generics hab ich selbstverständlich dem Takt angepasst(mehrmals 
überprüft).

Befehle werden mit großem "S" gesendet.

Daniel

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ TheMason

Das is ja echt wissenswert, dass unbenutzte Pins einfach irgendwo hin 
gemappt werden. Danke für die Info. Werde zukünftig alle Pins zuweisen.

Daniel

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert es nun?

Autor: Daniel R. (daniel_r)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein

Autor: high_speed (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel

> .. ich benutze momentan das Windows-Terminal

Ich habe es eben auch mal mit HyperTerminal ausprobiert und es 
funktioniert
genauso gut. Besorge dir trotzdem mal ein anderes Terminal, das
HyperTerminal ist nicht gerade benutzerfreundlich.

Die PLL habe ich jetzt mal rausgenommen und takte direkt mit 32 MHz.

Im Anhang hänge im mal das aktuelle Projekt als Quartus II Archiv an.

MfG
Holger

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.