Forum: FPGA, VHDL & Co. Zustandsänderung erfassen - Schieberegister oder Vergleich Signal und Variable (VHDL)


von Dominik (Gast)


Lesenswert?

Hallo zusammen,

ich habe eine Frage, wie ich (sinnvoll) eine Zustandsänderung in VHDL 
erfassen kann. Ich habe ein sich ständig änderndes Integer-Signal int1, 
bei welchem ich überprüfen möchte, in welchem Bereich der aktuelle Wert 
gerade liegt. Die Bereichsgrenzen sind über Konstanten definiert. Liegt 
der neue Wert von int1 in einem anderen Bereich, soll ein 
Std_Logic-Signal für einen Taktzyklus auf '1' gehen. Für die Erfassung 
dieser Zustandsänderung hatte ich zwei Wege gefunden:
1. Schiebe den aktuellen Bereich in ein 2 Bit Schieberegister und 
vergleiche die beiden Werte.
2. Weise den aktuellen Bereich einem Signal und einer Variablen zu und 
vergleiche im Anschluss das Signal mit der Variablen. Nachdem der 
Zustand bei dem Signal erst mit dem nächsten Taktzyklus "übernommen" 
wird, liefert ein Vergleich von Signal und Variable sofort, ob sich der 
Zustand geändert hat.
Ich versuche den zweiten Fall mal als Code zu schreiben, damit es 
leichter verständlich ist:
1
if rising_edge(clk) then 
2
  if int1 < const1 then 
3
    bereich_sig <= bereich1;
4
    bereich_var := bereich1; 
5
  elsif int1 < const2 then 
6
    bereich_sig <= bereich2;
7
    bereich_var := bereich2; 
8
  elsif 
9
  ...
10
  end if; 
11
  
12
  if bereich_sig /= bereich_var then
13
    neuer_zustand <= '1'; 
14
  else
15
    neuer_zustand <= '0'; 
16
  end if;

Die erste Umsetzung umgeht den Einsatz von Variablen. Bei der zweiten 
Umsetzung habe ich irgendwie ein ungutes Gefühl ob das in Hardware dann 
auch wirklich funktioniert.
Meine Frage ist nun allgemein, ob etwas bei diesem Beispiel gegen die 
Verwendung der Variablen spricht und ob es hier zu Problemen kommen 
kann, oder ob beide Möglichkeiten prinzipiell umsetzbar sind. Vielen 
Dank im Voraus für eure Kommentare.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dominik schrieb:
> ich habe eine Frage, wie ich eine Zustandsänderung in VHDL
> erfassen kann.
Achtung: die Frage ist falsch gestellt!
Sie muss lauten:
wie kann ich eine Zustandsänderung in der Hardware erfassen?
Und daraus dann eine VHDL-Beschreibung für diese Hardware ableiten?

Und letztlich ist es dann so, dass ein Zustand in einem (oder mehreren) 
Flipflop(s) gespeicher ist, und du dann einfach das "vorher" mit dem 
"nachher" vergleichst.
Eine Flankenerkennung mach sowas z.B.: da wird der aktuelle Zustand des 
Pins mit dem Zustand vorher verglichen und darauf reagiert:
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung

Aber das hast du ja schon erkannt...

Dominik schrieb:
> Ich habe ein sich ständig änderndes Integer-Signal int1, bei welchem ich
> überprüfen möchte, in welchem Bereich der aktuelle Wert gerade liegt.
> Die Bereichsgrenzen sind über Konstanten definiert. Liegt der neue Wert
> von int1 in einem anderen Bereich, soll ein Std_Logic-Signal für einen
> Taktzyklus auf '1' gehen. Für die Erfassung dieser Zustandsänderung
> hatte ich zwei Wege gefunden: 1. Schiebe den aktuellen Bereich in ein 2
> Bit Schieberegister und vergleiche die beiden Werte.
Gut soweit.

Aber jetzt komt der mentale Knoten, wo du die Hardware verlässt und dich 
auf Hilfskonstrukte einer Beschreibungssprache "verlässt":
> 2. Weise den aktuellen Bereich einem Signal und einer Variablen zu
> und vergleiche im Anschluss das Signal mit der Variablen.
Wie sieht denn die Hardware dazu aus?

Ein Tipp zum Nachdenken: entkopple einfach mal die Bereichsermittlung 
des aktuellen Werts von der Auswertung, ob sich der Bereich geändert 
hat. Hier mal ganz ohne Prozess:
1
akt_bereich <= bereich1 when int1 < const1 else
2
               bereich2 when int1 < const2 else
3
               bereich3 when int1 < const3 else
4
               bereich0;
5
6
7
neuer_zustand <= '1' when akt_bereich /= alt_bereich else '0'; 
8
9
alt_bereich <= akt_bereich when rising_edge(clk); -- für später merken

