Hallo zusammen,
ich hätte mal eine kleine Verständnisfrage:
Ich lege einen neuen Typ fest, welcher sagen wir nur 6 Werte annehmen
kann. Alle Zustände werden anschließend in einem CASE abgefragt.
Benötige ich am Ende des CASE noch ein WHEN others? Ich stelle mir das
immer so vor, dass ich um 6 Werte zu kodieren 3 Bit benötige. Mit 3 Bit
kann ich aber natürlich 8 verschiedene Zustände darstellen. Damit
erfasse ich bei meinem CASE zwar alle definierten Zustände, aber nicht
die beiden "undefinierten" Zustände, welche durch die 3 Bit noch
theoretisch möglich wären. Deshalb füge ich am Ende derzeit immer noch
ein WHEN others ein "um auf Nummer sicher zu gehen". Ist das unnötig
oder kann ich mir dadurch unter Umständen sogar Probleme einfangen?
Zum besseren Verständis vielleicht noch ein bisschen Code:
1
-- ...
2
typeperiodis(period1,period2,period3,period4,period5,period6);-- 6 verschiedene Zustände benötigten 3 Bit. Mit 3 Bit wären aber 8 Zustände möglich...
3
signalperiodX:period;
4
-- ...
5
CASEperiodXIS
6
WHENperiod1=>
7
-- ...
8
WHENperiod2=>
9
-- ...
10
WHENperiod3=>
11
-- ...
12
WHENperiod4=>
13
-- ...
14
WHENperiod5=>
15
-- ...
16
WHENperiod6=>
17
-- ...
18
WHENothers=>-- notwendig??? Alle definierten Zustände bereits abgefragt, aber nicht alle mit 3 Bit theoretisch möglichen Zustände...
Wenn Du der FSM sagst, was sie bei einem ungültigen Zustand tun soll,
gewinnst Du prinzipiell ein wenig Sicherheit hinzu. Ob das notwendig
ist... who knows. Allerdings wird die Synthese im Allgemeinen erkennen,
dass Du alle gültigen Fälle auscodiert hast und den 'when others" Zweig
wegoptimieren (siehe verlinkten Artikel von Lothar Miller.) Wenn es
dann wirklich mal zu einem falschen Zustand kommt, reagiert das Design
indeterministisch. Das kannst Du verhindern, indem Du in Deinem Beispiel
nur 5 Zustände auscodierst und den letzten in den others-Zweig packst.
Der gilt dann für Zustand 6 und alle ungültigen Zustände.
Andererseits, wenn es Dein Design schafft, in einem ungültigen Zustand
zu landen, dann gibt es sowieso irgendwo ein Problem, dass Du dringend
beseitigen solltest (Temperatur, Strahlung, falsche Timingconstraints
etc).
Vancouver schrieb:> Das kannst Du verhindern, indem Du in Deinem Beispiel nur 5 Zustände> auscodierst und den letzten in den others-Zweig packst. Der gilt dann> für Zustand 6 und alle ungültigen Zustände.
Obacht! Das ist eine Fehlannahme!
Der Synthesizer wird sich auch im "when others" Pfad niemals um
ungültige Zustände scheren. Und so ist es dann im Fehlerfall eher so,
dass kurioserweise 2 Zustände "aktiv" sind:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Eine OneHot-FSM mit 6 Flipflops wie sie für die Aufgabe des TO nötig
wäre, könnte also z.B. auch 5 "aktive" Zustände haben und käme trotzdem
nicht in den "when others" Zweig.
> Andererseits, wenn es Dein Design schafft, in einem ungültigen Zustand> zu landen, dann gibt es sowieso irgendwo ein Problem, dass Du dringend> beseitigen solltest (Temperatur, Strahlung, falsche Timingconstraints> etc).
Das beliebteste Problem weiterhin: asynchrone Signalübergabe
> Obacht! Das ist eine Fehlannahme! [...]
Interessant, das ist bei den einzelnen Synthesetools anscheinend
unterschiedlich. Du verwendest xst bzw. Vivado-Synthese, nehme ich an?
Ich habe diesen Fall vor einigen Jahren (2012?) mal für die
Synopsys-Synthese untersucht: Es kam heraus, das im when-others-Zweig
die invertierte Or-Verknüpfung der Zustände aus den anderen Zweigen
ausgewertet wird. Da sind die ungültigen Zustände dann automatisch mit
dabei. Ich muss mal ausprobieren, wie das bei aktuellen Versionen
gemacht wird.
Wie verhält sich Xilinx, wenn man allen möglichen Zuständen aus dem
Zustandsraum eine Namen gibt (die Anzahl der Zustände wäre dann immer
2**n), und die ungültigen Zustände nirgendwo benutzt?
Nachtrag: Wenn allen benötigten Zuständen einen Namen gegeben wird,
diese zwar nicht explizit benutzt, aber in der CASE Abfrage dann unter
"others => null" zusammengefasst werden, scheint dieser Teil nicht
automatisch wegoptimiert zu werden.
Vancouver schrieb:> Wie verhält sich Xilinx, wenn man allen möglichen Zuständen aus dem> Zustandsraum eine Namen gibt (die Anzahl der Zustände wäre dann immer> 2**n)
Zu einer Binärcodierung musst du die Toolchain aber dann zwingen. Wenn
du ihr die freie Wahl lässt, dann kommt evtl. eine OneHot-Codierung
heraus...
> und die ungültigen Zustände nirgendwo benutzt?
Das wird nach einer Info wegoptimiert.
Dominik schrieb:> Nachtrag: Wenn allen benötigten Zuständen einen Namen gegeben wird,> diese zwar nicht explizit benutzt, aber in der CASE Abfrage dann unter> "others => null" zusammengefasst werden, scheint dieser Teil nicht> automatisch wegoptimiert zu werden.
Das darf er ja nicht, denn das wäre ja, wie wenn du sagst: "Alle
Personen bis 1,40 links, alle Personen zwischen 1,41 und 1,70 Mitte und
der Rest rechts" und du machst keinen Weg nach rechts...
Wenn du aber sagst: "Alle Personen bis 1,40 links, alle Personen
zwischen 1,41 und 1,70 Mitte, alle ab 1,71 nach rechts und der Rest
bleibt hier bei mir stehen". Dann ist die Anweisung für "den Rest"
unnötig...
> Nachtrag: Wenn allen benötigten Zuständen einen Namen gegeben wird,> diese zwar nicht explizit benutzt, aber in der CASE Abfrage dann unter> "others => null" zusammengefasst werden, scheint dieser Teil nicht> automatisch wegoptimiert zu werden.
Wenn du aber 5 Zustände hast (und dafür binär codiert durch 3 Bit 8
Möglichkeiten "reservierst") und 3 davon explizit verwendest, dann wird
der Synthesizer für den "when others" Fall nur die beiden fehlenden
Zustände berücksichtigen. Nicht aber die 3 undefinierten...
Vancouver schrieb:> Ich habe diesen Fall vor einigen Jahren (2012?) mal für die> Synopsys-Synthese untersucht: Es kam heraus, das im when-others-Zweig> die invertierte Or-Verknüpfung der Zustände aus den anderen Zweigen> ausgewertet wird. Da sind die ungültigen Zustände dann automatisch mit> dabei. Ich muss mal ausprobieren, wie das bei aktuellen Versionen> gemacht wird.
So eine "Safe-FSM" hilft aber leider gar nichts, denn sie läuft trotzdem
nicht zuverlässig bzw. korrekt weiter, sondern nimmt nach einem Fehler
den Weg über den "others" Pfad...
Ein paar Gedanken dazu im
Beitrag "Re: VHDL - 'Warnung' vom Synthesetool (Synplify) unverständlich"
> So eine "Safe-FSM" hilft aber leider gar nichts, denn sie läuft trotzdem> nicht zuverlässig bzw. korrekt weiter, sondern nimmt nach einem Fehler> den Weg über den "others" Pfad...
Wenn die FSM einmal - auf welche Weise auch immer - in einem ungültigen
Zustand gelandet ist, dann findet sie über den others-Zweig wieder in
einen definierten gültigen Zustand, mehr will man ja erstmal garnicht.
Dieses Ereignis muss dann entsprechend behandelt werden, aber FSM ist
erstmal wieder benutzbar.
Dass die FSM überhaupt in den ungültigen Zustand gelangt, wird dadurch
nicht vermieden. Insbesondere undefinerte Transitionen durch asynchrone
Events - also letzlich Setup-Verletzungen wie in Deinem Besipiel
(http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html),
lassen sich damit nicht ausbügeln.
Vancouver schrieb:> Wenn die FSM einmal - auf welche Weise auch immer - in einem ungültigen> Zustand gelandet ist, dann findet sie über den others-Zweig wieder in> einen definierten gültigen Zustand, mehr will man ja erstmal garnicht.
Es gibt üblicherweise keinen ungültigen Zustand, in dem sich eine FSM
komplett "verhakt". Sie hüpft dann entweder sofort wieder in einen
"gültigen" Zustand, oder sie tigert über ein paar undefinierte Zustände
zu einem "gültigen" Zustand. "Gültig" in Anführungszeichen, weil der
Zustand zwar deiniert ist, nicht aber der Weg, wie sie dorthin gekommen
ist.
Und oft hüpft die FSM auch mal eben vom einen gültigen Zustand in einen
anderen ebenfalls "gültigen" Zustand. Allerdings eben nicht in den
korrekten. Und macht dann dort irgendwie weiter. Das ist mindestens
gleich schlimm, wie wenn sie komplett raus tappt...
Lothar M. schrieb:> Sie hüpft dann entweder sofort wieder in einen> "gültigen" Zustand, oder sie tigert über ein paar undefinierte Zustände> zu einem "gültigen" Zustand.
ja, richtig, und diese Spielchen kann man unterbinden, indem man die
undefinierten Zustände abfängt.
Das Gleiche macht man üblicherwiese mit Zählern. Angenommen, Du hast
einen 8-Bit-Zähler, der bis 211 zählen und dann wieder auf Null springen
soll. Wenn Du in der Abbruchbedingung auf Gleichheit prüfst, also
if (counter=X"D3") ...
dann gibt es ein Problem, wenn der Zähler einmal durch einen Fehler z.B.
auf 220 springt. Dann würde er nämlich bis zum Überlauf
durchmarschieren. Prüfst Du auf ">=", dann hast Du den Zähler im
nächsten Takt wieder eingefangen.
---------------
CASE / WHEN
---------------
Ist eigentlich nicht so schwer.
Wenn du dir nicht sicher bist das du alle Zustände erfasst hast in der
vorgegebenen größe, setzt du WHEN others.
Wenn nicht, können unnötige Latche enstehen die ein unvorhersehbares
geschehen verursachen können bei nicht Ausschöpfung der Zustände.
Kann ich bei mir immer gut beobachten im RTL Viewer.
Gruss