Hallo,
der folgende Beispielcode ist aus einem Buch entnommen und leider
verstehe ich eine Stelle nicht. Es ist ein Moore Automat in der
sogenannten Ein-Prozess-Darstellung, es soll eine Sequenz an E erkannt
werden (01 11 10) und beim erkennen ein Ausgang A gesetzt werden.
Die Stelle die ich nicht verstehe ist: Wenn ich in dem Prozess vor der
case-Anweisung den Zustand immer auf Z0 setze (Defaultzuweisung) dann
kann ich doch nie in die when Z1 anweisung kommen. Ich gehe davon aus
das in dem Buch kein Mist steht und der Fehler also in meinem
Verständnis zu suchen ist. Wenn mir dabei jemand auf die Sprünge helfen
könnte wäre das toll.
Hier der Code:
-- Moore-FSM 1-Prozess: Sequenz Erkennung (01,11,10)
entity FSM_1p_MOORE is
port( RESET, CLK : in bit;
E : in bit_vector (1 downto 0);
A : out bit);
end FSM_1p_MOORE;
architecture SEQUENZ of FSM_1p_MOORE is
type ZUSTAENDE is (Z0, Z1, Z2. Z3);
signal ZUSTAND: ZUSTAENDE;
begin
process(CLK,RESET)
begin
if RESET = '1' then
ZUSTAND <= Z0 after 20ns; A after 20ns;
elsif CLK = '1' and CLK'event tehn
A <= '0' after 20ns;
ZUSTAND <= 'Z0' after 20 ns; -- Defaultzuweisung
case ZUSTAND is
when Z0 => if E="01" then ZUSTAND <= Z1 after 20ns;
end if;
when Z1 => if E="11" then ZUSTAND <= Z2 after 20ns;
end if;
when Z2 => if E="10" then ZUSTAND <= Z3 after 20ns;
A <= '1' after 20 ns;
-- Ausgang an Übergangsschaltnetz gekoppelt
elseif E= "01" then ZUSTAND <= Z1 after 20 ns;
end if;
when Z3 => if E="01" then ZUSTAND <= Z1 after 20ns;
end if;
end case;
end if;
end process;
end SEQUENZ
Ein Prozess wird sequentiell abgearbeitet. Wenn also eine Bedingung der
case Anweisung erfüllt ist, wird die Defaultanweisung dadurch
überschrieben. Die Defaultanweisung dient in diesem Fall nur dazu, wenn
der Automat in einen undefinierten Zustand geht, dass er dann in Z0
zurückgeholt wird.
Der Zustand wird ja nur bei Reset auf Z0 gesetzt, wie z.B. nach einem
Neustart.
1
if RESET = '1' then
2
ZUSTAND <= Z0 after 20ns; A after 20ns;
Wenn Du das System nicht resetest, laeuft es und geht immer nur in den
Elsif-Zweig. Wird also nicht auf den Default (Z0) Zustand gesetzt.
PS: Kleiner Schreibfehler in der Zeile
elsif CLK = '1' and CLK'event tehn
then statt tehn. Gibt sonst Probleme beim Compilen.
Hallo,
@ Christian: wenn du das after 20 ns meinst: "Die Verzögerung der
Signalzuweisung mit der after Anweisung um die symbolische
Signallaufzeit von 20ns wird hier gewählt, um die Timingpfade
aufzuzeigen die durch die Verkettung der Register- und
Schaltnetzverzögerungen entstehen" Das ganze wird im Anschluss
simuliert.
@ Stingray und T.M.:
Das ein Prozess sequenziell abgearbeitet wird ist klar, auch das wenn
ich in Z0 bin und E 01 anliegt in Z1 gegangen wird ABER:
Nachdem ZUSTAND= Z0 und E= 01 ist wird ZUSTAND= Z1.
Gehts jetzt direkt weiter mit case Z1 obwohl vorher schon eine case
abfrage zugetroffen hat??? Ich dachte der Prozess ist nach dem setzen
von ZUSTAND auf Z1 erstmal zuende und fängt dann mit der nächsten
steigenden CLK Flanke wieder von vorne an und dort setz ich ja ZUSTAND
wieder auf Z0...
Das ist der Punkt den ich nicht verstehe.
Und selbst wenn die case abfrage weiter geht, also nach dem setzen von
ZUSTAND auf Z1 der case Z1 zweig aktiv wird, dann ist ja E noch nicht 11
(mal davon ausgegangen das sich E auch erst mit der nächsten clock
flanke ändert) dann ist der Prozess also doch zu ende und wird bei der
nächsten flanke wieder gestartet, wobei ZUSTAND wiederum auf Z0 gesetzt
wird.
@ Stingray
hab deinen zweiten kommentar grad erst gelesen:
Der ZUSTAND wird eben nicht nur beim reset auf Z0 gesetzt sondern auch
danach im else zweig.
elsif CLK = '1' and CLK'event tehn
A <= '0' after 20ns;
ZUSTAND <= 'Z0' after 20 ns; -- Defaultzuweisung
Und genau das bereitet mir Kopfzerbrechen weil er ja dann mit jeder clk
flanke auf Z0 gesetzt wird, wie soll er denn da "zum ZIEL kommen"
Danke für den Tippfehler, hab ich jetzt nur aus dem Buch abgetippt und
nicht versucht zu compilieren.
Es gibt kein korrigierten code. Der code ist so korrekt wie er oben
dargestellt ist. Man muss beim durchdenken was passiert nur beachten das
ein Signal, welches in einem Prozess geändert wird, erst beim Verlassen
des Prozesses geschrieben wird.
Bsp.:
prozessbeginn: ZUSTAND ist Z1
ZUSTAND <= Z0;
if ZUSTAND = 'Z0' then
ZUSTAND <= Z3
if ZUSTAND = 'Z1' then
ZUSTAND <= Z2
ende des prozesses
Am Ende wird ZUSTAND Z2 sein DENN ZUSTAND wird zwar am beginn des
prozesses Z0 gesetzt aber es wird erst am prozessende aktualisiert.
D.h. die if abfrage reagiert auf Z1 weil dies der Wert ist den ZUSTAND
noch hat.
somit wir ZUSTAND Z2 zugewiesen
und DAS wird am ENDE des prozesses aktualisiert.
Ich hoffe das hilft Dir weiter...
Nur um das nochmal klarzustellen:
[ ] - dieser Code kann synthetisiert werden
[x] - dieser Code dient nur zur Simulation und Anschauung
Richtig?
PS: Ich finde solche Bücher furchtbar, die einem
alle möglichen Ausdrücke näher bringen (wie wait for etc.)
und damit VHDL erklären, nur um dann mitten im Buch
zur Synthese zu wechseln und dann (hoffentlich wenigstens)
zu sagen "Alles, was du bisher gelernt hast, kannst du
wieder vergessen, geht hier nicht".
PS2: Das war jetzt eher allgemein, nicht speziell gegen
das Buch, welches ich ja gar nicht kenne.
Richtig das ganze soll nur simuliert werden und die wollen an der Stelle
das Timing irgendwie mit einbringen.
Spasseshalber heisst das Buch nicht Grundlagen VHDL oder so sondern
"VHDL-Synthese".
Den Namen hat es sich dennoch verdient, es wird ausführlich erklärt bei
welcher Art der Beschreibung zum Beispiel Latches entstehen, wann Flip
Flops und so weiter. Es wird also wert darauf gelegt beim programmieren
schon zu verstehen was für Hardware daraus am ende wird.
Das mit dem "after" in diesem Beispiel spricht natürlich nicht gerade
für den Titel des Buches :).
Also wen es interessieren sollte:
J. Reichardt / B. Schwarz
"VHDL-Sythese" Entwurf digitaler Schaltungen und Systeme
erschienen im Oldenburg Verlag
P.S.: Auch das Signale am ende eines Prozesses geschrieben werden ist im
Buch erklärt, aber wer merkt sich schon was in Kapitel 3 Stand wenn man
inzwischen Kapitel 7 liest ;))