Die Reihenfolge der obigen Anweisungen ist übrigens vöölig beliebig 
(weil concurrent). Das hier verhält sich genau gleich und ergibt die 
selbe Hardware:
1
alt_bereich <= akt_bereich when rising_edge(clk); -- für später merken
2
3
neuer_zustand <= '1' when akt_bereich /= alt_bereich else '0'; 
4
5
akt_bereich <= bereich1 when int1 < const1 else
6
               bereich2 when int1 < const2 else
7
               bereich3 when int1 < const3 else
8
               bereich0;

: Bearbeitet durch Moderator
von Dominik (Gast)


Lesenswert?

Hallo,

vielen Dank für die schnelle Antwort! Das ist natürlich eine sehr gute 
Gegenfrage. Ich bin um ehrlich zu sein nicht ganz sicher, wie genau 
Variablen in Hardware umgesetzt werden. Meine Idee war eine Art 
asynchrones FlipFlop oder ähnliches, aber damit liege ich wahrscheinlich 
falsch... Daher auch mein "schlechtes Gefühl" bei der Sache, weil ich 
die dahinter stehende Hardware nicht kenne.
Der gezeigte concurrent Code sollte denke ich funktionieren, und umgeht 
sowohl Variablen als auch ein "offensichtliches Schieberegister". Auf so 
eine Lösung wäre ich nicht gekommen.
Kann ich es so zusammenfassen (sicher nicht falsch ;-)): Nimm den Weg, 
von dem du weißt, was du tust! Also in meinem Fall: bleibe bei dem 
"bekannten" Schieberegister und versuche nicht etwas zu "optimieren" und 
verwende Konstrukte, von denen du nicht weißt, was eigentlich dahinter 
steht.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dominik schrieb:
> Nimm den Weg, von dem du weißt, was du tust!
Und sieh ab&zu über deinen Tellerrand...  ;-)

> Ich bin um ehrlich zu sein nicht ganz sicher, wie genau Variablen in
> Hardware umgesetzt werden.
Im Idealfall: gar nicht. Sie sind nur Hilfskonstrukte innerhalb von 
Prozessen.

Und wenn doch aml eine Variable was speichern soll: Augen auf, da ist 
schnell mal was passiert. Und wieder gilt: natürlich sind Variablen 
hilfreich, wenn man weiß was daraus wird...

Siehe dazu den Beitrag "Variable vs Signal"

von Hanswurst (Gast)


Lesenswert?

Ich meine ich habe Deine Beschreibung möglicherweise nicht verstanden, 
aber ich würde sie gerne verstehen.
Der Code deutet darauf hin, das es zwei Bereiche zwischen 0 (bzw. 
MIN_INT) und const1 und zwischen 0 und const2 gibt. Ist das so richtig?

Was das hier betrifft:
> Nimm den Weg, von dem du weißt, was du tust! Also in meinem Fall:
> bleibe bei dem "bekannten" Schieberegister und versuche nicht
> etwas zu "optimieren" und verwende Konstrukte, von denen du
> nicht weißt, was eigentlich dahinter steht.

Dieser Grundsatz hat den Nachteil, dass Du bei dem stehenbleibst, was Du 
weißt und nichts neues lernst - wenn man ihn denn wörtlich nimmt.

Schaue doch einfach immer wieder nach, was denn tatsächlich bei der 
Synthese erzeugt wird. Dann erfährst, was "eigentlich dahinter" steht.

Um auf das unmittelbare Problem einzugehen:
Variablen sind Dinge, die nicht synthetisiert werden.
Du siehst zwar in der Simulation ein plausibles Resultat, aber nur weil 
der Simulator eben auch die Variablen simuliert. Eine Variable 
beschreibt aber keine Hardware.
Variablen und Funktionen dienen dazu "Zwischenrechnungen" im VHDL-Code 
auszuführen die dann in der Regel (aber nicht zwingend) wieder in 
synthetisierbaren Anweisungen verwendet werden. Sozusagen, ein 
Schmierzettel im Code.

Ein einfacher Fall ist etwa der, dass Du lediglich einen Maximalwert zur 
Verfügung hast, der von einem Signal dargestellt werden soll. Etwa 15.
Mit einer Funktion kannst Du nun daraus die Breite des Vektors in Bit 
ermitteln. Etwa mit Breite := log2(n+1). So, und damit kannst Du einen 
Vektor deklarieren: signal DataBus : Bit_vector((Breite - 1) downto 0);
(Das ist ein eher künstliches Beispiel, geht auch anders. Es soll nur 
ein Beispiel sein). So ähnlich wie Du es mit Generics tun würdest.

Grundsätzlich aber wird in den VHDL-Lehrbüchern auch gesagt, was 
synthetisierbar ist (wobei man die Handbücher der jeweiligen Synthesizer 
auch lesen sollte, weil das noch eine Untermenge von dem theoretisch 
möglichen sein kann).

