Forum: FPGA, VHDL & Co. Defaultwert bei State Machines


von Heiner (Gast)


Lesenswert?

Hallo,

bei einer State Machine sollten ja den Ausgangssignalen immer 
Defaultwerte zugewiesen werden, damit das Signal nicht in jedem case 
zugewiesen werden muss. In der Uni habe ich gelernt als Default immer 
Null zu verwenden.

In der Praxis sehe ich jedoch häufig, dass dem Ausgangssignal der 
"vorherige" Wert, also dessen Register zugewiesen wird. Den Vorteil sehe 
ich bei der zweiten Variante darin, das z. B. ein Counter oder ein 
Zustandsregister ihren Wert über mehrere Takte beibehalten. Nachteil 
ist, das z. B. ein "write enable" Signal nicht vergessen werden darf in 
den nachfolgenden Zuständen wieder zurückzusetzen.

Ich verwende daher immer eine Kombination aus beiden: Defaultwert 
entspricht dem alten Wert und nur Schreibsignale setze ich auf Null.

Meine Frage ist daher, welche Variante ist besser? Was verwendet ihr und 
warum? Ist es für die Synthese besser, wenn man den alten Wert als 
Default verwendet und nicht Null?

Danke!
Heiner

von Schlumpf (Gast)


Lesenswert?

Hallo!

"DIE" Antwort wird es auf deine Frage vermutlich nicht geben.

Signale können kombinatorisch aus dem State gebildet werden. Dann 
brauchen sie auf jeden Fall einen "Default"-Wert, da sonst ein Latch 
entsteht.

Sind die Signale registered, ist es vermutlich eher philosophischer 
Natur, was man bevorzugt.

Ich halte es immer so:
Wenn ein Signal nur in einem State oder für einen Takt einen bestimmten 
Wert annehmen soll, dann mache ich das über einen Default-Wert.
Soll das Signal über mehrere Takte oder States anliegen, dann setze ich 
das Signal im State X und setzte es im State Y zurück.

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


Lesenswert?

Meine Konterfrage lautet hier: verwendest du die Ein- oder die 
Zwei-Prozess Schreibweise?

Denn in der Zwei-Prozess Schreibweise darf im kombinatorischen Teil nie 
der "vorherige" Wert zugewiesen werden. Das gäbe ein Latch...

von Lina (Gast)


Lesenswert?

> Meine Konterfrage lautet hier: verwendest du die Ein- oder die
> Zwei-Prozess Schreibweise?

Man sollte nicht vergessen, dass es neben diesen beiden älteren 
Schreibweisen auch noch die etwas neuere Schreibweise mit einem Prozess 
für die State Übergänge und dem kombinarorischem Teil außerhalb eines 
Prozesses gibt.
Beispiel:
1
foo <= "101 when state = idle else
2
       "010" when state = ramrd else
3
       "011" when state = ramwr else
4
       "110";
Das ist am übersichtlichen, wenn es darum geht zu sehen, welcher Ausgang 
in welchem state welchen Wert hat und man vergisst auch nie den default 
Wert. :-)

von Bogomil (Gast)


Lesenswert?

Das finde ich eigentlich auch am Übersichtlichsten, danke für den Tipp!

von Heiner (Gast)


Lesenswert?

Schlumpf schrieb:
> Wenn ein Signal nur in einem State oder für einen Takt einen bestimmten
> Wert annehmen soll, dann mache ich das über einen Default-Wert.
> Soll das Signal über mehrere Takte oder States anliegen, dann setze ich
> das Signal im State X und setzte es im State Y zurück.

Also so wie ich es auch mache. ;-)

Lothar Miller schrieb:
> Meine Konterfrage lautet hier: verwendest du die Ein- oder die
> Zwei-Prozess Schreibweise?

Ich habe einen kombinatorischen und einen sequentiellen Prozess. Im 
kombinatorischen Prozess weise ich dem kombinatorischen Signal das 
zughörige registrierte Signal zu.

Lina schrieb:
> Man sollte nicht vergessen, dass es neben diesen beiden älteren
> Schreibweisen auch noch die etwas neuere Schreibweise mit einem Prozess
> für die State Übergänge und dem kombinarorischem Teil außerhalb eines
> Prozesses gibt.

