Forum: FPGA, VHDL & Co. Probleme bei Vivado Tutorial mit State Machine


von Daniel P. (daniel2345)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich mache aktuell das Xilinx Tutorial HDL Design using Vivado.
Ich bin bei Lab10 "Finite State Machines" angekommen.
Jedoch scheitere ich schon an der Aufgabe 1-1.
Ich soll eine Mealy State machine mit 3 processen machen.
Allerdings bekomme ich das angezeigte Timing Diagramm nicht hin, sondern 
bin immer um eine Clock Periode verzögert.
Ohne State Machine bekomme ich das ohne Probleme gelöst.
Hat jemand einen Vorschlag wie ich meine Code verändern könnte damit das 
klappt. Außerdem weiß ich auch nicht was ich in den 3. Process 
reinschreiben soll.

Danke und Gruß
Daniel

von Achim S. (Gast)


Lesenswert?

Das ist ja mal eine lustige FSM. Du zählst zwar die Zustände S0..S2 
durch. Aber dein Ausgangssignal hängt überhaupt nicht von der FSM ab - 
das wird alleine über Count erzeugt.

Du musst dich entscheiden, was deine FSM sein soll und was deinen 
aktuellen Zustand festlegt (state oder count).

Daniel P. schrieb:
> Allerdings bekomme ich das angezeigte Timing Diagramm nicht hin, sondern
> bin immer um eine Clock Periode verzögert.

Weil du die Zuweisung des Ausgangssignals LED0 innerhalb des  getakteten 
Prozesses machst. Dann brauchst du einen Takt um count zu erhöhen. Und 
im folgenden Taktzyklus wird LED0 in Abhängigkeit vom neuen Wert von 
count gesetzt.

Daniel P. schrieb:
> Außerdem weiß ich auch nicht was ich in den 3. Process
> reinschreiben soll.

Die Ausgangslogik. Die sollte laut Tutorial kombinatorisch arbeiten 
(also ohne Takt), und aus dem aktuellen Zustand und den momentanen 
Werten des Eingangs die Ausgangssignale erzeugen. Da dieser Prozess ohne 
Takt läuft, werden die Ausgänge "sofort" auf den neuen Wert gehen, nicht 
erst einen Takt später.

Ich kann übrigens nicht erkennen, wie dein Code zu dem in Aufgabe 1-1 
gefragten Sequence detector passen soll. Vielleicht fängst du zum 
Entwurf lieber mal mit einem Zustandsfolgediagramm an, ehe du den 
VHDL-Code schreibst.

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


Lesenswert?

Daniel P. schrieb:
> ich mache aktuell das Xilinx Tutorial HDL Design using Vivado.
1
use ieee.numeric_std.all;
2
use IEEE.std_logic_unsigned.all;
Never ever both together!
Die numeric_std hat alles, was du brauchst, um dir später mal ein gutes 
Einkommen zu sichern.
Siehe dazu den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete" und darin 
den Beitrag "Re: IEEE.STD_LOGIC_ARITH.ALL obsolete" samt der darin 
befindlichen Links einfach mal ganz genau und ausführlich an.

> Ohne State Machine bekomme ich das ohne Probleme gelöst.
In deinem Code ist ein Zähler. Ein einfacher Zähler ist bereits eine der 
einfachsten Formen einer FSM. Ein vor sich hintoggelndes Bit wäre 
biologisch gesehen die "Einzellervariante" einer FSM.

> Allerdings bekomme ich das angezeigte Timing Diagramm nicht hin, sondern
> bin immer um eine Clock Periode verzögert.
Weil du mit deinem Zähler keinen Mealy-Automaten gemacht hast. Was du 
hier gerade lernst, ist ein wichtiges Kapitel beim Design von synchronen 
Schaltwerken und nennt sich "Latency": scheinbar reagiert alles um 1 
Takt "verspätet".

Achim S. schrieb:
> Vielleicht fängst du zum Entwurf lieber mal mit einem
> Zustandsfolgediagramm an, ehe du den VHDL-Code schreibst.
Und wenn du dann den Code mal durch den Synthesizer durchbekommst, dann 
siehst du dir mal den RTL-Schaltplan an, ob der Synthesizer deine 
Beschreibung der gewünschten Hardware so verstanden hat, wie du es 
meinstest.

