Vielleicht sind hier Experten, die mir beantworten können wann man für
einen Zähler in meinem Fall besser variable oder signal nimmt. In einem
Prozess zähle ich hoch bis der Zählwert erreich ist und prüfe das in
einer state mashine. Wenn ich in einem Zustand eine Variable um 1 erhöhe
und prüfe, ob ein Wert erreich wurde geschieht dies bei Variablen ja
sofort. Das heißt ja auch, dass da nichts registered ist und das bei
einem 32 bit Zähler zu glitches kommen kann. Wann also benutzt man
jemals Variablen in VHDL?
Gustav G. schrieb:> Das heißt ja auch, dass da nichts registered ist und das bei> einem 32 bit Zähler zu glitches kommen kann.
Ne, das stimmt so nicht. Änderungen von Signal und Variable werden zwar
beim Syntheserun (und im Simulator) zu unterschiedlichen Zeitpunkten
wirksam. Aber wenn du den Zähler taktsynchron beschreibst, dann wird
auch bei Nutzung einer Variablen in der Hardware ein taktsynchroner
Zähler daraus.
Wenn du innerhalb des taktsynchronen Prozesses die Variable mehrfach
änderst, dann arbeitest du im Prozess mit unterschiedlichen
Zählerständen - aber in der Hardware ändert sich der Wert des Zählers
ändert trotzdem nur immer genau zur Taktflanke.
Z.B. in folgendem Code:
zaehler wird bei jeder Taktflanke um 2 hochzählen. Vergleich1 und
Vergleich2 werden im identischen Takt auf '1' gehen. Dass sie innerhalb
des Prozesses unterschiedliche Zählerstände abfragen berücksichtigt das
Synthesetool, indem es in der Hardware den Vergleich auf
unterschiedliche Zählerstände durchführt (auf den im Register
gespeicherten Zählerstand+1 und auf den gespeicherten Zählerstand+2).
Gustav G. schrieb:> wann man für einen Zähler in meinem Fall besser variable oder signal> nimmt.
Mann nimmt immer ein Signal, ausser man braucht unbedingt eine Variable.
Gustav G. schrieb:> Das heißt ja auch, dass da nichts registered ist und das bei einem 32> bit Zähler zu glitches kommen kann.
Probiers doch einfach mal aus und mache 2 funktionsgleiche Zähler, 1 mit
einem Signal als Zählerregister und 1 mit einer Variablen. Vergleiche
die beiden RTL Schaltpläne.
> Wenn ich in einem Zustand eine Variable um 1 erhöhe und prüfe, ob ein> Wert erreich wurde geschieht dies bei Variablen ja sofort.
Alles, was in 1 Prozess (mit Sensitivliste) zwischen dem Anfang und dem
Ende steht, passiert sofort und gleichzeitig. Bei Prozessen ohne
Sensitivliste passiert alles gleichzeitig beim jeweils nächsten wait.
Und zwar jeweils unabhängig davon, ob da Signale oder Variablen
verwendet werden.
Lothar M. schrieb:> Gustav G. schrieb:>> wann man für einen Zähler in meinem Fall besser variable oder signal>> nimmt.> Mann nimmt immer ein Signal, ausser man braucht unbedingt eine Variable.
Es gibt gute Gruende auf Variablen zu setzen auch wenn sie aequivalente
Synthese Resultate zu einem Signal erzielen.
Ein Grund ist zum Beispiel die Design Practice "Keep Things Local". Wenn
ich einen Zaehler habe ist das z.B. ein super Beispiel dafuer eine
Variable zu nehmen. Macht den Code deutlich lesbarer, Stichwort "Clean
Code"
Solche "Bauernregeln" nach dem Motto "mach immer dies" und "mach immer
das" sind einfach nicht zielfuehrend. Man muss verstehen was man macht,
welche Resultate das bedingt und sich dann fuer die optimale Loesung
entscheiden. Das ist fuer Anfaenger sicher nicht einfach und klar, jedem
Anfaenger sollte man raten erstmal die Dinge mit Signalen zu loesen.
Aber zu betonen dass die Dinge so gemacht werden muessen, ist einfach
nur Unfug. Aufklaerung ist einfach besser als Religion. ;-)
Dennis E. schrieb:> Lothar eben.
Zu mehr reicht es nicht?
Tobias B. schrieb:> zum Beispiel die Design Practice "Keep Things Local".
Hört sich ein wenig nach einer englischen Bauernregel an...
> Wenn ich einen Zaehler habe ist das z.B. ein super Beispiel dafuer eine> Variable zu nehmen.> Macht den Code deutlich lesbarer, Stichwort "Clean Code"
Diese ganzen neudeutschen Schlagworte mögen für die üblichen
Softwareprogrammiersprachen schon passen. Ich würde aber ein Signal in
VHDL nicht als "ugly code" bezeichnen.
Und gerade speichernde Variablen sind schon so manchem zur Stolperfalle
geworden. Siehe diesen altbekannten Tread:
Beitrag "Re: Variable vs Signal"
Aber meinetwegen darf jeder in VHDL gerne wie von C gewohnt mit
Variablen programmieren. Es ist ja nicht so, dass ich mir damit eine
blutige Nase hole.
Tobias B. schrieb:> Aufklaerung ist einfach besser als Religion. ;-)
Dann habe ich da mal einfach ohne groß nachzudenken als erstbestes
Beispiel zwei 8-Bit-Zähler implementiert, einem mit einem Signal als
Counter und einen mit einer Vraiablen. Meine Idee war, dass dabei ja
wohl das gleiche herauskommen dürfte:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
4
entitySig_vs_Varis
5
Port(clk:inSTD_LOGIC;
6
cnt1:outintegerrange0to255;
7
cnt2:outintegerrange0to255);
8
endSig_vs_Var;
9
10
architectureBehavioralofSig_vs_Varis
11
signalca:integerrange0to255:=0;
12
begin
13
14
processbegin
15
waituntilrising_edge(clk);
16
ca<=ca+1;
17
ifca=99thenca<=0;
18
endif;
19
endprocess;
20
cnt1<=ca;
21
22
process
23
variablecb:integerrange0to255:=0;
24
begin
25
waituntilrising_edge(clk);
26
cb:=cb+1;
27
ifcb=99thencb:=0;
28
endif;
29
cnt2<=cb;
30
endprocess;
31
32
endBehavioral;
Insgesamt das gleiche Ergebnis(**), aber holla: der cnt2 hat 2 solcher
8-bit-Registersätze.
Klar, die Zuweisung an cnt2 ist ja auch getaket. Blöd aber auch, da kann
ich meinen "wait until"-Stil gar nicht beibehalten. Schade... :-/
(**) für die Screenshots des Synplify-RTL-Viewers habe ich jeweils einen
der beiden Prozesse auskommentiert
Gut, umgestellt auf den old-school Stil mit "if rising_edge":
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
4
entitySig_vs_Varis
5
Port(clk:inSTD_LOGIC;
6
cnt1:outintegerrange0to255;
7
cnt2:outintegerrange0to255);
8
endSig_vs_Var;
9
10
architectureBehavioralofSig_vs_Varis
11
signalca:integerrange0to255:=0;
12
begin
13
14
process(clk)
15
begin
16
ifrising_edge(clk)then
17
ca<=ca+1;
18
ifca=99thenca<=0;
19
endif;
20
endif;
21
endprocess;
22
cnt1<=ca;
23
24
process(clk)
25
variablecb:integerrange0to255:=0;
26
begin
27
ifrising_edge(clk)then
28
cb:=cb+1;
29
ifcb=99thencb:=0;
30
endif;
31
endif;
32
cnt2<=cb;
33
endprocess;
34
35
endBehavioral;
Und jetzt sind auch die Ergebnisee die selben. Gut soweit.
Allerdings muss natürlich die Zuweisung "cnt2 <= cb;" ausserhalb des
getakteten Teils des getakteten Prozesses stehen, was an sich schon
wieder unschöner Coding-Stale ist. Denn in einem getakteten Prozess
sollten nicht neben dem getatketen Teil noch irgendwelche
kombinatorischen Geschichten abgehandelt werden. "Aber diese zuweisung
ist doch gar keine Logik" kann man jetzt sagen. "Aber sie sieht so aus
und deshalb muss man sich das extra anschauen" halte ich dann dagegen.
Cartman schrieb:>> die Design Practice "Keep Things Local"> Eine putzige Idee bei einem FPGA
Im Grunde ist das die grundlegende Idee, die früher(tm) auch in den
Lehrbüchern zu finden war. Allerdings war die "lokalität" dort so
definiert, dass für jeden Zähler und jeden winzigen Fetzen Kombinatorik
ein eigenes Modul geschrieben und die Gesamtheit der Module dann eine
Ebene höher verdrahtet wurde. "Keep things local" war also auf
Komponentenebene zu sehen.
Diese Codewüsten mit tausendundeinem Prozessen und copy+paste-FSM in 1
Modul, die heute abgeliefert werden, finde ich in ähnlicher Form gern
mal im Sofwarebereich wieder...
Lothar M. schrieb:> mal einfach ohne groß nachzudenken
Das ist oft ein Problem ;)
Ich weiß nicht, was dein Beispiel beweisen soll?
Wenn ich - ohne Not - ein überflüssiges speicherndes Element in den
Prozess einbaue, kann ich doch erwarten, dass das in der Synthese auch
irgendwo erscheint?
Du sagst: "wenn Du die Eigenschaften von VHDL-Sprachelementen nicht
kennst, lass die Finger davon".
Ich sage: "wenn Du die Eigenschaften von VHDL-Sprachelementen nicht
kennst, lerne sie kennen und (sinnvoll) einzusetzen".
Dein Beispiel ist sicherlich kein sinnvoller Einsatz für eine Variable.
Es ist ja in Ordnung, wenn man auf solche Fallstricke aufmerksam macht,
aber deswegen Variablen generell zu verdammen, ist m.E. nicht
zielführend. Wenn wir alle ein bisschen komplizierteren Sprachelemente
von VHDL als "böse" erklären und nicht (auch dort, wo ihr Einsatz
sinnvoll ist) nutzen, hätten wir gleich "nur" Verilog oder AHDL lernen
können
P.S.: an dieser Stelle meine Entschuldigung an alle Verilog-Kenner und
Könner.
Markus F. schrieb:> Ich weiß nicht, was dein Beispiel beweisen soll?
Es zeigt allem Voran, dass es für die gleichartige Lösung der selben
Aufgabe keinen Unterschied macht, ob ich eine Variable oder ein Signal
nehme (siehe die Frage des TO).
> Wenn ich - ohne Not - ein überflüssiges speicherndes Element in den> Prozess einbaue, kann ich doch erwarten, dass das in der Synthese auch> irgendwo erscheint?
Ja, klar. Mein Beispiel zeigt ja nur, dass genau das passiert, obwohl
ich es nicht wollte. Und im Ernst: wenn mir das schon passiert... ;-)
> deswegen Variablen generell zu verdammen, ist m.E. nicht zielführend.
Ich meine auch, dass ich nirgends Variablen und deren Verwendung
verdammt hätte. Ich hatte nur darauf hingewiesen, dass man eben
normalerweise ein Signal nimmt,
>>> ausser man braucht unbedingt eine Variable.Markus F. schrieb:> Dein Beispiel ist sicherlich kein sinnvoller Einsatz für eine Variable.
Aber es beantwortet die ursprüngliche Frage.
Und meine weitergehende Analyse lautet: in einem Zähler brauche ich
keine Variable. Und deshalb nehme ich keine.
Wenn ich z.B. für eine Berechnung in einem Prozess oder in einer
Prozedur/Funktion eine Variable brauche, dann nehme ich auch eine.
> Du sagst: "wenn Du die Eigenschaften von VHDL-Sprachelementen nicht> kennst, lass die Finger davon".
Nein, ich sage: "so lange du..." und gebe dann Hinweise, wo/wie man sich
das nötige Wissen zur korrekten Anwendung aneignen kann.
Mal ganz pragmatisch, zum Einsatz von Variablen gibt es weitere Aspekte,
neben Tobias' Aussage, die ich unterschreiben wuerde:
- Variablen tauchen bei vielen Simulationstool nicht in der Trace auf,
also: Was man nicht von aussen sehen muss (lokale Variablen), muss auch
kein Signal sein.
- Simulationen laufen teils deutlich schneller mit Variablen/ blocking
assignments
- Aber: Variablen und Signale nicht in Prozessen wild mischen (im Sinne
von sauberem Code).
Bei komplexeren Designs (SoC-Registermaps, Encoder) bei denen viel Code
erzeugt wird, hat man deutlich mehr Performance und weniger Stress mit
Variablen, bei BRAM-Modellierung geht's teils kaum ohne, ein Zaehler
waere aber eher typischerweise als global sichtbares Signal
implementiert (was im Ergebnis genauso glitchen kann).
Ein Problem ist nur, dass manche Synthese-Engines mal mit dem einen
Konstrukt, mal mit dem andern nicht klarkommen (Reizthema partielle
Zuweisung). Da faehrt man mit Verilog als Transfersprache besser.
Martin S. schrieb:> Variablen tauchen bei vielen Simulationstool nicht in der Trace auf,> also: Was man nicht von aussen sehen muss (lokale Variablen), muss auch> kein Signal sein.
Das ist aber nur eine Seite der Medaille. Diese eingeschränkte
Sichtbarkeit von Variablen ist z.B. für den TO, der grade so anfängt,
ein spürbarer Minuspunkt.
Es soll ruhig jeder Variablen verwenden, wenn er weiß was sie tun. Die
allermeisten Anfänger verwenden Variablen aber, "weil sie ihren Wert
sofort ändern", so wie sie das von ihrer prozeduralen Programiersprache
gewohnt sind.
Lothar M. schrieb:> Das ist aber nur eine Seite der Medaille. Diese eingeschränkte> Sichtbarkeit von Variablen ist z.B. für den TO, der grade so anfängt,> ein spürbarer Minuspunkt.>> Es soll ruhig jeder Variablen verwenden, wenn er weiß was sie tun. Die> allermeisten Anfänger verwenden Variablen aber, "weil sie ihren Wert> sofort ändern", so wie sie das von ihrer prozeduralen Programiersprache> gewohnt sind.
Das ist doch der ganze Punkt meines Einwandes. Es ist didaktisch einfach
vollkommener Quatsch zu sagen: "Mach das immer so."
Mein Ansatz waere: "Mach das ERSTMAL so."
Ich wollte hier nicht ansetzen, warum Variablen sinnvoller als Signale
sein sollen oder rumgekehrt. Das "Keep Things Local" war auch nur ein
Beispiel, in einem Kontext in dem man z.B. fordert, dass die Lesbarkeit
von Code hoeher bewertet wird, als z.B. ressourcensparende Synthese
Ergebnisse. Solche Anforderungen sind durchaus real, es ziehen nunmal
immer mehr Coding Praktiken aus der Software Entwicklung in die HDL Welt
ein (und das ist auch gut so!) und werden von solchen Bauernregeln aus
den 90er einfach sinnlos konterkariert.
Ein Antibeispiel welches z.B. eine Ablehnung von Variablen rechtfertigen
wuerde, koennte z.B. sein: "Verwende immer ein Signal, ausser man
braucht unbedingt eine Variable, weil dein Code auch in Toolchain XYZ
umsetzbar sein muss und die Erfahrung hat gezeigt, dass sich diese mit
Variablen schwer tut bei der Synthese."
Vielleicht hat ja auch ein exotischer Synthesetool Herrsteller gemurkst
und die Vorgabe muss heissen:
"Verwende immer eine Variable, ausser man braucht unbedingt ein Signal,
weil dein Code auch in Toolchain XYZ umsetzbar sein muss und die
Erfahrung hat gezeigt, dass sich diese mit Signalen schwer tut bei der
Synthese."
Lothar M. schrieb:> Gut, umgestellt auf den old-school Stil mit "if rising_edge":
Da haste das beste Beispiel gebracht zum Thema: "Ich mach einfach immer
meinen Stiefel ohne ueber die Ergebnisse nachzudenken was die Resultate
sind." Sieht man an den beiden Prozessen auch deutlich, dass da
unterschiedliche Ergebnisse rauskommen muessen. Und da wollen wir die
Anfaenger doch hinbringen, dass die Sprachbeherrschung das Level
erreicht solche Dinge zu erkennen. Dazu benoetigt es allerdings ein
tiefergehendes Verstaendnis, welches man durch solche Bauernregel
Restriktionen nicht erlangen kann, weil man sich prinzipiell von einem
Grossteil des Sprachschatzes ausschliesst.
Nach ausgiebiger Diskussion sehe ich es ein, streiche feierlich das
steigernde "immer" sowie das "unbedingt" aus meiner obigen Aussage und
präsentiere hiermit eine weichgespülte Version, die aber den selben
Sinngehalt hat:
Man nimmt ein Signal, ausser man braucht eine Variable.
Ob man die Variable nun braucht, um den verordneten "Best-Coding-Style"
zu erfüllen oder um der Toolchain zum zügigen Ablauf zu verhelfen oder
einfach, weil sie an dieser Stelle die eleganteste Lösung ermöglicht,
sei dahingestellt.
Tobias B. schrieb:> Ein Antibeispiel welches z.B. eine Ablehnung von Variablen rechtfertigen> wuerde, koennte z.B. sein
Es "könnte" alles Mögliche sein oder auch nicht sein.
Meine Erfahrung mit zig Anfängern ist aber eben einfach, dass Anfänger
(und um einen solchen geht es hier) Variablen einfach nur aus den
bereits genannten Gründen nehmen (false friend bekannt aus der
SW-Programmierung).
Sie machen sich in dieser Phase des Lernens (zu Recht) keine Gedanken um
Unzulänglichkeiten der Toolchain.
Tobias B. schrieb:> Lothar M. schrieb:>> Gut, umgestellt auf den old-school Stil mit "if rising_edge":> Da haste das beste Beispiel gebracht zum Thema: "Ich mach einfach immer> meinen Stiefel ohne ueber die Ergebnisse nachzudenken was die Resultate> sind."
Ich brauche da in 99 von 100 Fällen ja gar nicht nachdenken, weil das so
funktioniert. Und in dem 1 Fall weiß ich dann wie es anders geht.
> Sieht man an den beiden Prozessen auch deutlich, dass da> unterschiedliche Ergebnisse rauskommen muessen.
Ja, das war mir nach 2 Sekunden auch klar. Der Anfänger sieht das aber
eben allein durch das Anschauen des Codes nicht.
Deshalb war mein zweiter Tipp: sieh den RTL-Plan an.
FPGA NOTFALLSEELSORGE schrieb im Beitrag #7091328:
>[..]>> Funktioniert dank VHDL2008 wunderbar und ist schöner clean Code.> Alles Gute, alles Liebe (-:
Ist das ernst gemeint?
Mich schüttelts, wenn mir jemand so ein Konstrukt anbieten würde. Mit
reset wirds noch unübersichtlicher.
Jo, "clean" ist anders.
Tim schrieb:> Ist das ernst gemeint?
+1
Fehlt eigentlich nur noch, aus count einen buffer zu machen, damit auch
Freunde von pre-2008 VHDL ihren Code so verhunzen können ;)
Hmm. Mal wieder eine Praesentation der idiotischsten Neuerungen von
VHDL2008: Lesen eines Ausgangs, noch dazu mit fehlender Initialisierung.
Kann sein, dass ich altmodisch bin, aber Hardware-Beschreibung als
Einzeiler mit > 80 Zeichen geht eher in Richtung Obfuscation als lesbar
fuer's Coder-Team.
Ich wage mal zu behaupten, dass einige Tools von 2014 aus sowas
innerhalb einer Hierarchie nicht das synthetisieren, was man eigentlich
wollte. Wenn sie es ueberhaupt schlucken.
@ Tim, Markus F., Martin S.
:o))))))))
Und das letzte "and" in seinem statement hat er ja wohl auch nicht so
richtig bedacht... (oder heisst das jetzt 'durchgedenkt'?)
Mein Motto: KISS
Tim schrieb:> Ist das ernst gemeint?
Natürlich nicht.
Martin S. schrieb:> Hardware-Beschreibung als> Einzeiler mit > 80 Zeichen geht eher in Richtung Obfuscation als lesbar> fuer's Coder-Team.
Naja, es sieht clean aus weil wenig Code, ist aber schwerer zu
durchdenken als eine Schreibweise mit getaktetem Prozess. Ich bin ein
großer Freund der geschwätzigen Sprachen und mag lieber mehr aber
einfacher zu durchdenkenden Code. Gerade wenn man Code nach langer Zeit
mal wieder anguckt will man den ja auch schnell wieder verstehen.
Martin S. schrieb:> Mal wieder eine Praesentation der idiotischsten Neuerungen von> VHDL2008: Lesen eines Ausgangs, noch dazu mit fehlender Initialisierung.
Du musst sie nicht nutzen. Und auch ganz ohne VHDL2008 geht der Zähler
als when else. Und ebenfalls ohne VHDL2008 sehe ich oft Code in dem
Signale nicht initialisiert werden. Darüber lässt sich sogar streiten.
Ist es sinnvoller bei Reset auf einen definierten Wert zu setzen oder zu
initialisieren? Oder Beides? Es gibt auch aktuell noch FPGA Familien die
ihre Register nicht initialisieren können.
vhdlerimruhestand schrieb:> Und das letzte "and" in seinem statement hat er ja wohl auch nicht so> richtig bedacht...
Wieso? Das simuliert und synthetisiert wunderbar. Ja, man könnte
Klammern setzen, also (rising_edge(clk) and cnt < 99) schreiben, aber
das ist optional.
> Wieso? Das simuliert und synthetisiert wunderbar. Ja, man könnte> Klammern setzen, also (rising_edge(clk) and cnt < 99) schreiben, aber> das ist optional.
Potentiell ist da ein Latch. Und die Tatsache, dass es nicht so
offensichtlich ist macht es nicht besser. (Hint: Das 'else ohne
Zuweisung zum alten Wert fehlt')
Deinen 'process' wuerde ich anders beschreiben. Und dein 'concurrent'
statement ist halt "nicht so einfach lesbar".
Kein Ding, mach' wie du denkst. Aber was ist eigentlich in deiner
Variante, wenn cnt >= 99 ist? Du hattest ja immerhin 'cnt' in deinem
Post nicht initialisiert.
Kann sein, dass das Kleinigkeiten und Erbsenzaehlerei ist. Ich habe halt
seit der 2. 1990er Haelfte VHDL als sehr konsistente Sprache
kennengelernt. Deshalb bin ich halt auch ein Fan von 'keep it simple...'
vhdlerimruhestand schrieb:> Kein Ding, mach' wie du denkst.FPGA NOTFALLSEELSORGE schrieb im Beitrag #7092720:
> Tim schrieb:>> Ist das ernst gemeint?>> Natürlich nicht.vhdlerimruhestand schrieb:> Aber was ist eigentlich in deiner Variante, wenn cnt >= 99 ist?
Ist ein Problem, kleiner Fehler meinerseits, kann man aber einfach
vermeiden durch
vhdlerimruhestand schrieb:> Deshalb bin ich halt auch ein Fan von 'keep it simple...'
Richtig, das bin ich auch. Daher nochmal: Das hier war als
Negativbeispiel gedacht.
Aber auch unter "simpel" werden unterschiedliche Dinge verstanden. Ist
Code "simpel" wenn es wenig Code ist? Ist Code "simple" wenn er
geschwätzig aber leicht zu verstehen ist?
Hier ging es ursprünglich mal um Variable vs. Signal. Ich finde Code ist
einfacher zu verstehen wenn möglichst alles getaktet ist und keine
Variablen vorkommen.
Man kann Variablen sogar auch immer komplett vermeiden. Nur eben nicht
wenn man gleichzeitig auch alles getaktet haben will.
FPGA NOTFALLSEELSORGE schrieb im Beitrag #7092780:
> Hier ging es ursprünglich mal um Variable vs. Signal.
Es ging darum, ob es allein durch die Verwendung des einen oder des
anderen
Gustav G. schrieb:> bei einem 32 bit Zähler zu glitches kommen kann.