Forum: FPGA, VHDL & Co. Signal-Verspätung in Prozess


von Road Runner (Gast)


Lesenswert?

Ich benütze einen Zustandsautomaten. Dieser soll in bestimmten Zuständen
von aussen angelegte Signal-Pegel speichern.
Nun habe ich das Problem, dass während der Simulation jeder
gespeicherte Signalpegel erst einen Zustand später erscheint.
Ist es möglich in einem Prozess, die Pegel sofort abzufragen, anstelle
einen Zustand verspätet?

von Daniel R. (daniel_r)


Lesenswert?

Nein, da Signale auf D-FlipFlops bestehen und die brauchen einen Takt um
die Daten zu übernehmen.

von Alex H. (alex123)


Lesenswert?

Hallo Road Runner,

die "Verzögerung" um einen Takt ist i.d.R. ja so gewollt ...

Wenn Du ein Signal in einem Prozess "speichern"
möchtest und dann gleich weiterverwenden, dann kannst Du
das über Variablen machen.

Bsp:
variable v_InputSignal
...
v_InputSignal := InputSignal
if (...) then
  StoredSignal <= v_InputSignal;
else
  StoredSignal <= v_InputSignal + 3; -- oder was auch immer.
end if;

Dann wird die ganze Berechnung zum selben Zeitpunkt
ausgeführt und erst für das Ergebnis StoredSignal
ein Register eingebaut. Für v_StoredSignal wird kein
Register eingebaut (wenn man es richtig macht, d.h.
die Variable muss in allen möglichen Verzweigungen
des Prozesses gesetzt werden.

So erzeugt z.B.
b <= a;
c <= b;
innerhalb eines getakteten Prozesses 2 FFs,
d.h. a wird um 2 Takte verzögert, während
variable b
b := a;
c <= b;
nur ein FF und nur einen Takt Delay für a erzeugt.

Gruss,

Alex

von Daniel R. (daniel_r)


Lesenswert?

Daraus resultieren Latches. Und Latches sollte man vermeiden. Außerdem
klappt sein Vorhaben auch D-FFs. Kein Grund sich Sorgen zu machen.

von Alex H. (alex123)


Lesenswert?

> Daraus resultieren Latches.

Woraus?

Die Verwendung von Variablen ist nicht gleichbedeutend
mit dem Einbau von Latches.
Man muss es nur richtig machen ...

Alex

von Daniel R. (daniel_r)


Lesenswert?

Woraus sollte die Variable denn sonst bestehen? Wenn ein Signal sofort
übernommen wird ist es ein Latch, da das nur ein Latch kann. Wäre es
ein FF, würde es die Daten erst beim nächsten Takt übernehmen.

Ich habe mal ein bisschen mit Variablen rumgespielt und obigen Code
ausprobiert. Die Variable wird in dem Fall sowieso wegoptimiert.

Bitte klärt mich auf, wenn ich falsch liege.

Daniel

von Alex H. (alex123)


Lesenswert?

Hallo Daniel,

was denn nun, ein Latch oder wegoptimiert ;-)
Naja, Spass muss sein ...

> Wenn ein Signal sofort übernommen wird ist es ein Latch
(Sollte wohl Variable heissen)

Die Variable wird nicht "übernommen" im Sinne von "Eintakten"
in ein "Speicherglied". Wird der Wert geschrieben und danach
benutzt (immer Schreiben der Variable vor dem Benutzen),
dann ist der zeitlich vorhergehende Wert (aus dem letzten
Durchlauf des Prozesses) nicht relevant, also wird auch
nix gespeichert.

Die Variable ist also in dem gedachten Fall nur ein
temporärer Speicher - sieh es als Zwischenwert oder sowas ...

Man muss die Variablen richtig verwenden, dann kommt
bei der Synthese auch was gescheites heraus. I.d.R. designed
man synchron, sollte also keine Latches einbauen (manchmal
muss man das, aber das sind Ausnahmen, die man auch immer
separat behandeln sollte).

Beispiel:

prozess
variable Var1, Var2 : ...
if Reset ...
elsif Rising_edge (Clock)
  ...
  Var1 := A + B + C;
  Var2 := D + E + F;
  Result <= Var1 - Var2;
  ...
end if;
end process;

und

prozess
if Reset ...
elsif Rising_edge (Clock)
  ...
  Result <= (A + B + C) - (D + E + F);
  ...
end if;
end process;