von Daniel P. (daniel2345)


Lesenswert?

Hallo zusammen,

danke für die Antworten, ich werde das ausprobieren.

Gruß Daniel

von Daniel P. (daniel2345)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

nun habe ich eine Lösung gefunden, die das gewünschte Verhalten zeigt.

Jedoch habe ich jetzt 15 Zustände was mir sehr viel vorkommt.

Anbei auch noch der RTL Schaltplan.

Nochmals vielen Dank für die Hilfe.

Gruß Daniel

von Achim S. (Gast)


Lesenswert?

Daniel P. schrieb:
> Jedoch habe ich jetzt 15 Zustände was mir sehr viel vorkommt.

mir auch. ich verstehe die Aufgabe so, dass du 3 Zustände brauchst. 
s0,wenn die Zahl der einsen 3*n ist, s1 wenn die Zahl 3*n+1 ist, s2 wenn 
die Zahl 3*n+2 ist. immer wenn eine neue 1 ankommt gehst du einen 
Zustand weiter.

von Daniel P. (daniel2345)


Angehängte Dateien:

Lesenswert?

Achim S. schrieb:
> Daniel P. schrieb:
>> Jedoch habe ich jetzt 15 Zustände was mir sehr viel vorkommt.
>
> mir auch. ich verstehe die Aufgabe so, dass du 3 Zustände brauchst.
> s0,wenn die Zahl der einsen 3*n ist, s1 wenn die Zahl 3*n+1 ist, s2 wenn
> die Zahl 3*n+2 ist. immer wenn eine neue 1 ankommt gehst du einen
> Zustand weiter.

Hallo, das mit den 3 Zuständen ist eine gute Idee, allerdings bekomme 
ich es einfach nicht hin.
Ich verstehe einfach nicht, wie und in welchem process ich den counter 
hochzählen soll.
Der counter soll ja nur hochzählen wenn der Eingang ain = '1' ist.

Ich habe jetzt eine Version, die folgende Fehler hat:
- wenn ain von 0 auf 1 wechselt, zählt der counter einmal zusätzlich 
nach oben
- wenn der counter auf seinem maximalwert (15) ist der Ausgang 1, beim 
nächsten Wert von 0 müsste der Ausgang wieder 1 sein, dies ist jedoch 
nicht der Fall. Hierzu müsste zweimal hintereinander der Zustand S0 
aktiv sein.

Dies ist die erste Aufgabe von diesem Blatt und ich scheitere bereits 
kläglich.
Hat noch jemand einen Tipp.

Danke und Gruß
Daniel

von Achim S. (Gast)


Lesenswert?

Daniel P. schrieb:
> Ich verstehe einfach nicht, wie und in welchem process ich den counter
> hochzählen soll.
> Der counter soll ja nur hochzählen wenn der Eingang ain = '1' ist.

Er soll hochzählen, wenn eine Taktflanke kommt und der Eingang ain='1' 
ist. Genau so, wie dein State um eins weitergehen soll, wenn eine 
Taktflanke kommt und der Eingang ain='1' ist. Beides (FSM und counter) 
sollen sich also gleich verhalten. Von daher kannst du es auch in deinen 
Prozessen gleich handhaben.

So etwas wie
"count_int <= count_int;"
darst du nicht in einen kombinatorischen Prozess packen. Es würde dazu 
führen, dass count_int ständig weiter hochzählt, so schnell wie die 
Schaltung im FPGA es hergibt (eine sog. kombinatorische Schleife). Und 
es würde nicht nur viel zu schnell zählen, sondern auch mit Sicherheit 
falsch zählen. Die Simulation zeigt dir das nicht an, weil count_int 
nicht in der Sensitivitätsliste steht (obwohl es innerhalb des Prozesses 
abgefragt wird). Aber spätestens bei der Synthese dürfte dir das 
aufstoßen.

Eine solche Anweisung darfst du entweder innerhalb eines getakteten 
Prozesses verwenden - also mit Abfrage der Taktflanke. Dann zählt 
count_int immer mit der Taktflanke hoch.

Oder du bleibst bei deiner Aufteilung der Prozesse und schreibst im 
synch_process (taktflankengesteuert):
   count <= count_next;
und im next_state_decode Prozess (kombinatorisch):
   count_next <= count +1;

