Hallo,
ich habe eine Frage bezüglich State-Machines in VHDL. Ich habe diese
bisher immer mittels If/Elsif realisiert, also ungefähr so:
process(clk)
begin
...
if state = idle then
-- Do something
elsif state = calc then
-- Do something
elsif state = finish then
-- Do something
else
-- Do something
end if;
...
end process;
Nun habe ich im Internet fast kein anderes Beispiel gefunden, indem die
State-Machine ebenfalls mit If/Elsif-Statements aufgebaut ist. In nahezu
allen Beispielen werden stattdessen Case-Statements verwenden, also so:
process(clk)
begin
...
case state is
when idle =>
-- Do something
when calc =>
-- Do something
when finish =>
-- Do something
when other =>
-- Do something
end case;
...
end process;
Auch wenn ich es mir eigentlich nicht vorstellen kann, gibt es zwischen
den beiden Realisierungen irgendwelche Unterschiede? Bietet die
Realisierung mit dem Case-Statement evtl. irgendwelche Vorteile bei der
Synthetisierung? Oder wird Case aufgrund der besseren Lesbarkeit einfach
häufiger verwendet?
Vielen Dank im Voraus,
Marc
Streng genommen, deine if/elsif Kaskade wird zu einer Mux Kette
synthetisiert. Die if/elsif Kette gibt auch eine Priorisierung vor. Die
boolsche Optimierung ist allerdings meistens in der Lage die wahre
Intention zu erkennen und flacht das ganze wieder aus, muss aber nicht
sein. Wenn die Optimierung nicht klappt ist deine Logik langsamer.
Deine Case Lösung wird zu einem einzigen N -> 1 Multiplexer
synthestisiert (Natürlich eine kleinere Kaskade wenn N zu breit ist)
wobei N die Anzahl der States ist. d.h. Die Logik hier ist schneller.
Von der Simulation, die Case wird natürlich schneller Simulieren auch
wenn du den Unterschied wahrscheinlich gar nicht merkst auf einem
schnellen PC.
Wenn du eine Analogie in C suchst, if/elsif muss ggfs bis zum letzten
else durchlaufen werden. Case ist ein Table-Jump mit Index, wobei STATE
der Index ist.
Adrian Bergmann schrieb:> Synthetisier beide Varianten mal und such nach den Unterschieden im> RTL-Schaltbild, dann wird dir bestimmt klar, warum man das mit einem> case macht.
Und was dann letztlich tatsächlich herauskommt sieht man erst am
Ressourcenverbrauch und im Technologieschaltplan.
Ganz wichtig ist meist, dass für alle States eine Aktion erfolgt (hier
durch else bzw. others). Ansonsten baust Du Dir unbeabsichtigt
Latches ein, die dein Synchrones Design durcheinander bringen.
Beim if ist die Gefahr eines Fehlers viel größer, da hier ganz schnell
mal eine andere Variable reingefrickelt wird ("elseif state2 = finish"
oder "AND X = ready") wodurch dann das gleiche Problem auftritt.
Wenn ein case passt, dann sollte man es auch verwenden. Die Lesbarkeit
wird enorm erhöht, da ich sofort weiss, dass in diesem Block nur state
die maßgebliche Eingangsvariable ist.
Benutzt man das Case-Konstrukt, ist die Mux-Struktur vorgegeben, und man
kann eigentlich nichts falsch machen.
Benutzt man das If-Konstrukt, kann im Idealfall eine Mux-Struktur
resultieren, muss aber nicht. Falls man es dann wirklich so hinkriegt,
dass man viele Priorisierungen hat, erhöht das direkt die Anzahl
Logic-Levels zwischen den Registern. Dies wiederum ist böse, wenn man
Mühe hat das Timing zu zu kriegen...
Marc schrieb:> wird Case aufgrund der besseren Lesbarkeit einfach häufiger verwendet?
Eher wegen der geringeren Fehlerträchtigkeit. Denn sowas geht mit einem
if zufällig problemlos:
Vielen Dank für die vielen und ausführlichen Antworten! Der Unterschied
zwichen den zwei Methoden ist dann doch größer als ich vermutet hatte.
In Zukunft werde ich, wann immer es geht, auch das Case-Statement für
den Bau meiner FSMs verwenden.
Noch ein Punkt zum Thema Fehlerträchtigkeit, ein case muss immer alle
möglichen Werte abdecken. Es ist im Gegensatz zum if/elsif/... nicht
möglich, einen Zustand zu vergessen.
Außer man ist faul und fasst alle Zustände, in denen nichts oder das
selbe zu tun ist, in einem "when others" zusammen. Dann ist man aber
auch selbst schuld.
Andreas B. schrieb:> Außer man ist faul und fasst alle Zustände, in denen nichts oder das> selbe zu tun ist, in einem "when others" zusammen.
Oder man führt aus Gewohnheit einen "when others" Pfad ein, wo es gar
keine "others" mehr gibt. Wenn ich solchen VHDL-Code vors Auge bekomme,
dann ist das für mich dann immer ein Warnsignal mit Ausrufezeichen:
http://www.lothar-miller.de/s9y/categories/25-when-others