Auch eine interessante Idee, aber ich denke meine State Machines würden 
dadurch unübersichtlicher werden...

von Jope (Gast)


Lesenswert?

>Man sollte nicht vergessen, dass es neben diesen beiden älteren
>Schreibweisen auch noch die etwas neuere Schreibweise mit einem Prozess
>für die State Übergänge und dem kombinarorischem Teil außerhalb eines
>Prozesses gibt.
>Beispiel:
>
1
>foo <= "101 when state = idle else
2
>       "010" when state = ramrd else
3
>       "011" when state = ramwr else
4
>       "110";


Was hat das mit "neuerer Schreibweise" zu tun?
Du weist hier einfach einem Signal (foo) kombinatorisch einen Wert zu, 
abhängig vom aktuellen Zustand. Das hat nichts mit dem Unterschied 
zwischen der Ein- und Zweiprozessvariante von Zustandsautomaten zu tun.

von Lina (Gast)


Lesenswert?

Jope schrieb:
> Was hat das mit "neuerer Schreibweise" zu tun?

In der ein- und zwei-Prozess Schreibweise ist die Kombinatorik in einem 
Prozess. Dies ist imho unnötig, da man nur für sequentielle Logik 
Prozesse wirklich braucht. Hier ist dies nicht der Fall, daher 
neue/andere Schreibweise. Ich hoffe, dass beantwortet deine Frage.

von Schlumpf (Gast)


Lesenswert?

Lina schrieb:
> Dies ist imho unnötig, da man nur für sequentielle Logik
> Prozesse wirklich braucht.

Da hast du natürlich recht. Aber es ist ja auch kein Problem, seine 
Kombinatorik in einen Prozess zu "packen".

Mir gefällt es besser, wenn ich auf einen Blick sehe, was in einen State 
passiert.
In deiner Schreibweise sieht man auf einen Blick, welche Werte ein 
Signal zu welchem Zeitpunkt annimmt...

Ob man dann seine Signalzuweisungen nach States "sortiert" dargestellt 
hat, oder, wie in deiner Schreibweise, nach Signalnamen, ist vermutlich 
einfach nur Geschmackssache.

von Karl Könner (Gast)


Lesenswert?

Lina schrieb:
> Jope schrieb:
>> Was hat das mit "neuerer Schreibweise" zu tun?
>
> In der ein- und zwei-Prozess Schreibweise ist die Kombinatorik in einem
> Prozess. Dies ist imho unnötig, da man nur für sequentielle Logik
> Prozesse wirklich braucht. Hier ist dies nicht der Fall, daher
> neue/andere Schreibweise.

Das klingt als ob man das proces konstrukt vermeiden sollte, warum?

von Lina (Gast)


Lesenswert?

> Ob man dann seine Signalzuweisungen nach States "sortiert" dargestellt
> hat, oder, wie in deiner Schreibweise, nach Signalnamen, ist vermutlich
> einfach nur Geschmackssache.
In der Tat. ;)

> Das klingt als ob man das proces konstrukt vermeiden sollte, warum?
Wie das "imho" schon andeutet, ist das alles nur meine persönliche und 
keinesfalls allgemeingültige Meinung. ;) Prozesse erinnern meiner 
Meinung nach einfach zu sehr an prozedurale Programmiersprachen, was 
VHDL ja nun mal nicht ist. Daher finde ich, dass meine Schreibweise 
besser zu programmierbarer Logik passt. :) (In Testbenches oder anderen 
Dingen, die nicht synthetisiert werden sollen ist das natürlich was 
anderes.)

von berndl (Gast)


Lesenswert?

Karl Könner schrieb:
> Das klingt als ob man das proces konstrukt vermeiden sollte, warum?

in dem gezeigten Fall sparst du dir die sensitivity Liste, ein 
riesengrosser Vorteil. Und ein Latch ist auch wesentlich besser zu 
erkennen bzw. zu vermeiden im Vergleich mit einem kombinatorischen 
process(....).

Und die Bildschirme werden ja auch immer breiter, es bleibt ganz gut 
lesbar...

von Jope (Gast)


Lesenswert?

>Ich hoffe, dass beantwortet deine Frage

Nein, da sie rhetorisch war.

Das was Du hier machst, hat nichts mit dem Unterschied zwischen Ein- und 
Zweiprozessvarianten zu tun.