Daniel P. schrieb:
> Hierzu müsste zweimal hintereinander der Zustand S0
> aktiv sein.

Du hast 4 States genutzt, nicht 3. Lass das idle weg, starte gleich mit 
S0 und mach Gebrauch davon, dass du auch bei Null Einsen schon den Wert 
1 ausgeben darfst.

Daniel P. schrieb:
> Dies ist die erste Aufgabe von diesem Blatt und ich scheitere bereits
> kläglich.
> Hat noch jemand einen Tipp.

Aller Anfang ist schwer, lass dich einfach nicht zu schnell entmutigen.

Und: im Tutorial geht es speziell um einen Mealy-Automat mit drei 
Prozessen. Es ist sicher nicht verkehrt, das einmal grundsätzlich 
durchzugehen. Im normalen Alltag verwende ich persönlich lieber die 
Ein-Prozess Schreibweise. Dort muss zwar erst mal der Groschen fallen, 
dass man denselben Signalname für Ausgang wie für Eingang des Flip-Flops 
verwendet (beim Abfragen und beim Zuweisen). Dafür wird aber nach meinem 
persönlichen Geschmack die Beschreibung innerhalb eines einzelnen 
Prozesses übersichtlicher als mit drei Prozessen. (Andere sehen das 
anders und arbeiten lieber mit mehreren Prozessen zur Beschreibung einer 
FSM. Kennenlernen sollte man alle Varianten einmal...)

von Daniel P. (daniel2345)


Angehängte Dateien:

Lesenswert?

Achim S. schrieb:
> So etwas wie
> "count_int <= count_int;"
> darst du nicht in einen kombinatorischen Prozess packen. Es würde dazu
> führen, dass count_int ständig weiter hochzählt, so schnell wie die
> Schaltung im FPGA es hergibt (eine sog. kombinatorische Schleife). Und
> es würde nicht nur viel zu schnell zählen, sondern auch mit Sicherheit
> falsch zählen. Die Simulation zeigt dir das nicht an, weil count_int
> nicht in der Sensitivitätsliste steht (obwohl es innerhalb des Prozesses
> abgefragt wird). Aber spätestens bei der Synthese dürfte dir das
> aufstoßen.

Sehr interessant. Ich dachte immer ein Prozess wird nur ausgeführt, wenn 
ein Signal aus der Sensitivitätsliste seinen Zustand ändert?

Abgesehen davon das "count_int <= count_int;" nicht sehr clever und 
nützlich ist, würde das wirklich hochzählen, es wird doch der selbe wert 
zugewiesen?


> Aller Anfang ist schwer, lass dich einfach nicht zu schnell entmutigen.
Danke, ich denke jetzt habe ich es verstanden.
Ich habe die Aufgabe mit Ein-Prozess, Zwei-Prozess und drei-Prozess 
Schreibweise gemacht.

In der Zwei und drei Prozess Schreibweise musste ich aber das signal 
"count_int" in die Sensitivitätsliste stecken um beim Zählerstand 15 zu 
erreichen, das erneut der state S0 aufgerufen wird.
Ist das so guter Stil, oder sollten in die Sensitivitätsliste nur 
Eingangssignale?

Muss nach dem Zählerstand 15, der Zählerstand 0 zugewiesen werden, wenn 
das Signal std_logic_vector(3 downto 0) ist?
In der Simulation klappt das Wunderbar ohne Zuweisung, aber wie verhält 
sich das in Hardware?


> Und: im Tutorial geht es speziell um einen Mealy-Automat mit drei
> Prozessen. Es ist sicher nicht verkehrt, das einmal grundsätzlich
> durchzugehen. Im normalen Alltag verwende ich persönlich lieber die
> Ein-Prozess Schreibweise. Dort muss zwar erst mal der Groschen fallen,
> dass man denselben Signalname für Ausgang wie für Eingang des Flip-Flops
> verwendet (beim Abfragen und beim Zuweisen). Dafür wird aber nach meinem
> persönlichen Geschmack die Beschreibung innerhalb eines einzelnen
> Prozesses übersichtlicher als mit drei Prozessen. (Andere sehen das
> anders und arbeiten lieber mit mehreren Prozessen zur Beschreibung einer
> FSM. Kennenlernen sollte man alle Varianten einmal...)

