Hallo allerseits,
ich bin gerade dabei, ein paar Sachen fuer die Pruefung morgen nochmal
anzusehen. Dabei fiel mir auf, dass in meinem Skript sinngemaess
folgendes steht:
Neuen Datentyp anlegen:
type dtyp is (aa, ab, ac);
signal a : dtyp;
spaeter in einem Prozess:
case a is
when aa .... ,
when ab .... ,
when ac .... ,
when others => ... ;
end case
Hinter when others wird per Kommentar noch angegeben, dass diese Zeile
unbedingt noetig sei, wenn die Anzahl der Zustaende von 2^n abweiche.
Simulation mit Modelsim und testweises Synthetisieren brachten beim
Fehlen dieser Zeile keinen Fehler und ich kann mir eigentlich auch nicht
vorstellen, dass der Kommentar im Skript richtig sein soll. Welchen
Zustand sollte a denn noch annehmen...
Waer fuer einen kurzen Kommentar dankbar :)
Gruessle,
André
Der Sinn dieser Maßnahme ist, nicht explizit definierte, aber in der
Hardware vorhandene Zustände abzufangen, z.B. der 4. Zustand wenn 2 Bits
zur Codierung von 3 Zuständen verwendet werden. Diese Zustände können
(ordentlicher synchroner Aufbau vorausgesetzt) nicht im normalen
Betrieb, sondern nur durch elektrische Fehler auftreten.
Allerdings habe ich starke Zweifel dass dein Code zum gewünschten
Ergebnis führen wird, da das "others" wahrscheinlich schon
herausgeworfen wird, bevor sich der Compiler Gedanken um die
Zustandscodierung macht.
Wenn Robustheit gegen falsche Zustände gewünscht ist, dann kann man in
der Synthesesoftware die Funktion zur sicheren Zustandscodierung
aktivieren ("safe FSM" bei Xilinx). Man muss sich allerdings im Klaren
darüber sein was das bedeutet: man rechnet damit, dass jedes Bit zu
jedem beliebigen Zeitpunkt kippen kann.
Nunja. Hinter when others stand eigentlich => null, es dient also nur
der Vermeidung vermeintlicher Fehler beim Synthetisieren.
Nur besteht der Prof hier anscheinend auf etwas, das nicht unbedingt
noetig ist und auch keinen Nutzen bringt.
Danke auf jeden Fall fuer die bisherigen Antworten.
Gruessle,
André
André wrote:
> Nunja. Hinter when others stand eigentlich => null ...
Unnötig, denn a ist vom Typ dtyp und hat damit nur drei Zustände.
Weil die alle verwendet sind, kann es keine others, also anderen
Zustände mehr geben.
Die binäre Codierung ist nur 1 Art der Codierung für die drei Zustände,
und zudem bei FPGAs idR. die ineffizienteste.
>Unnötig, denn a ist vom Typ dtyp und hat damit nur drei Zustände.>Weil die alle verwendet sind, kann es keine others, also anderen>Zustände mehr geben.
Da aber die drei Zustände in der Synthese mit
mindestens zwei Bits codiert werden, kann
es theoretisch ungewollte Zustände geben.
Ich würde deshalb
1
whenothers=>
2
zustand<=aa;
schreiben. Also sozusagen eine bevorzugten
Zustand einnehmen.
Gruß
Gast
> Da aber die drei Zustände in der Synthese mit> mindestens zwei Bits codiert werden, kann> es theoretisch ungewollte Zustände geben.
Richtig, es kann in der Hardware undefinierte Zustände geben. Bei drei
definierten Zuständen wird aber, wenn (wie im Beispiel oben) alle
auscodiert sind, für den others-Zweig gar nichts erzeugt. D.h. auch wenn
durch einen ESD-Impuls ein undefinierter Zustand erreicht würde, kommt
man nicht beim others -Zweig heraus (weil es den in der Hardware gar
nicht gibt!).
Wenn ich einen default-State haben will, dann muß ich das so schreiben:
1
typedtypis(aa,ab,ac);
2
signala:dtyp:=aa;
3
:
4
:
5
caseais
6
whenab....,
7
whenac....,
8
whenothers=>...;-- hierher der Code für den Defaultstate aa
9
endcase
Dann wird alles, was nicht ab oder ac ist, automatisch aa.
Allerdings ist z.B. beim One-Hot-Encoding niemals definiert, was
passiert, wenn zwei FFs gleichzeitig aktiv sind. Man kann nur auf Kosten
zusätzlicher Ressourcen in den Syntheseeinstellungen eine sichere
Implementierung erzwingen. Dadurch gibt es dann keine undefinierten
Zustände. Stichwort: FSM Safe Implementation
@gast
Das kann ein fataler Irrtum sein!
Für den Simulator gibt es keine extra Zustände, da ist das when others
überflüssig.
Bei der Synthese gibt es :
1) verschiedene Kodierungen des Types, wie Lothar schon erwähnt hat.
2) Der Compiler berücksichtigt bei der Logik generierung nur die 3
Zustände, dass es noch weitere Bit-Kombinationen für den Zustandsvektor
gibt ist ihm schnurzpiepegal.
Der einzige richtige Weg sind Compiler-Optionen oder Attribute, die
wirklich den Compiler anweisen für alle ungültigen Zustände zu einem
sicheren Zustand zu springen (SAFE_FSM oder ähnlich). Das wurde auch
schon gesagt.
Um mich selber zu zitieren:
> Allerdings ist z.B. beim One-Hot-Encoding niemals definiert, was> passiert, wenn zwei FFs gleichzeitig aktiv sind.
Ich hatte mal eine SM, die ich One-Hot synthetisieren ließ, und bei der
alle Zustände mit when behandelt wurden. Und ab und an machte das Ding
Zicken.
Also habe ich zusätzlich noch die when others mit eingebaut, und
setzte dort einen Pin auf high. Das Ding machte weiter Zicken, aber der
Pin wurde nie gesetzt.
Daraufhin legte ich jedes einzenle State-FF auf einen eigenen Pin. Und
siehe da: Im Fehlerfall waren mehrere States aktiv, aber der others
Zweig wurde nicht erreicht (der entsprechende Pin niemals gesetzt).
BTW:
Der Fehler im obigen Beispiel war ein asynchroner Reset. So konnte sich
ein kurzer Spike am Reset-Pin direkt auf die FFs auswirken und die FFs
durcheinander bringen.
> Nunja. Hinter when others stand eigentlich => null, es dient also nur> der Vermeidung vermeintlicher Fehler beim Synthetisieren.> Nur besteht der Prof hier anscheinend auf etwas, das nicht unbedingt> noetig ist und auch keinen Nutzen bringt.
Wie Lothar sehr schön belegt hat, dient es zu überhaupt nichts, sondern
wird einfach von den Tools ignoriert (auch Synthese).
Gut möglich, dass der Prof schon zu lange in der Welt der Theorie
schwebt. Wenn er ein guter Lehrer ist, dann weise ihn doch mal darauf
hin, dass der "others" Zweig nichts bringt. Ansonsten mach das was jeder
macht: Rede ihm nach dem Mund und behalte für dich, dass du es besser
weißt. Wenn er zufällig genau die Frage stellt, wozu der "others" Zweig
gut ist, dann musst du halt abschätzen, ob er die Wahrheit verkraftet.
Ich habe das nochmal nach dem obigen Beispiel durchgemacht und an das
Beispiel ein wenig Fleisch gebracht:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entitySM_ueberdefiniertis
6
Port(clk:inSTD_LOGIC;
7
leds:outSTD_LOGIC_VECTOR(1downto0);
8
error:outSTD_LOGIC);
9
endSM_ueberdefiniert;
10
11
architectureBehavioralofSM_ueberdefiniertis
12
typedtypis(aa,ab,ac);
13
signala:dtyp;
14
15
begin
16
17
processbegin
18
waituntilrising_edge(clk);
19
error<='0';-- default
20
caseais
21
whenaa=>a<=ab;leds<="00";
22
whenab=>a<=ac;leds<="01";
23
whenac=>a<=aa;leds<="10";
24
whenothers=>a<=aa;error<='1';
25
endcase;
26
endprocess;
27
28
endBehavioral;
Bei der Synthese erhalte ich den Hinweis
1
WARNING:Xst:1710 - FF/Latch <error> has a constant value of 0 in block <SM_ueberdefiniert>.
Im Schaltplan sieht man schön, wie das error Flag fest auf GND
verdrahtet ist. Und wenn die Synthese schon nichts generiert, können die
nachfolgenden Arbeitsschritte (Translate, P&R) auch nichts mehr
herzaubern ;-)
hi,
ein beispiel ist leider kein nachweis, dass der von lkmiller
beschriebene effekt nicht auftreten kann.
im vorliegenden testcase kann der vhdl compiler/synthese die optimierung
so ansetzen, dass der "case" und die logic eindeutig ist. der von
lkmiller beschriebene fall wuerde zb. eintreten, falls der enum in der
port-map als io port aufgefuehrt wird. damit waere an der modul grenze
nach der synthese ein 2bit port sichtbar. dieser koennte den
undefinierten zustand '11' haben und damit u.U. die state-machine in
einen zustand bringen, der NICHT im RTL kodiert ist. das verhalten der
schaltung ist dann nur in der gate level simulation sichtbar.
das ganze laeuft unter design bug und sollte schon von anfang an
ausgeschlossen werden. wenn man noch mehr pech hat, fuehren diese
verborgenen states auf eine loop ohne rueckkehr in den RTL state space.
das macht spass das zu suchen (jedenfalls bekommt man aufmerksamkeit
vom mgmt ...)
also:
- enums auf 2**n literals auffuellen
- integer types (ranges) sollten 2**n values haben
- eine case alternative sollte "others" sein
- damit ist das case voll auskodiert (auch fuer sachen,
an die man nicht gedacht hat )
- am besten einen legal case zu others erweitern:
case a is
when aa .... ,
when ab .... ,
when others => ... ; -- ac
end case
- damit sollte die synthese dann auch nichts mehr machen was nicht im
rtl definiert ist.
mfg
/uwe
>- enums auf 2**n literals auffuellen
Das nutzt nichts - keiner sagt dir, dass die Synthese das dann mit n
Signalen codiert. Häufig wird eine one-hot-codierung genommen, die dann
2**n Signale hat. Da hilft kein VHDL-Konstrukt etwas, nur eine Anweisung
an die Synthese, eine sichere Implementierung zu wählen.
> - enums auf 2**n literals auffuellen
Wie Jan M. schon gesagt hat, erzwingt man damit keineswegs, dass die
Zustände auch in n Bits kodiert werden.
Davon abgesehen: Was genau hat man von den zusätzlichen Zuständen? Diese
müssen dann ja auch Übergänge und Werte für die Ausgangssignale haben.
In welchen "gültigen" Zustand soll verzweigt werden? Und so weiter. Da
man nicht weiß, warum ein ungültiger Zustand überhaupt erreicht wurde,
ist jeder Wechsel in einen "gültigen" Zustand falsch, abgesehen von
einem Reset des kompletten Subsystems - und selbst das ist meistens
falsch. Egal welchen "Ausweg" man sich ausdenkt, das System macht in 99%
aller Fälle etwas, was es eigentlich nicht machen soll.
> - integer types (ranges) sollten 2**n values haben
Gleiche Argumentation.
> - eine case alternative sollte "others" sein
Wenn alle definierten Zustände durch case-Zweige abgedeckt sind, wird
"others" wie oben beschrieben ignoriert, kann man also auch weglassen.
> - damit ist das case voll auskodiert (auch fuer sachen, an die man nicht
gedacht hat )
Ich denke, durch das oben geschriebene sollte klar werden, dass sich
beim Bau digitaler Logik ein wenig Nachdenken mehr lohnt als der
Versuch, Fehler nachträglich durch Rumfrickeln auszubessern.
> - damit sollte die synthese dann auch nichts mehr machen was nicht im> rtl definiert ist.
Genau das hat sich der Prof des OP sicher auch gedacht: "sollte". Aber
die Realität sah anders aus.
> - enums auf 2**n literals auffuellen
Das hilft nichts:
wenn ich 8 Zustände (2**3) habe, und die SM OneHot codiere,
dann gibt es 248 undefinierte Zustände (256-8).
Und es gibt noch viele andere Methoden, eine SM zu codieren.
Die "Safe Implementation" hilft auch nur, dass in keinen undefiniertenZustand eingetreten wird. Gegen undefinierte Übergänge hilft diese
Syntheseoption auch nichts.
>Wie Jan M. schon gesagt hat, erzwingt man damit keineswegs, dass die>Zustände auch in n Bits kodiert werden.
ok, auch lkmiller'ss onehot beispiel zeigt, doch gerade dass es
fehlermoeglichkeiten gibt, die auftreten, wenn im enum nicht alle
moeglichen binary values des types definiert sind (um im one hot zu
bleiben: 8 states=8bit=256 moeglichkeitn-8gueltige=248ungueltige. da
dass natuerlich nicht als vollstaendiger enum gefasst wird, wuerde ich
besondere vorsicht walten lassen, um nicht in die beliebten one-hot
issues zu laufen.
>Davon abgesehen: Was genau hat man von den zusätzlichen Zuständen? Diese>müssen dann ja auch Übergänge und Werte für die Ausgangssignale haben.
Nö, die dienen nur dazu, zu verhindern, dass es unterschiede zwischen
synth. netzliste und dem rtl gibt (sonst kann der fall eintreten dass
die synth. state machine ein superset! der im rtl beschriebenen ist -
die auf gate level macht also mehr als beschrieben+gewollt. dieses delta
an funktionlitaet ist tools/optimierungsabhaenig/etc. wenn man(n) pech
hat haengt sich daran das system auf. btw frag doch mal ein formales
tool ob gate und rtl gleich sind.
>In welchen "gültigen" Zustand soll verzweigt werden? Und so weiter. Da
man nicht weiß, warum ein ungültiger Zustand überhaupt erreicht wurde,
ist jeder Wechsel in einen "gültigen" Zustand falsch, abgesehen von
einem Reset des kompletten Subsystems - und selbst das ist meistens
falsch. Egal welchen "Ausweg" man sich ausdenkt, das System macht in 99%
aller Fälle etwas, was es eigentlich nicht machen soll.
klar,
1. ziel: komplette equivalenz im verhalten rtl vs gate level
(ausschliessen von hidden states und transitions welche durch die
synthese autreten koennen
2. ziel: wenns schon mal schiefgeht in der hardware (und das passiert
:-)) geht es darum das sich das system faengt und in einen definierten
zustand zurueckkehrt (und das ohne subsystem/system reset)
/mfg