Dieser Unterschied bezieht sich nämlich nur darauf, ob ich:
1. Das "state"-Register in einen getakteten Prozess packe, zusammen mit 
den Zustandsübergangslogik;
2. Oder aber die Zustandsübergangslogik in einen ungetakteten Prozess 
auslagere und in einem separaten, getakteten Prozess das 
"state"-Register update.

Die Ausgangssignale, die mit den jeweiligen Zustände gekoppelt sind, 
kann ich dann kombinatorisch erzeugen (innerhalb und außerhalb von 
Prozessen). Ich mache das auch wie Du wenn es geht außerhalb.

von Lina (Gast)


Lesenswert?

Achso, okay. Zwei-Prozess-Schreibweise impliziert für mich, dass die 
Kombinatorik in einem zweiten Prozess ist. ;) Da dies bei mir (und 
offenbar auch bei dir) nicht der Fall ist, meinte ich, dass es eine 
andere Schreibweise ist. Tut mir leid, dass wir uns da missverstanden 
haben. :)

von Lina (Gast)


Lesenswert?

PS: die Zustandsüberganslogik kann man natürlich auch wunderbar 
außerhalb eines Prozessen machen, wenn man möchte:
1
next_state <= idl when reset = '0' else
2
              rdy when (state = idl or state = done) and tready = '1' else
3
              send_addr when state = rdy and rx_done = '1' else
4
              send_data when state = send_addr else
5
              done when state = send_data else
6
              state;

Ist aber natürlich Geschmackssache und jedem selbst überlassen. ;)

von John D. (Firma: Privat) (doejohn)


Lesenswert?

Lina schrieb:
> PS: die Zustandsüberganslogik kann man natürlich auch wunderbar
> außerhalb eines Prozessen machen, wenn man möchte:
>
>
1
next_state <= idl when reset = '0' else
2
>               rdy when (state = idl or state = done) and tready = '1' 
3
> else
4
>               send_addr when state = rdy and rx_done = '1' else
5
>               send_data when state = send_addr else
6
>               done when state = send_data else
7
>               state;
>
> Ist aber natürlich Geschmackssache und jedem selbst überlassen. ;)

Wird halt bei große und komplexen FSMs sehr schnell sehr 
unübersichtlich. Da hat die Schreibweise mit Process & CASE deutlich 
Vorteile. Man sieht direkt, was in einem State passiert, welche 
Ausgangssignale gesetz werden, welche State-Übergänge möchlich sind. 
Alles auf eine Blick erkenntlich. Ein FSM ist ja meistens die zentralle 
Kontrollinstanz und kontroliert die (Ausgangs-)Signale, daher finde ich 
die zentralle Zuweisung der Signale genau in dem State Case am 
effektivsten. Nimm man an deine FSM kontrolliert 50 Signale, da darf man 
sich dann aus 50 einzelnen Zuweisungen den State raussuchen. Mal davon 
abgesehen, dass obige Schreibweise ganz schnell sehr hässlich aussieht, 
wenn es von einem State nicht nur einen Übergang gibt, sondern viele.

Rein von der Logik betrachtet beschreibt dein Code übrigens einen 
Priority-Encoder, d.h. viele hintereinander geschaltete Multiplexer, 
d.h. längere Signallaufzeiten und eine höheren Logikverbrauch.Ein CASE 
Statement beschreibt lediglich einen MUX. Das büglen heute jedoch alle 
(FPGA-) Synthesizer glatt, intern wird ein CASE synthetisiert.

Gruss,
  JD

von Lina (Gast)


Lesenswert?

Das kannst du so pauschal nicht sagen. Ein Case Statement ist nur dann 
übersichtlich, wenn der Verlauf der FSM recht gradlinig ist und es von 
einem State nur wenige Verzweigungen gibt. Reagiert deine FSM jedoch auf 
Events wird ein Case Statement sehr groß, weil man für jeden State 
einzeln eine if Anfrage auf das Event schreiben muss, was in Viel 
doppeltem Code resultiert. In meiner Schreibweise wäre es nur eine 
Zeile.

Aus der Sicht des FPGAs ist beides nur syntaktischer Zucker. Am Ende 
kommen LUTs bei heraus.

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.