Bei der Ein-Prozess Schreibweise habe ich das Problem das dass 
Ausgangssignal immer um einen Takt verzögert ausgegeben wird, im 
gegensatz zu den anderen beiden Schreibweisen. So wie ich das verstehe, 
geht das aber nicht anders, da bei dieser Schreibweise nur der clk 
entscheidend und kein kombinatorischer Prozess vorhanden ist.
Ich habe versucht statt mit einem Signal mit einer Variable zu arbeiten, 
aber dadurch kann ich das Ausgangssignal nur um einen halben Takt 
verschieben.
Sind meine Gedanken korrekt oder bekomme ich auch mit der Ein Prozess 
Schreibweise das selbe Ergebnis, wie mit den anderen beiden?

Mit freundlichen Grüßen
Daniel

von Achim S. (Gast)


Lesenswert?

Daniel P. schrieb:
> Sehr interessant. Ich dachte immer ein Prozess wird nur ausgeführt, wenn
> ein Signal aus der Sensitivitätsliste seinen Zustand ändert?

Im Simulator ist das der Fall. Aber in der Synthese (wenn die 
Logikschaltung wirklich in eine FPGA gepackt werden soll) gibt das eine 
kombinatorische Schleife. Viele Synthesetools ignorieren die 
Sensitivitätsliste ganz.

Daniel P. schrieb:
> Abgesehen davon das "count_int <= count_int;" nicht sehr clever und
> nützlich ist, würde das wirklich hochzählen, es wird doch der selbe wert
> zugewiesen?

Tschuldingung, war mein Fehler. Ich hatte die falsche Stelle zitiert.
count_int <= count_int;
kannst du problemlos zuweisen. Aber du hattest in deinem Code auch
count_int <= count_int + 1;
Und das gibt die kombinatorische Schleife.

Daniel P. schrieb:
> Ist das so guter Stil, oder sollten in die Sensitivitätsliste nur
> Eingangssignale?

In die Sensitivätsliste müssen alle Signale rein, deren Änderung zu 
einer Signaländerung im Prozess führen kann. Ein Signal zu viel in der 
Sensititätsliste zu haben, kann keinen Schaden anrichten. Wenn ein 
Signal fehlt kann das dagegen kritisch sein.

Daniel P. schrieb:
> Bei der Ein-Prozess Schreibweise habe ich das Problem das dass
> Ausgangssignal immer um einen Takt verzögert ausgegeben wird, im
> gegensatz zu den anderen beiden Schreibweisen. So wie ich das verstehe,
> geht das aber nicht anders, da bei dieser Schreibweise nur der clk
> entscheidend und kein kombinatorischer Prozess vorhanden ist.

Das ist richtig: wenn alles innerhalb des getakteten Prozesses steht, 
dann wird tatsächlich die Zuweisung des Ausgangs erst mit der nächsten 
Taktflanke wirksam. Bei dem kombinatorischen Prozess für die 
Ausgabefunktion musst du dagegen nicht auf die Taktflanke warten, bis 
der Ausgang den neuen Wert annimmt.

Daniel P. schrieb:
> Sind meine Gedanken korrekt oder bekomme ich auch mit der Ein Prozess
> Schreibweise das selbe Ergebnis, wie mit den anderen beiden?

Na ja, du könnste die Ausgabefunktion auch ohne Prozess schreiben 
(einfach als nebenläufige Zuweisung). Das ist aber kein wesentlicher 
Unterschied dazu, die Ausgabefunktion in einen eigenen kombinatorischen 
Prozess zu verpacken - womit es dann wieder keine 
Ein-Prozess-Schreibweise wäre.

von Daniel P. (daniel2345)


Lesenswert?

Hallo Achim,

vielen Dank für deine Hilfe.
Ich denke ich habe jetzt die FSM grundsätzlich verstanden.

Gruß Daniel

von Daniel P. (daniel2345)


Angehängte Dateien:

Lesenswert?

Hallo,

eigentlich dachte ich, ich hätte die FSM verstanden.
Doch bei der Aufgabe 2.1 von Übung 10, gibt es schon die nächsten 
Probleme.
Hier soll ich einen sequence detector mit einer Moore state machine 
bauen.
Der Ausgang soll zu Beginn 0 sein und dann konstant bleiben, bis eine 
bestimmte Eingangssequenz auftaucht.

