Hallo Gemeinde,
Thema VHDL:
Ich versuche gerade, mir eine Vorstellung einer Variable vs. Signal zu
machen.
Gebetsmühlenartig wird auf diversen Seiten heruntererzählt, dass eine
Variable sofort bei der Zuweisung ihren Wert erhält. Das mag sein. Wenn
man sich folgende Seite anschaut, klingt das auch gut und schön:
https://www.nandland.com/vhdl/tips/variable-vs-signal.html
Was mir nicht in den Kopf will, ist die Zeile 25 des ersten Listing:
1
v_Count:=v_Count+1;-- Variable
Woher nimmt v_Count seinen aktuellen Wert? Er wird doch nirgends
gespeichert? Dazu muss doch eine Zuweisung von einem Signal stattfinden?
Ist dieses Design überhaupt synthetisierbar?
Ich käme auch nicht auf die Idee, einer Variablen bei der Deklaration
einen Startwert zu verpassen?
Nach meiner Auffassung sind Variablen "lediglich" zur Speicherung von
Zwischenergebnissen tauglich.
Ich habe den Verdacht, dass sich der Einsatzbereich von Variablen in
synthetisierbaren Designs massiv verändert, aber mit keinem Wort darauf
eingegangen wird?
Eddy C. schrieb:> Woher nimmt v_Count seinen aktuellen Wert? Er wird doch nirgends> gespeichert?
Doch: v_Count (genau wie r_Count) wird in einem Register gespeichert.
Das ist durch die Struktur des Prozesses festgelegt und das gilt sowohl
für die Variable wie auch für das Signal.
Der Unterschied ist: wenn lesend auf das Signal zugegriffen wird, dann
ist immer der Ausgang dieses Registers gemeint (egal an welcher Stelle
des Prozesses der Lesezugriff steht).
Wenn lesend auf die Variable zugegriffen wird, dann ist damit einmal der
Ausgang des Registers gemeint (in Zeile 25 des Listings) und das andere
mal der um 1 erhöhte Ausgang des Registers (in Zeile 29 des Listings).
Eddy C. schrieb:> Ich käme auch nicht auf die Idee, einer Variablen bei der Deklaration> einen Startwert zu verpassen?
Mit irgendeinem Wert muss das Register, das den Variablenwert
repräsentiert, aber loslaufen. Hier wird es eben auf 0 initialisiert.
Eddy C. schrieb:> Nach meiner Auffassung sind Variablen "lediglich" zur Speicherung von> Zwischenergebnissen tauglich.
Die Einsatzmöglichkeiten für Variablen sind "speziell". Meine meisten
Designs kommen ohne Variablen aus. Manchmal erleichtern sie aber die
Arbeit.
Eddy C. schrieb:> Ich habe den Verdacht, dass sich der Einsatzbereich von Variablen in> synthetisierbaren Designs massiv verändert, aber mit keinem Wort darauf> eingegangen wird?
Wo siehst du diese Veränderung? (Meinst du "heute" werden Variablen
anders eingesetzt als "früher"? Was vergleichst du konkret um zu diesem
Verdacht zu kommen?)
Achim S. schrieb:> Doch: v_Count (genau wie r_Count) wird in einem Register gespeichert.> Das ist durch die Struktur des Prozesses festgelegt und das gilt sowohl> für die Variable wie auch für das Signal.
Das war mir bis jetzt nicht bewusst.
> Der Unterschied ist: wenn lesend auf das Signal zugegriffen wird, dann> ist immer der Ausgang dieses Registers gemeint (egal an welcher Stelle> des Prozesses der Lesezugriff steht).
Richtig.
> Wenn lesend auf die Variable zugegriffen wird, dann ist damit einmal der> Ausgang des Registers gemeint (in Zeile 25 des Listings) und das andere> mal der um 1 erhöhte Ausgang des Registers (in Zeile 29 des Listings).
Schwer vorstellbar.
> Eddy C. schrieb:>> Ich käme auch nicht auf die Idee, einer Variablen bei der Deklaration>> einen Startwert zu verpassen?>> Mit irgendeinem Wert muss das Register, das den Variablenwert> repräsentiert, aber loslaufen. Hier wird es eben auf 0 initialisiert.
Das ist nachvollziehbar, wenn hinter der Variablen real existierende
Hardware steckt.
> Eddy C. schrieb:>> Ich habe den Verdacht, dass sich der Einsatzbereich von Variablen in>> synthetisierbaren Designs massiv verändert, aber mit keinem Wort darauf>> eingegangen wird?>> Wo siehst du diese Veränderung? (Meinst du "heute" werden Variablen> anders eingesetzt als "früher"? Was vergleichst du konkret um zu diesem> Verdacht zu kommen?)
Ich bezog mich auf einen Vergleich von synthetisierbaren zu nicht
synthetisierbaren Designs. In letzteren sitzt ja noch ein Computer
dahinter der mitrechnen kann. In nicht synthetisierbaren Designs mag es
hilfreich sein, eine Testumgebung mit Hilfe von Variablen zu erschaffen,
was aber offensichtlich eine Fehleinschätzung meinerseits ist.
Wenn es stimmt, was Du sagst, müsste das Beispiel synthetisierbar sein.
Eddy C. schrieb:> Nach meiner Auffassung sind Variablen "lediglich" zur Speicherung von> Zwischenergebnissen tauglich.
besonders im 1-prozess-Stil kann man variablen für kombinatorische
Beschreibungen verwenden. Hiermit dient v_counter als Zwischenergebnis,
es wird jedoch keine Register erzeugen.
1
process(clk)
2
begin
3
ifrising_edge(clk)then
4
ifsig_counter=0thenstate=IDLE;endif;
5
v_counter:=v_counter+1;
6
sig_counter<=v_counter;
7
endif;
8
endprocess;
anders kann man Variablen auch als Speicherelemente verwenden:
1
process(clk)
2
begin
3
ifrising_edge(clk)then
4
ifv_counter=0thenstate=IDLE;endif;
5
v_counter:=v_counter+1;
6
endif;
7
endprocess;
jedoch sind Variablen mit Vorsicht zu genießen. Es lassen sich leicht
ungewollte oder verwirrende Beschreibung erzeugen, die auch schlechte
Syntheseergenisse liefern. Mit Signalen ist man meist zu einer klareren
Struktur gezwungen.
Vielleicht zeigt dieses Beispiel die Problematik:
1
process(clk)
2
begin
3
ifrising_edge(clk)then
4
v_counter:=v_counter+1;
5
ifv_counter=0thenstate=IDLE;endif;
6
endif;
7
endprocess;
in diesem Beispiel wird bereits der neue Wert für den State geprüft.
Dies ist ungünstig, da dies einen langen kombinatorischen Pfad aus
Addier+Vergleich erzeugt.
Weitere Fehlerquellen sind Variablen als Zwischenergebnisse zu
verwenden, die jedoch unabsichtlich doch einen Speicher erzeugen.
Prinzipiell verwende ich Variablen gerne in Testbenches, aber selten im
Design.
Eddy C. schrieb:> Schwer vorstellbar.
Stell dir einfach ein Register vor, das den Wert von v_Count speichert.
Und dahinter ein Logiknetz, dass den Wert des Registers+1 berechnet.
Diese Logiknetz brauchst du ohnehin für die Zuweisung in Zeile 25. In
Zeile 29 wird jetzt einfach der Ausgang des Logiknetzes betrachtet.
So wäre das zumindest einfach vorstellbar. Tatsächlich umsetzen wird es
das Synthesetool wahrscheinlich anders (indem es den Ausgang des
Registers mit 4 vergleicht statt den Ausgang des Addiernetzwerks mit 5).
Wie genau es tatsächlich umgesetzt wurde kannst du dir als RTL-Ansicht
von deiner Entwicklungsumgebung anzeigen lassen.
Eddy C. schrieb:> Ich bezog mich auf einen Vergleich von synthetisierbaren zu nicht> synthetisierbaren Designs.
Ok, jetzt verstehe ich den Kommentar.
Eddy C. schrieb:> In nicht synthetisierbaren Designs mag es> hilfreich sein, eine Testumgebung mit Hilfe von Variablen zu erschaffen,
Korrekt: in Testbenches nutzt man typisch viel häufiger Variablen als in
synthetisierbarem Code.
Eddy C. schrieb:> Wenn es stimmt, was Du sagst, müsste das Beispiel synthetisierbar sein.
Ich sehe auf den ersten Blick nichts, was dagegen spräche.
Ich glaube das ist aussichtslos. Viele Frager sind zu faul zum suchen
und stellen dieselben überflüssigen fragen immer wieder. In Büchern und
an Hochschulen wird das sehr genau erklärt, was da passiert und wie man
es nutzt, aber stattdessen reimt sich jeder selbst was zusammen oder
entnimmt sein Wissen den YT-Videos mit ihren alternativen Fakten.
Ich bewundere die Gleichmut Lothars, immer wieder darauf zu reagieren.
Eddy C. schrieb:>> Wenn lesend auf die Variable zugegriffen wird, dann ist damit einmal der>> Ausgang des Registers gemeint (in Zeile 25 des Listings) und das andere>> mal der um 1 erhöhte Ausgang des Registers (in Zeile 29 des Listings).> Schwer vorstellbar.
Warum? Der Addierer "plus eins" ist doch sowieso im Design. Da kann ohne
Weiteres im selben Taktzyklus auf beide Werte zugreifen....
Weltbester FPGA-Pongo schrieb im Beitrag #5626228:
> In Büchern und an Hochschulen wird das sehr genau erklärt, was da> passiert
Ja, aber ganz oft so unbändig abstrakt, dass man meint, da müsste
unheimlich komplizierte Technik dahinterstecken.
Lothar M. schrieb:> Ich verweise da mal auf den Klassiker:> Beitrag "Variable vs Signal"
Ausgezeichnet!
Lothar M. schrieb:> Warum? Der Addierer "plus eins"
Ja, das mag sein. Dann ist in diesem Zusammenhang eine Variable aber
auch nicht mehr als ein Zwischenwertspeicher, z.B. so:
1
process(clk)
2
variableshift:unsigned(7downto0);
3
begin
4
ifrising_edge(clk)then
5
shift:=ss_shift(6downto0)&mosi;
6
ifss_bitno<7then
7
ss_shift<=shift;
8
else
9
ss_rxdata<=shift;
10
endif;
11
endif;
12
endprocess;
Wenn das so i.O. ist, ist das sicherlich ein netter Anwendungsfall.
Insbesondere kommt dabei aber der ggf. vorhandene Speichercharakter
nicht zum Vorschein (was ich hier sogar hoffe)
Klakx schrieb:> Prinzipiell verwende ich Variablen gerne in Testbenches, aber selten im> Design.
Was Du schreibst, geht in meine Richtung. Oft sitzt man doch brütend vor
dem Bildschirm und überlegt, ob man hie oder da nicht doch versehentlich
ein Register erzeugt hat. Und wenn dann noch Variablen ins Spiel kommen,
wird es gerade für Einsteiger endgültig unübersichtlich.
Eddy C. schrieb:> Ja, das mag sein. Dann ist in diesem Zusammenhang eine Variable aber> auch nicht mehr als ein Zwischenwertspeicher, z.B. so:
prinzipiell richtig. Aber jetzt stell dir mal vor, die Zuweisung auf
diese Variable steht irgendwo mitten im Prozess. Und dann stell dir mal
vor, du 'benutzt' sie weiter oben und du 'benutzt' sie auch weiter
unten.
Das macht Variablen so sau gefaehrlich...
Eddy C. schrieb:> Insbesondere kommt dabei aber der ggf. vorhandene Speichercharakter> nicht zum Vorschein (was ich hier sogar hoffe)
Eine Variable hat keinen "Speichercharakter". Es ist einfach so, dass
die Variable den "alten" Wert behält, wenn man sie im Prozess liest, vor
ihr ein Wert zugewiesen wird.
Allein dieses "Lesen vor dem Schreiben" macht quasi eine "Static"
Variable aus ihr.
Mein Vorschlag bei solchen Diskussionen: einfach mal den RTL Schaltplan
ansehen. Dann sieht man, was der Synthesizer aus der Beschreibung macht.
Und dann sieht man auch, ob das was mit der Schaltung zu tun hat, die
man mit VHDL beschrieben hat.
Lothar M. schrieb:> Allein dieses "Lesen vor dem Schreiben" macht quasi eine "Static"> Variable aus ihr.
Sehr schön. Aber damit wird sie doch zum Register! Und das meine ich,
wenn ich von Speichercharakter spreche. Und das ist es auch, was in
meinem Beispiel oben gezeigt wird. Wo liegt hier das Missverständnis?
Eddy C. schrieb:> Aber damit wird sie doch zum Register!
Die Variable bleibt weiterhin eine Variable. VHDL legt nämlich nicht
fest, wie ein Signal oder eine Variable in der Hardware abgebildet wird.
Wenn ein Signal rein kombinatorisch verwendet wird, dann wird es ja auch
nicht registriert.
Du beschreibst mit VHDL ein Verhalten und der Synthesizer versucht,
dieses Verhalten in Hardware umzusetzen. Wenn da ein Takt beteiligt ist,
und das Signal oder die Variable taktsynchron speichern soll, dann
werden die in ein Register umgesetzt. Wenn sie kombinatorisch speichern
sollen, dann wird ein Latch daraus. Und wenn gar nichts gespeichert
wird, dann bleiben sie einfach Kombinatorik und werden ggfs. einfach
wegoptimiert.
> Wo liegt hier das Missverständnis?
Vorrangig darin, dass du ein bestimmtes Verhalten und eine bestimmte
Umsetzung /erwartest/:
>>>> Nach meiner Auffassung sind Variablen "lediglich" zur Speicherung von>>>> Zwischenergebnissen tauglich.
Es schadet allerdings nichts, wenn du Variablen tatsächlich in diesem
Sinne weiterverwendest und der Variablen vor dem ersten Lesen im Prozess
einen Wert z.B. von einem Signal zuweist. Du kannst dir damit einige
unliebsame Überraschungen sparen.
Eddy C. schrieb:>>>> Ich käme auch nicht auf die Idee, einer Variablen bei der Deklaration>>>> einen Startwert zu verpassen?
Das wäre aber bei einer speichernden Variablen durchaus sinnvoll.
Genauso wie bei einem speichernden Signal.
Wenn du nichts weiter angibst, dann wird jedes Signal und jede Variable
"automatisch" initalisiert. Im Fall von std_logic oder signed/unsigned
ist das der "linkeste" Wert der Aufzählung, hier "U". Im Falle eines
Integers ist das der niedrigste darstellbare Wert.
Und richtig, wie angemerkt steht das in jedem VHDL-Buch. Und in den
brauchbareren Anleitungen, die im Netz zu finden sind:
https://www.tu-ilmenau.de/fileadmin/public/iks/files/lehre/ihs/VHDL_Kurzbeschreibung.pdf
Eddy C. schrieb:> Sehr schön. Aber damit wird sie doch zum Register! Und das meine ich,> wenn ich von Speichercharakter spreche. Und das ist es auch, was in> meinem Beispiel oben gezeigt wird. Wo liegt hier das Missverständnis?
Ich denke, Du knabberst hier am falschen Problem rum (das gar keins
ist).
Mach' dir klar: eine Variable existiert nur innerhalb eines Prozesses.
Wenn Du also in der realen Welt (Synthese) willst, daß deine Variable
irgendwelche Auswirkungen hat, mußt Du sie irgendwie "nach außen"
bringen - das geht nur, indem Du sie entweder direkt einem Signal
zuweist oder in einer arithmetischen Operation mit einem Signal
"verwurstest" - ansonsten existiert sie einfach nicht.
Damit läuft's wieder auf "Zwischenergebnis" raus und es ist eigentlich
völlig unerheblich, ob sie "speichernd" ist oder nicht.
Lothar M. schrieb:> Und richtig, wie angemerkt steht das in jedem VHDL-Buch. Und in den> brauchbareren Anleitungen, die im Netz zu finden sind:> https://www.tu-ilmenau.de/fileadmin/public/iks/files/lehre/ihs/VHDL_Kurzbeschreibung.pdf
Da hast Du dir aber eine didaktisch fragwürdige Anleitung als Beispiel
ausgesucht, Lothar ;)
Die empfiehlt (auf Seite 20), auf Signale in Prozessen zu verzichten
(weil die "oft" zu "unerwarteten Ergebnissen" führen würden) und
stattdessen Variablen zu verwenden.
So ziemlich genau das Gegenteil von dem, was Du uns beizubringen
versuchst ;)
Achim S. schrieb:> Eddy C. schrieb:>> In nicht synthetisierbaren Designs mag es>> hilfreich sein, eine Testumgebung mit Hilfe von Variablen zu erschaffen,>> Korrekt: in Testbenches nutzt man typisch viel häufiger Variablen als in> synthetisierbarem Code.
In meinem Fall nicht ... Ich nutze in Prozessen meist Variablen und
weise sie dann Signalen zu, wenn sie außerhalb des Prozesses gebraucht
werden.
Beispiel:
Macht sowas mal nur mit Signale xD
Als temporäre Register sind Variablen perfekt.
In diesem Fall dürfte dieses curl_state_low und curl_state_high keine
Variable sein, weil es sonst nicht mehr funktionieren würde.
Hier nutzt man die Tatsache, dass Werte, die Signalen zugewiesen wurden,
erst im nächsten "Durchlauf" gelesen werden können - so überschreibt man
sich quasi nichts in der loop.
Markus F. schrieb:> Da hast Du dir aber eine didaktisch fragwürdige Anleitung als Beispiel> ausgesucht, Lothar ;)
Mann, echt blöd, was man im Netz so alles findet. Auf der Seite 36
offenbart der Autor nochmal, das er das "schöne" Verhalten von Signalen,
ihren Wert erst am Prozessende zu ändern, nicht erkannt hat und deshalb
nicht in der Praxis anwenden kann.
Nach einem zweiten Blick auf dieses überaus akademische Dokumanet
schlage ich vor, daraus nur die untere Hälfte der Seite 20 anzusehen...
;-)
Der Rest, in dem vorrangig unnötigerweise nur mit Variablen und zudem
mit symbolischen Verzögerungen (wie z.B. a := not b after 1.5 ns; )
gearbeitet wird, ist eigentlich nur für die Simulation brauchbar.
Symbolische Verzögerungen verwendet nur der, der die Idee des synchronen
Designs nicht verstanden hat.
Mampf F. schrieb:> when 2 =>> ...> Macht sowas mal nur mit Signale xD
Ich kann da nichts sehen, dass das mit Signalen nicht auch möglich wäre.
Die Variablen sorgen doch lediglich dafür, dass die langen Tabellennamen
lesbar werden. Aber warum hast du für "curl_state_low(index_table(I+1)"
nicht auch eine Variable deklariert?
Lothar M. schrieb:> Mampf F. schrieb:>> when 2 =>>> ...>> Macht sowas mal nur mit Signale xD> Ich kann da nichts sehen, was mit Signalen hier nicht möglich wäre.> Die Variablen sorgen lediglich dafür, dass die langen Tabellennamen> lesbar werden.
Ja genau - darauf wollte ich hinaus.
Gibt Menschen, die verzichten auf Variablen aus Prinzip - auch dort, wo
sie von Vorteil sein können.
Lothar M. schrieb:> Aber warum hast du für "curl_state_low(index_table(I+1)"> nicht auch eine Variable deklariert?
Das ist einem Port von Java nach VHDL geschuldet - ich hab es einfach so
übernommen.
Markus F. schrieb:> Lothar M. schrieb:>> Und richtig, wie angemerkt steht das in jedem VHDL-Buch. Und in den>> brauchbareren Anleitungen, die im Netz zu finden sind:>>> https://www.tu-ilmenau.de/fileadmin/public/iks/files/lehre/ihs/VHDL_Kurzbeschreibung.pdf>> Da hast Du dir aber eine didaktisch fragwürdige Anleitung als Beispiel> ausgesucht, Lothar ;)>> Die empfiehlt (auf Seite 20), auf Signale in Prozessen zu verzichten> (weil die "oft" zu "unerwarteten Ergebnissen" führen würden) und> stattdessen Variablen zu verwenden.>> [...]
Wenn man den vorhergehenden Absatz einbezieht, dann empfiehlt der Text
das nicht grundsätzlich, sondern in Zusammenhang mit der Tatsache, dass
Änderungen an Registern bzw. Zuweisungen die synthetisiert werden
(können) zu vermeiden sind, weil eventuelle Unklarheiten über das
auslösende Ereignis bestehen, wenn man mehrstufige Berechnungen mit
Zwischenwerten durchführt.
Das ist genau die andere Seite der selben Medaille: Man wundert sich am
Anfang auch gerne mal, warum alle Variablenzuweisungen und
Zwischenrechnungen scheinbar instantan (nach dem auslösenden Ereignis)
stattfinden; daß diese Zwischenschritte für sich genommen, keine
Auslöser zu brauchen scheinen.
Insgesamt beziehen sich beide Absätze also auf den Fall der Unsicherheit
wann eine Variablenzuweisung und wann eine Registersetzung erfolgt.
Man man evtl. einräumen, dass diese Unsicherheit unter den meisten
Anfängern so verbreitet ist, dass gewisse Hinweise etwas tendenziös
sind; die didaktische Absicht aber ist in dem Text korrekt ausgedrückt,
meine ich.
Komplexe Zusammenhänge kann man in einem komplexen Satz oder in mehreren
einfacheren, aber zusammenhängenden (Ab-) Sätzen formulieren.
Es ist zweckmässig solche textuellen Zusammenhänge zu erkennen und zu
akzeptieren.
Theor schrieb:> Wenn man den vorhergehenden Absatz einbezieht, dann empfiehlt der Text> das nicht grundsätzlich, sondern in Zusammenhang mit der Tatsache, dass> Änderungen an Registern bzw. Zuweisungen die synthetisiert werden> (können) zu vermeiden sind, weil eventuelle Unklarheiten über das> auslösende Ereignis bestehen, wenn man mehrstufige Berechnungen mit> Zwischenwerten durchführt.
Hast Du den Text mitverfaßt oder widersprichst Du aus Prinzip ;) ?
Wenn ich nicht schon wüsste, was der grundsätzliche Unterschied zwischen
Variablen und Signalen ist, würde ich es jedenfalls mit dem Text nicht
verstehen.
Der Text ist nicht falsch, aber m.E. fehlt die fundamentale Information,
daß
1
v:=v+1;
2
v:=v+1;
was völlig anderes ist, als
1
s<=s+1;
2
s<=s+1;
Wenn ich das verstanden habe, verstehe ich auch den Rest. Aber nicht
notwendigerweise andersrum.
Markus F. schrieb:> Theor schrieb:>> [...]>> Hast Du den Text mitverfaßt oder widersprichst Du aus Prinzip ;) ?
Öhm ... https://xkcd.com/2051/ ;-)
> Wenn ich nicht schon wüsste, was der grundsätzliche Unterschied zwischen> Variablen und Signalen ist, würde ich es jedenfalls mit dem Text nicht> verstehen.
Vermutlich versteht man das nicht allein aus dieser einen Stelle.
> Der Text ist nicht falsch, aber m.E. fehlt die fundamentale Information,> daß [...]
Hm. Als ein Hinweis könnte der Anfang des fraglichen vorherigen Absatzes
gelten:
"Um den zeitlichen Charakter der Signalzuweisung hervorzuheben, wird
auch ein anderer Zuweisungsoperator als bei Variablen benutzt ..."
(Hervorhebung von mir).
Theor schrieb:> "Um den zeitlichen Charakter der Signalzuweisung hervorzuheben, wird> auch ein anderer Zuweisungsoperator als bei Variablen benutzt ..."
;)
https://xkcd.com/386/
Aha. Wenn da jetzt noch stünde, wie Variablen vs Signale gelesen
werden - ich finde mein Beispiel irgendwie eingängiger
Hallo an alle, die hier wertvolle Beispiele gegeben haben: Ich bin der
Sache ein gutes Stück näher gekommen. Insbesondere die Tatsache, dass
eine Variable alleine noch keinerlei Logik oder Register erzeugt ist für
meine Vorstellung wichtig: Erst die Zuweisung an ein Signal macht den
Wert oder dessen Auswirkung überhaupt sichtbar. Sehr anschaulich Dein
Minibeispiel, Markus aber auch die krassere Version von Mampf, die in
letzter Konsequenz zeigt, wofür Variablen sinnvoll einsetzbar sind.
Jetzt mal abgesehen von der Menge Logik, die damit in wenigen Zeilen
produziert wird.