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


von Daniel R. (daniel_r)


Angehängte Dateien:

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

von Andi (Gast)


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

von Dirk (Gast)


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

von Homer (Gast)


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.

von high_speed (Gast)


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

von Rainer (Gast)


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).

von Daniel R. (daniel_r)


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

von Axel (Gast)


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

von high_speed (Gast)


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 .
1
if count_clk = 5208 then
2
count_clk <= 0;
Der Fehler im Reset liegt im Transmitter:
1
..
2
signal tx_ready_int : std_logic := '1'; -- initalized to 1 for tx_ready = 1 on start
3
..
4
begin
5
-------------------------------------
6
-- load tx_ready with rx_ready_int --
7
-----------------------------------
8
      tx_ready <= tx_ready_int;
9
..

Ich habe es jetzt umgeschrieben auf:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_unsigned.all;
4
5
entity transmitter is
6
   generic (
7
      CLK_div_bit   : natural := 5208  -- clock = 50 MHz
8
   );
9
   port (
10
      CLK        : in  std_logic;   -- clock
11
      nReset     : in  std_logic;   -- asynch reset
12
      Tx         : out std_logic;   -- transmitter output
13
      Tx_Data    : in  std_logic_vector(7 downto 0); -- data input
14
      data_ready : in  std_logic := '1';   -- control signal data ready
15
      tx_ready    : out std_logic  -- transmitter ready for new data
16
   );
17
end transmitter;
18
  
19
20
architecture behavior of transmitter is
21
22
   signal sending       : boolean; -- sending mode
23
   signal sent          : boolean; -- sent mode
24
   signal count_CLK     : std_logic_vector(12 downto 0); --natural range 0 to 4167; -- clock counter for clock divider
25
   signal count_bit     : natural range 0 to 10; -- bit counter
26
   signal enable        : std_logic; -- clock enable for sending mode
27
   signal data_register : std_logic_vector(7 downto 0); -- for storage of  data input to send
28
29
begin
30
31
   --------------------------------------------------
32
   -- clock divider for baudrate generation --
33
   -- sensitive to clock, asynch reset by received --
34
   -- receiving mode: generate clock enable --
35
   -- for wished baudrate --
36
   --------------------------------------------------
37
38
   clock_divider : process (CLK, sent) is
39
   begin
40
      if sent then
41
         count_CLK <= (others => '0');
42
      elsif CLK'event and CLK = '1' then
43
         if sending then
44
            enable <= '0';
45
            if count_CLK = CLK_div_bit then
46
               count_CLK <= (others => '0');
47
            elsif count_CLK = 0 then
48
               enable <= '1';
49
               count_CLK <= count_CLK + 1;
50
            else
51
               count_CLK <= count_CLK + 1;
52
            end if;
53
         end if;
54
      end if;
55
   end process clock_divider;
56
57
   -----------------------------------------------------------
58
   -- data storage of input data --
59
   -- sensitive to clock, asynch reset by reset --
60
   -- storage data in internal register when data_ready = 1
61
   -----------------------------------------------------------
62
63
   data_storage : process (CLK, nReset, sent) is
64
   begin
65
      if nReset = '0' or sent then
66
         data_register <= (others => '0');
67
         sending <= false;
68
      elsif CLK'event and CLK = '1' then
69
         if data_ready = '1' then
70
            if not sending then
71
               data_register <= Tx_Data;
72
               sending <= true;
73
            end if;
74
         end if;
75
      end if;
76
   end process data_storage;
77
78
   -------------------------------------------------------
79
   -- send storaged data --
80
   -- sensitive to clock, asynch reset by reset --
81
   -- load tx with content of data register from 0 to 9 --
82
   -- when sending complete : ready for new data --
83
   -------------------------------------------------------
84
85
   data_send : process (CLK, nReset) is
86
   begin
87
      if nReset = '0' then
88
         Tx <= '1';
89
         count_bit <= 0;
90
         tx_ready <= '1';              
91
      elsif CLK'event and CLK = '1' then
92
         sent <= false;
93
         if enable = '1' then
94
            tx_ready <= '0';          
95
            Tx <= '1';
96
97
            case count_bit is
98
               when 0 =>
99
                  Tx <= '0';
100
                  count_bit <= count_bit + 1;
101
102
               when 9 =>
103
                  Tx <= '1';
104
                  count_bit <= count_bit + 1;
105
106
               when 10 =>
107
                  Tx <= '1';
108
                  count_bit <= 0;
109
                  sent <= true;
110
                  tx_ready <= '1';       
111
112
               when others => count_bit <= count_bit + 1;
113
                  Tx <= data_register(count_bit - 1);
114
                  
115
            end case;
116
117
         end if;
118
      end if;
119
   end process data_send;
120
121
end architecture behavior;

MfG
Holger

von Daniel R. (daniel_r)


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

von T.M. (Gast)


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.

von Daniel R. (daniel_r)


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

von high_speed (Gast)


Angehängte Dateien:

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.
1
 signal count_clk : natural range 0 to 4167;
2
..
3
> if count_clk = 5208 then
4
> 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

von Daniel R. (daniel_r)


Angehängte Dateien:

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




von Rainer (Gast)


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

von high_speed (Gast)


Angehängte Dateien:

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

von Daniel R. (daniel_r)


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


von Daniel R. (daniel_r)


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

von TheMason (Gast)


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

von Honey (Gast)


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).

von high_speed (Gast)


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
1
generic (
2
    CLK_div_bit   : natural := 5208; -- clock = 50 MHz
3
    CLK_div_start : natural := 2604  -- clock = 50 Mhz
4
);
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

von Daniel R. (daniel_r)


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

von Daniel R. (daniel_r)


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

von Dirk (Gast)


Lesenswert?

Funktioniert es nun?

von Daniel R. (daniel_r)


Lesenswert?

nein

von high_speed (Gast)


Angehängte Dateien:

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

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.