sind absolut identisch (aus sicht des Verhaltens in der
Simulation, also laut VHDL LRM).
Die Synthese sollte daher i.d.R. auch etwas "sehr ähnliches"
rausbringen.

Zum Vergleich:

prozess
if Reset ...
elsif Rising_edge (Clock)
  ...
  Sig1 <= A + B + C;
  Sig2 <= D + E + F;
  Result <= Sig1 - Sig2;
  ...
end if;
end process;

verhält sich anders. Hier gelten die Werte für Sig1 und Sig2
erst im darauffolgenden Takt, d.h. das Ergebnis steht erst
einen Takt später zur Verfügung.

Wann und warum verwendet man Vaiablen?

-) Variablen erhalten immer sofort ihren neuen Wert,
Signale erst nach Delta-Delay (oden nach einer
spezifizierten Zeit). Variablen können daher in einem
Prozess gleich weiterverwendet werden für die nachfolgenden
Berechnungen, Signale sind dabei erst mit dem nächsten
Takt gültig (das Delta-Delay führt dazu, dass der Wert
für diesen Durchlauf noch nicht gilt, der nächste Durchlauf
des getakteten Prozesses passiert dann erst einen
Clockcycle später.
Bei asynchronen Prozessen wird der Prozess bei der
Verwendung von Signalen dann eben nochmals gestartet ...
(oder so oft, so viele voneinander abhängige
Signalzuweisungen drin sind), bei Variablen wird er in
einem Durchlauf berechnet (Simulationszeit!).

-) In obigem Beispiel kann es recht unübersichtlich werden,
wenn man eine komplexe Berechnung hat und diese mit vielen
Klammerebenen verschachtelt direkt in der Signalzuweisung
beschreibt. Hier kann es besser sein, den Wert "nach und nach"
über Variablen "zusammenzubauen" und erst am Schluss auf
ein Signal zuzuweisen.

-) Manchmal möchte man gemeinsame Teilausdrücke vorab
berechnen, z.B.
  Sig1 := A + B;
  Sig2 := C + D;
  Sig3 := E + F;
  Result1 <= Sig1 - Sig2;
  Result2 <= Sig1 - Sig3;
ist i.d.R. besser als
  Result1 <= (A + B) - (C + D);
  Result2 <= (A + B) - (E + F);
Wenns komplexer wird, ist es auch einfacher, daran was zu ändern.

-) Verschiedenen Synthesetools können manchmal mehr, manchmal
weniger gut optimieren.
So kann man z.B. durch das Zusammenfassen eines Teilausdruckes
eine bessere Optimierung erreichen (Stichwort Resource-Sharing).
Z.B.:
  if (opcode = add) then
    res <= a+b;
  else -- opcode = sub
    res <= a-b;
  end if;
oder
  if (opcode = add) then
    var1 := b;
  else
    var1 := -b;
  end if;
  res <= a+var1;
Im ersten Fall wird ggf. ein Addierer und ein Subtrahierer
(noch'n Addierer) eingebaut und das Ergebniss gemultiplext, im
zweiten Fall wird eventuell nur ein Addierer eingebaut und der
b-Eingang des Addierers gemultiplext. Sind a und b beispielsweise
32-Bit-Vektoren, dann macht das HW-mäßig schon was aus.
Gute Synthesetools sollten dies aber mittlerweile automatisch
machen, so das in beiden Fällen dasselbe rauskommt (war nicht
immer so). (BTW, ich selber tendiere normalerweise zur ersten
Variante, da besser lesbar - und man die HW-Implementierung nicht
notwendigerweise vorwegnehmen soll, aber da hat jeder seine
eigene Meinung zu ...)

-) Simulatoren sind i.d.R. etwas schneller mir den Variablen
als mit den Signalen.
Hat man also viele Prozesse mit Signalen vs. Variablen in einem
großen Design, dann kann das schon was ausmachen ...
Siehe auch oben bei asynchronen Prozessen, die mit Signalen
ggf. wesentlich öfters durchlaufen werden.

Es gibt sicher noch jede Menge andere Gründe unter
Google (vhdl, variable, ...) bzw. in anderen Threads in diesem
Forum ...

Vieles ist auch Geschmachssache, meist sind die Auswirkungen
nicht wirklich so groß, als daß man auf diesem Level optimieren
muss. Da gilt dann eher die Devise, "lesbaren" und
verständlichen Code zu schreiben (wie im Beispiel mit dem
Addierer).

Gruss,

Alex

von Daniel R. (daniel_r)


Lesenswert?

OK, vielen Dank für die Erklärung.

Daniel

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.