Meinem Eindruck nach, wird in den Foren von Variablen selten 
ausdrücklich gesagt inwiefern sie sich in der Hardware niederschlagen 
oder eben nicht, solange ein TO nicht ausdrücklich damit ein Problem 
hat. Meist haben die TOs eher ein "Problem" damit, dass die 
Variablenwerte scheinbar nicht berücksichtigt werden. Aber eine Suche 
nach "Variable wird nicht synthetisiert" oder ähnliches (auch auf 
englisch) wird dazu wohl einige Diskussionen finden, vermute ich.

Viel Erfolg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Hanswurst schrieb:
> Eine Variable beschreibt aber keine Hardware.
Oh doch. Lass mal einen Takt auf sie los. Hastdunichtgesehen erscheinen 
überraschenderweise Flipflops. Oder schlimmer noch: ganz zufällig wird 
bei einer schlechten Beschreibung die Variable in ein Latch 
verwandelt...

Hanswurst schrieb:
> Schaue doch einfach immer wieder nach, was denn tatsächlich bei der
> Synthese erzeugt wird. Dann erfährst, was "eigentlich dahinter" steht.
Ich schaue schon deshalb nach, um zu kontrollieren, ob denn der 
Synthesizer meine Beschreibung meiner Hardware verstanden und richtig 
umgesetzt hat.

Denn das bedeutet HDL ja: Beschreibungssprache. Ich beschreibe damit 
die Hardware, die ich mir ausgedacht habe. Und hinterher sollte der 
Synthesizer wieder diese Hardware draus machen.

So wie eine Wegbeschreibung: ich beschreibe jemandem mit Worten, wo es 
irgendwo hingeht. Und letztlich wäre es auch interessant, zu wissen, ob 
der dort auch ankommt. Wenn der alle falsch ankommt, dann ist meine 
Beschreibung schlecht. Oder ich beschreibe unnötige Umwege oder schicke 
ihn auf nicht passierbare Wege.

: Bearbeitet durch Moderator
von Dominik (Gast)


Lesenswert?

Vielen Dank nochmal für die Kommentare! Ihr habt natürlich beide recht. 
Ich schaue mir tatsächlich viel zu selten die synthetisierte Hardware 
an. Und per se neue Wege auszuschließen, ist natürlich auch Quatsch.

@Hanswurst: eine etwas ausführlichere Beschreibung, was ich umsetzen 
wollte: ich habe einen Motor, der sich mit einer gewissen 
Geschwindigkeit dreht. Diese Geschwindigkeit bekomme ich als Integer 
übergeben und sie kann sich ständig ändern (oben mit int1 bezeichnet). 
In Abhängigkeit davon, in welchem Bereich (mehrere Bereiche möglich, 
über verschiedene Konstanten const1, ... definiert) sich die 
Geschwindigkeit gerade bewegt, müssen bestimmte Parameter angepasst und 
ein Signal (neuer_zustand) gesendet werden, dass sich die Parameter 
ändern sollen. Dieses Signal soll aber nur gesetzt werden, wenn sich die 
Geschwindigkeit so weit verändert hat, dass sie sich in einem neuen 
Bereich bewegt hat und nicht bei jeder Änderung der Geschwindigkeit.
Das ganze wollte ich mit dem oben beschriebenen Weg 2 "Vergleich 
Variable und Signal" umsetzen, weil es mir hier einfacher vorkam als ein 
Schieberegister zu verwenden. Aber ich war nicht sicher, ob es 
tatsächlich in Hardware funktionieren würde.

von Hanswurst (Gast)


Lesenswert?

Danke für Deine ausführliche Beschreibung.
Was ich vor allem verstehen wollte:

> Der Code deutet darauf hin, das es zwei Bereiche zwischen 0 (bzw.
> MIN_INT) und const1 und zwischen 0 und const2 gibt. Ist das so richtig?

D.h. sind die Bereiche entweder durch zwei beliebige Konstanten begrenzt 
oder sind sie es einerseits durch das Minimum des Zahlenbereiches und 
andererseits durch eine Konstante?

Anders ausgedrückt: Ein "Bereich" wird durch ZWEI Angaben festgelegt, 
nicht nur durch eine. Und wenn Du nur eine nennst, dann ist die zweite 
plausibel nur durch die Intervallgrenze bestimmt, die sich aus dem 
Zahlenbereich ergibt.

Das hat eine Auswirkung auf die Implementierung. Denn wenn sich die 
Bereiche überschneiden (können), - und im zweiten Fall tun sie es per 
Definition -, dann brauchst Du oder brauchst Du nicht, so etwas wie 
einen Prioritätsencoder.

Du hast ja vielleicht daran gedacht und eine Antwort befriedigt 
lediglich meine Neugier, aber der Code gibt keine Antwort darauf oder er 
ist unabsichtlich unvollständig.

von Dominik (Gast)


Lesenswert?

Das stimmt, das hatte ich nicht erwähnt. Der Bereich soll wie folgt 
aufgeteilt werden:
Minimum des Zahlenbereiches bis const1 = Bereich 1
const1 bis const2 = Bereich 2
const2 bis const3 = Bereich 3 usw.

von Hanswurst (Gast)


Lesenswert?

Aha. Danke.

Viel Erfolg.

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.