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
ifrising_edge(clk)then
2
ifint1<const1then
3
bereich_sig<=bereich1;
4
bereich_var:=bereich1;
5
elsifint1<const2then
6
bereich_sig<=bereich2;
7
bereich_var:=bereich2;
8
elsif
9
...
10
endif;
11
12
ifbereich_sig/=bereich_varthen
13
neuer_zustand<='1';
14
else
15
neuer_zustand<='0';
16
endif;
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.
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:
alt_bereich<=akt_bereichwhenrising_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_bereichwhenrising_edge(clk);-- für später merken
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.
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"
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
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.
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.
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.
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.