Forum: FPGA, VHDL & Co. Verständnisfrage Kombinatorischer Prozess


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Chris (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich habe eine Frage zu kombinatorischen Prozessen.
Sehen wir uns diese State machine an:
1
STATE_MEM : process( clk ,  reset )
2
begin
3
  if reset =  ’1’ then
4
    state <= "00";
5
  else if rising_edge(clk) then
6
    if(enable = '1') then
7
      state <= next_state;
8
    end if;
9
  end if;
10
11
end process
12
13
14
15
TRANSITION_LOGIC : process( state ,  i )
16
begin
17
  next_state <= state ;
18
19
  case( state) is
20
    when "00" =>
21
      if i =  ’1’ then
22
        next_state <= "01";
23
      else
24
        next_state <= "00";
25
      end  if;
26
    when "01" =>
27
      if i =  ’1’ then
28
        next_state <= "10";
29
      else
30
        next_state <= "00";
31
      end  if;
32
    when "10" =>
33
      if i =  ’1’ then
34
        next_state <= "10";
35
      else
36
        next_state <= "00";
37
      end  if;
38
    when others =>
39
      next_state <= "00";
40
  end case;
41
end process;

Es heisst doch, dass in einem rein kombinatorischen Prozess Signale 
nicht gespeichert werden. Weil diese ja nicht getaktet sind und somit 
keine Flip Flops erzeugt werden.
Wenn wir jetzt den Prozess "TRANSITION_LOGIC" betrachten. Dann wird ja 
"next_state" auf einen Wert gesetzt falls sich "state" oder "i" ändert. 
Danach wird bei der nächsten steigenden Flanke dem "state" der WErt von 
"next_state" zugewiesen. Aber sollte zu diesem Zeitpunkt der Wert vom 
"next_state" nicht wieder weg sein? Weil dieser ja nicht gespeichert 
wird...?

Danke schon mal im Vorraus

Chris

von Jürgen S. (engineer) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Aus Softwaresicht, also im Sinne der Simulation, wird das natürlich sehr 
wohl gespeichert und auch die Synthese speichert sich diese Information.

Aber das, was dabei herauskommt, enthält keinen Speicher mehr, in dem 
Variablen oder "temporäre Signale" noch irgendwie sichtbar wären, weil 
diese eben nur Hilfskonstrukte beim Bauen sind. Deren Information muss 
sich in irgendeiner Form in Signale abbilden, die in einen echten 
Speicher münden.

Und:

Nur, was aufgrund der Verknüpfungen mit IOs oder internen 
"Energiespeichern" tatsächlich benötigt wird, führt auch zu einer 
Hardware und nur die kann (muss nicht) einen Wert speichern. Ein solcher 
state wäre z.B. auch in Hardware dann nicht mehr in dieser Form 
sichtbar, wenn die Bits, die ihn codieren, nicht vollständig benötigt 
werden.

Ich betone nochmals, dass VHDL eine Bauanleitung für eine Schaltung ist. 
Wenn dort drin steht, dass der Erbauer sich was merken soll oder eine 
Schleife machen soll um mehrfach etwas zu bauen, heißt das noch lange 
nicht, dass die Schaltung die er erbaut, sich später auch was merken 
muss oder Schleifen vollzieht.

von Theor (Gast)


Bewertung
0 lesenswert
nicht lesenswert
In dem Prozess TRANSITION_LOGIC ist next_state zu meine identisch mit 
state, dann aber wieder nicht. Da muss man sich entscheiden. Dann tritt 
auch die Frage gar nicht auf.

Es scheint mir, als wenn Du ein "Programm" schreiben willst. Aber, wie 
unser allseits beliebter Lothar immer sagt: Du beschreibst Hardware.

von Achim S. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Chris schrieb:
> Aber sollte zu diesem Zeitpunkt der Wert vom
> "next_state" nicht wieder weg sein?

Transistion_logic muss tatsächlich nichts speichern. Dieser Prozess 
beschreibt eine einfache kombinatorische Logik (ein Schaltnetz), die aus 
den aktuellen Werten von state und von i den Wert von next_state 
berechnet. next_state ändert sich immer dann, wenn einer der Eingänge 
(state, i) sich ändert.

Wichtig ist, dass der Wert von next_state dann stabil ist, wenn er 
benötigt wird. Das ist jeweils bei der positiven Taktflanke (wenn 
next_state nach state übernommen werden soll). Das ist aber 
gewährleistet, wenn sich die Werte von state und i einige ns vor der 
Taktflanke nicht mehr ändern.

Wenn die Taktflanke kommt ändert sich state, und in der Folge schaltet 
auch next_state um. Aber das ist ok, weil der abzuspeichernde Wert von 
next_state ja schon bei der Taktflanke nach state übernommen wurde und 
erst wieder bei der nächsten Taktflanke interessiert. Wennd die 
Taktfrequenz nicht zu hoch ist macht state als Eingang hier also keine 
Probleme, weil sich state und next_state nur kurz nach der Taktflanke 
ändern - aber erst beid er nächsten Taktflanke wieder von Interesse sind 
- und bis dahin ist next_state wieder stabil.

Bei i ist die Sache potentiell anders, weil wir in deinem Code-Schnipsel 
nicht sehen, wann genau i sich ändern kann. Wenn i sich zu beliebigen 
Zeitpunkten ändern kann, dann wird deine Statemachine tatsächlich nicht 
zuverlässig funktionieren. Es kann dann passieren, dass i sich gerade 
kurz vor einer Taktflanke ändert, und der Wert von next_state bei der 
Taktflanke noch nicht vollständig auf den neuen gültigen Wert 
umgeschaltet ist. Dann machte deine Statemachine falsche oder 
undefinierte State-Übergänge.

Aber wenn i selbst auch aus einem Flip-Flop stammt, das mit dem selben 
Takt arbeitet wie deine Statemachine, dann passt wieder alles. Dann 
liegt der Wert von i lange genug an um die Durchlaufzeiten der 
Übergangslogik abzuwarten. Dann hat next_state vor der nächsten Flanke 
wieder zuverlässig auf den neuen Folgezustand umgeschaltet.

Das ist auch der Grund, warum externe Signale (die keinen definierten 
Setup-Hold-Zeiten relativ zu clk haben) erst einsynchronisiert werden 
müssen, ehe sie in deiner synchronen Statemachine ausgewertet werden 
dürfen.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Chris schrieb:
> Es heisst doch, dass in einem rein kombinatorischen Prozess Signale
> nicht gespeichert werden.
Du hast da aus den Aussagen etwas falsch extrahiert.

In eine kombinatorischen Prozess werden keine getakteten 
Speicherelemente (aka. Flipflops) beschrieben. Bestenfalls ein Latch 
kannst du da basteln (meist ungewollt und zufällig).

Ein kombinatorischer Prozess beschreibt (genauso wie eine ungetaktete 
nebenläufige Anweisung) einfach eine Schaltung, die aus Eingangswerten 
Ergebnisse berechnet.
Udn diese Ergebnisse werden natürlich nicht gespeichert, sondern ändern 
sich mit jeder Änderung des Eingangswertes.

Aber wie Theor schon sagt, was ich immer sage:
Stell dir eine Hardware vor und beschreibe sie dann mit der 
HardwareBESCHREIBUNGssprache VH-D-L. Es geht mit Garantie schief, wenn 
du dir solche Eselsbrücken wie "kombinatorische Prozesse speichern 
nichts" merkst und basierend auf diesem "Extrakt" drauflos 
programmierst...

von C. A. Rotwang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Chris schrieb:

FSM:


Z(t+1) <= f(Z(t),X(t))
y(t)    <= f(Z(t),X(t))

Letzte Gleichung ist rein kombinatorisch, die erstere beinhaltet 
kombinatorik und Speicher. eine Zustands-Speicherung, also die Abbildung 
von Z(t) auf Z(t+1) wird durch FF ("getakteter Prozess) realisiert, 
alles andere durch kombinatorik.

https://www3.informatik.uni-erlangen.de/DE/Lehre/VHDL-RA/SS2014/folien/09-fsm.pdf


Such dir einfach mal die Blockbilder einer FSM aus einem gescheiten 
Lehrbuch raus, dann sollte der Unterschied zwichen "Speicher" und 
"Variablenspeicherung" klarer werden.

von Chris (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke euch allen :)
ich denke jetzt ist es klarer.
Ich werde mir auf jeden fall noch die erzeugte Schematic im detail 
anschauen.

Gruß

Chris

von Vancouver (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Man muss dem TO zugute halten, dass diese Sache in VHDL auch recht 
verwirrend ist. Die Semantik eines Prozesses besagt, dass der Rumpf nur 
ausgewertet wird, wenn sich eines der Signale aus der Sens-Liste ändert. 
Aber was ist, wenn sich keines der Signale ändert? Bleiben die Ergbnisse 
aus dem Prozess erhalten (aka Speicherung), oder sind sie anschließend 
undefiniert? Beides ist im obigen Beispiel falsch, weil es sich um reine 
Kombinatorik handelt, die kontinuierlich ausgewertet wird und nicht nur 
bei Änderung eines Signals.

Deswegen hat reine Kombinatorik streg genommen eigentlich auch nichts in 
einem Prozess zu suchen. Es wäre besser, sie als plattes concurrent 
statement ohne Prozess drumherum hinzuschreiben. Leider verbietet VHDL 
die Benutzung von IF und CASE außerhalb von Prozessen, und das ganze mit 
WHEN oder als Boole'sche Gleichungen aufzuschreiben ist umständlich und 
fehleranfällig. Deswegen nimmt man halt doch einen Prozess.

Vielleicht sollte man noch erwähnen, dass die ganze Sache mit der 
Sensitivitätsliste ein Zugeständnis an den Simulator ist. Der Simulator 
speichert die Zustände kombinatorischer Signale intern natürlich 
irgendwo ab, und muss sie daher auch nur dann neu berechnen, wenn sich 
die Operanden ändern (heißt deswegen Event Driven Simulation). Durch sie 
Sens-Liste sagt man dem Simulator, wann er seine internen Zustände neu 
berechnen muss. Das ganze darf aber nicht darüber hinweg täuschen, dass 
das Konstrukt eine reine Gatteranordnung ohne Speicherelemente 
beschreibt.

In SystemVerilog ist das übrigens besser gelöst: Es gibt dort den 
always_comb-Block, in dem der Benutzer reine Kombinatorik reinschreiben 
und  dabei alle Sprachkonstrukte von SystemVerilog verwenden kann. Die 
Sensitivitätsliste baut sich der Compiler selbst, daher kann man auch 
kein Signal vergessen und versehentlich ein Latch erzeugen.

von Theor (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Vancouver schrieb:
> Man muss dem TO zugute halten, dass diese Sache in VHDL auch recht
> verwirrend ist. Die Semantik eines Prozesses besagt, dass der Rumpf nur
> ausgewertet wird, wenn sich eines der Signale aus der Sens-Liste ändert.
> Aber was ist, wenn sich keines der Signale ändert? Bleiben die Ergbnisse
> aus dem Prozess erhalten (aka Speicherung), oder sind sie anschließend
> undefiniert? Beides ist im obigen Beispiel falsch, weil es sich um reine
> Kombinatorik handelt, die kontinuierlich ausgewertet wird und nicht nur
> bei Änderung eines Signals.
> [...]

Hm. Naja. Ich mag falsch liegen, aber mir kommt dieses Argument doch so 
vor, als wenn es aus der nicht ganz beiseite geschobenen Sichtweise der 
imperativen Programmierung her rührt.


Ich denke es ist nicht wirklich zutreffend, in beiden Fällen (der 
Beschreibung eines Flip-Flops und der Kombinatorik) von "Speicherung" zu 
sprechen. Um den Kontrast etwas deutlicher zu machen könnte man eher von 
Speicherung im Gegensatz zu "Beständigkeit" (das ist nur ein Vorschlag) 
sprechen. Ich stimme allerdings zu, dass, was ich eben Beschreibung 
genannt habe, in VHDL eine auch mir, etwas "gekünstelte" Semantik 
beinhaltet - eine ein wenig abseitige Interpretation.

Sie wird eigentlich erst klar, wenn man sich dazu, die reale Schaltung 
denkt. Dann nämlich kommt man an den Punkt, an dem eine von einer Flanke 
abhängige "Weiterleitung" und "Beständigkeit" eigentlich nur mit einem 
FF möglich ist. Andererseits ergibt eine Kombinatorik eine zeitlich 
verzögerte "Beständigkeit".

Um klar zumachen, was ich unter "Beständigkeit" hier verstehen will, 
eine Skizze eines Und-Gatters:

x1  +---+
----+   |   y
    | & +--->
----+   |
x2  +---+

In VHDL also etwa: "y y= x1 and x2".

Ein einfacherer, sogar trivialer, Fall ist:

x         x
----------->

Etwas, das in VHDL zur Semantik gehört und nicht ausdrücklich 
hingeschrieben werden muss.

Die Frage des TO ist sinngemäss, ob denn nicht y "verschwunden" ist, 
wenn der UND-Prozess ein weiteres Mal durchlaufen wird. Zitat: "Er wird 
ja nicht gespeichert". Die Fehlinterpretation ist dem 
VHDL-Fortgeschrittenen klar, denn er weiss, dass er eine 
Kombinatorik-SCHALTUNG beschrieben hat, die ständig die 
Und-Verknüpfung von x1 und x2 bildet und damit ist das Resultat y 
ständig vorhanden, obwohl es nicht gespeichert wird - nicht in dem 
Sinne, wie es mit einem Flip-Flop geschieht.

Damit ist diese Frage eigentlich geklärt. (Womit ich nicht sagen will, 
dass man darüber nicht noch weiter reden kann).


In meinem ersten Beitrag hier, habe ich mich auf etwas anderes bezogen, 
In Schaltung übersetzt, sieht TRANSITION_LOGIC etwa so aus:


      +-------------------+
state |                   |
----->+-----+------?--+   |   next_state
      |     |      ^  +---+------->
      |     V      |      |
      |  +--+--+   |      |
i     |  |     |   |      |
----->+--+ f   +->-+      |
      |  |     |          |
      |  +-----+          |
      +-------------------+

In dieser Beschreibung steckt ein Widerspruch. Und zwar nicht weil 
eine Rückkopplung beschrieben wird - das wird es nämlich nicht. Sondern 
weil next_state zum einen identisch mit state sein soll, andererseits 
aber, mit dem Resultat (der hier mit f angedeuteten) kombinatorischen 
Funktion (der case-Teil des Prozesses).

Der TO wollte anscheinend eine Rückkopplung beschreiben, in der 
Annahme, er realisiere damit eine Speicherung. Diese Deutung seines 
VHDL-Textes ist aber nur bei einer imperativen Interpretation, also 
Zeile-für-Zeile, sinnvoll. So aber kann VHDL eben nicht verstanden 
werden. Das ist nicht seine Semantik.


Hier spielt auch die so oft wiederholte Warnung vor asynchroner Logik 
eine Rolle, denke ich. Sie wird bei Erklärungen und in Lerntexten schon 
so weit stillschweigend vorausgesetzt, dass sie möglicherweise dem einen 
oder anderen gar nicht mehr erklärt wird. Ja, vielleicht hat sie der 
"Lehrer" schon so weit verinnerlicht, dass er die lediglich von den 
Konsequenzen erzählt und dem Schüler das unklare Gefühl bleibt, da fehle 
etwas an der Erklärung. Ich vermute wenigstens, dass diese Tatsache für 
den TO ein Teil seines Verständnisproblems ist.

Dabei ist es, wie schon oft demonstriert, durchaus möglich asynchrone 
Logik zu beschreiben und auch zu synthetisieren. Es handelt sich 
lediglich um eine Regel, die das arbeiten vereinfachen soll, nicht 
um ein technisches Hindernis im eigentlichen Sinn. (Ich denke, ich sage 
nur, was den VHDL-Fortgeschrittenen ohnehin klar ist).


Jedenfalls ist aber eine Rückführung von Signalen keine Speicherung. 
Vielmehr ein Fall von (der von mir so genannten) "Beständigkeit" von 
Signalen. Bei einer Rückführung tritt deswegen ein gewisser 
"Speichereffekt" ein, weil die Laufzeit eine Rolle spielt. Die Frage ist 
dann nur, ob nachfolgende Logik auf diesen "Zustand" schnell genug 
reagieren kann.

Püh. Ein langer Text. Ich hoffe er ist sinnvoll und hilft jemandem.

Viel Erfolg.

von Vancouver (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Theor schrieb:
> könnte man eher von
> Speicherung im Gegensatz zu "Beständigkeit" (das ist nur ein Vorschlag)
> sprechen.

Speicherung ist zugegeben unglücklich gewählt. Entscheidend ist, dass 
der Wert erhalten bleibt.

> Der TO wollte anscheinend eine Rückkopplung beschreiben, in der
> Annahme, er realisiere damit eine Speicherung.

Der Code des TO beschreibt einen völlig korrekten Zustandsautomaten, 
soweit ich das sehe, und der enthält eine Rückkopplung. Die Speicherung 
kommt aber nicht durch die Rückkopplung zustande, sondern durch den 
getakteten ersten Prozess. Die Frage des TO war, warum im ungetakteten 
zweiten Prozess nicht auch eine Speicherung stattfindet.

> In dieser Beschreibung steckt ein Widerspruch.
> Sondern
> weil next_state zum einen identisch mit state sein soll, andererseits
> aber, mit dem Resultat (der hier mit f angedeuteten) kombinatorischen
> Funktion (der case-Teil des Prozesses).

Nein, das ist kein Widerspruch. Innerhalb eines Prozesses werden die 
Anweisungen sequenziell (wie bei einem imperativen Programm) 
ausgewertet. (Genauer formuliert: Es wird bei der Synthese eine 
Schaltung erzeugt, die das gleiche Ergebnis liefert wie der sequenziell 
ausgeführte Code im Prozess).  Die mehrmalige Zuweisung von next_state 
ist korrekt, der zuletzt zugewiesene Wert "gewinnt". Next_state wird nur 
dann identisch mit state, wenn keiner der Case-Branches zutrifft, was 
aber im Beipiel niemals der Fall ist, weil die Case-Bedingungen 
vollständig auscodiert sind und immer eine zutrifft. Man könnte die 
Zeile next_state <= state also weglassen in diesem Fall, aber falsch ist 
sie nicht.

von Sigi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Vancouver schrieb:
> Man könnte die Zeile next_state <= state also weglassen

Auch wenn sie hier überflüssig ist, sollte man diese
Default-Zuweisungen immer am Anfang eines komb. Prozesses
schreiben (z.B. in der Zwei-Prozess-Schreibweise). Damit
sind Latches ausgeschlossen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.