Simulation:
In der Simulation bekomme ich das richtige Ergebnis, wenn ich das Signal 
"yout_int" aus der Sensitivtiätsliste von output_decode entferne.
Wenn das Signal "yout_int" in der Sensitivtiätsliste ist, dann erscheint 
die Fehlermeldung "FATAL_ERROR: Iteration limit 10000 is reached. 
Possible zero delay oscillation detected where simulation time can not 
advance. Please check your source code. Note that the iteration limit 
can be changed using switch -maxdeltaid. Time: 65 ns  Iteration: 10000"
Der Fehler erscheint genau dann wenn das Signal "yout_int" das erste mal 
'1' werden würde.


Synthese:
Der Test mit dem FPGA Board ist leider fehlgeschlagen. Der Ausgang 
reagiert zwar richtig auf die Eingangssequenz, bleibt jedoch nicht 
konstant bis die nächste Eingangssequenz kommt.

Gruß Daniel

von Achim S. (Gast)


Lesenswert?

Daniel P. schrieb:
> Wenn das Signal "yout_int" in der Sensitivtiätsliste ist, dann erscheint
> die Fehlermeldung "FATAL_ERROR: Iteration limit 10000 is reached.
> Possible zero delay oscillation detected where simulation time can not
> advance. Please check your source code.

du hast halt schon wieder eine kombinatorische Schleife:

yout_int <= not yout_int;

von Daniel P. (daniel2345)


Angehängte Dateien:

Lesenswert?

Achim S. schrieb:
> Daniel P. schrieb:
>> Wenn das Signal "yout_int" in der Sensitivtiätsliste ist, dann erscheint
>> die Fehlermeldung "FATAL_ERROR: Iteration limit 10000 is reached.
>> Possible zero delay oscillation detected where simulation time can not
>> advance. Please check your source code.
>
> du hast halt schon wieder eine kombinatorische Schleife:
>
> yout_int <= not yout_int;

Ok, verstanden. Dann ist "count_int <= count_int" keine kombinatorische 
Schleife weil das Signal nicht verändert wird, oder?

Ich habe jetzt einen anderen Ansatz gewählt, der sowohl in der 
Simulation wie auch im FPGA funktioniert, jedoch habe ich die Vermutung 
das ich eine Mealy Automaten verwendet habe.

Könntest du mir bitte einen Tipp geben, wie ich diese Aufgabe mit Moore 
Automaten mit 3 Prozessen lösen kann?
Vor allem das toggeln des Ausgangs und das speichern des Ausgangs bis 
zur nächsten Eingangssequenz bereiten mir Probleme.

Danke und Gruß
Daniel

von Achim S. (Gast)


Lesenswert?

Daniel P. schrieb:
> Könntest du mir bitte einen Tipp geben, wie ich diese Aufgabe mit Moore
> Automaten mit 3 Prozessen lösen kann?

ich zeig dir stattdessen mal, wie ich die geforderte Sequence-detection 
wahrscheinlich machen würde:
1
psequence: process(clk)
2
begin
3
   if rising_edge(clk) then 
4
  ainold<=ain;
5
  if (ainold&ain)="0100" then yout_int <= '0'; end if;
6
  if (ainold&ain)="1100" then yout_int <= '1'; end if;
7
  if (ainold&ain)="1000" then yout_int <= not yout_int; end if;    
8
   end if;
9
  
10
end process;
11
12
yout <= yout_int;

Ich denke, das sollte das geforderte Ergebnis bringen. Ist natürlich 
leider kein Moore-Automat mit drei Prozessen. Um es gemäß 
Tutoriums-Vorgabe zu beschreiben, müsste ich mich etwas mehr Zeit 
investieren.

von Achim S. (Gast)


Lesenswert?

Hmm: die Einrückung im if rising_edge(clk) then ... end if ist etwas 
hässlich geworden. Aber ich hoffe, man erkennt trotzdem, wie es gemeint 
ist.

von Daniel P. (daniel2345)


Lesenswert?

Achim S. schrieb:
> Hmm: die Einrückung im if rising_edge(clk) then ... end if ist etwas
> hässlich geworden. Aber ich hoffe, man erkennt trotzdem, wie es gemeint
> ist.

Ja danke, man erkennt wunderbar was gemeint ist.
Das ist mit Sicherheit eine elegantere Lösung und auch sehr viel 
einfacher.

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.