Hi,
habe gleich den nächsten Stolperstein gefunden. Es geht diesmal quasi um
eine "Hello World Konfiguration", eine blinkende LED bzw. 18 in meinem
Fall. Auf meinem Board gibt es zwei LED Ports, 10x Rot, 8x Grün beide
active high angesteuert.
Der untere VHDL Code soll diese halbsekündig abwechseln, ich stehe aber
vor eine Optimierung, die ich nicht nachvollziehen kann.
Das Ergebnis ist, dass alle 18 LEDs simultan blinken. Wenn man sich den
Synthesereport anschaut, sieht man warum. Alle 18 Register wurden auf
eines reduziert.
Mein Frage: Warum? Ich habe die LED Vektoren unterschiedlich
initialisiert, die not-Anweisungen im process können also nicht das
gleiche liefern. Woher kommt das?
Synthese-Report u.a.:
LEDG[7]~reg0 Merged with LEDR[0]~reg0
LEDG[0]~reg0 Merged with LEDR[0]~reg0
LEDR[4]~reg0 Merged with LEDR[0]~reg0
LEDG[6]~reg0 Merged with LEDR[0]~reg0
LEDG[2]~reg0 Merged with LEDR[0]~reg0
LEDR[8]~reg0 Merged with LEDR[0]~reg0
LEDR[9]~reg0 Merged with LEDR[0]~reg0
LEDR[1]~reg0 Merged with LEDR[0]~reg0
LEDG[1]~reg0 Merged with LEDR[0]~reg0
LEDR[5]~reg0 Merged with LEDR[0]~reg0
LEDG[5]~reg0 Merged with LEDR[0]~reg0
LEDG[3]~reg0 Merged with LEDR[0]~reg0
LEDR[7]~reg0 Merged with LEDR[0]~reg0
LEDR[3]~reg0 Merged with LEDR[0]~reg0
LEDR[2]~reg0 Merged with LEDR[0]~reg0
LEDR[6]~reg0 Merged with LEDR[0]~reg0
LEDG[4]~reg0 Merged with LEDR[0]~reg0
Total Number of Removed Registers = 17
Danke im Voraus :)
Du hast die Register gar nicht initialisiert. Du hast nur Defaultwerte
in der Entity angegeben, aber die haben keine Bedeutung, wenn an den
Ports etwas angeschlossen ist.
Okay, das ist ein Ansatz - wie würde man das denn dann aber richtig
initialisieren? Bzw. was mir in VHDL mehr Probleme macht im Moment: wo?
Ich dachte nämlich sie wären initialisiert, denn wenn ich in die
Richtung google, finde ich eigentlich nur Konstrukte, welche genau so
aussehen.
Gruß :)
Andy L. schrieb:> Ich dachte nämlich sie wären initialisiert, denn wenn ich in die> Richtung google, finde ich eigentlich nur Konstrukte, welche genau so> aussehen.
Nein, die sehen nicht genau so aus, nur ähnlich ;-)
auf jeden Fall solltest du erstmal 2 Signale in der architecture
deklarieren. Diese kannst du dann dort mittels := initialisieren. Oder
du setzt sie im process mittels reset auf einen bestimmten wert.
Also so:
Erst mal vielen Dank für die ausführliche Antwort! Echt klasse :)
So funktioniert es jetzt, auch wenn ich die Lösung als Recht umständlich
empfinde. (aber um das zu beurteilen fehlt mir die nötige Erfahrung)
Andy L. schrieb:> auch wenn ich die Lösung als Recht umständlich> empfinde. (aber um das zu beurteilen fehlt mir die nötige Erfahrung)
Nahezu alles, was du mit VHDL machst, mutet einem klar denkenden
Menschen als viel zu umständlich an. ;-) Das haben die VHDL Entwickler
absichtlich so eingebaut. Daran muss du dich gewöhnen.
Und jetzt schnell weg, bevor wieder VHDL-Jünger kommen und Ihre
Heiligkeit verteidigen... ;-)
Andy L. schrieb:> process(CLOCK_50) is> variable count : integer := 0;> begin> if rising_edge(CLOCK_50) then> count := count+1;> if count > 25000000 then
1. Dein Blinker blinkt zu langsam... :-o
Na gut, hier wird man das nicht gleich merken, aber wehe, du
behältst diesen Stil z.B. auch für einen Zähler auf 5 bei.
2. Warum werden denn dauernd Variablen verwendet?
Siehe den Beitrag "Variable vs Signal"
3. Vergiss die Tricks mit buffer und inout in der Portliste,
wenn es nicht um Funktion, sondern nur um Schreibfaulheit geht!
> Ich dachte nämlich sie wären initialisiert, denn wenn ich in die> Richtung google, finde ich eigentlich nur Konstrukte, welche genau so> aussehen.
Initialisierung eines buffer in der Portliste? Zeigen!
1. Ja ..müsst evtl. eins weniger sein .. quick'n'dirty lässt grüßen ;)
Um solche Feinheiten mach ich mir keine Gedanken, wenn ich einfach nur
will dass es abwechselnd blinkt.
2. Hat mir mein Dozent so beigebracht und schlüssig erklärt, warum ich
in einem Prozess Variablen benutzen soll. Da auch er Ende des Semesters
meine Klausur bewertet, werde ich das auch so beibehalten.
3. Weder noch: Es geht um die verzweifelte Suche nach etwas, das durch
die Synthese läuft und hinterher funktioniert ;)
Andy L. schrieb:> 2. Hat mir mein Dozent so beigebracht und schlüssig erklärt
Wie lautete die Erklärung?
Hat er die Fallstricke von Variablen auch erwähnt?
> Um solche Feinheiten mach ich mir keine Gedanken
Das wird dich noch einholen. Garantiert.
Erst sind es Feinheiten, dann Angewohnheiten...
> Es geht um die verzweifelte Suche nach etwas, das durch> die Synthese läuft und hinterher funktioniert
Also: lass die buffer da weg und mach es mit den initialisierten
Signalen. Als kleine Anmerkung: vor wenigen Jahren war so eine
Initialisierung (aus welchen Gründen auch immer) noch nicht
synthetisierbar...
Zum ersten Punkt:
Das fragst mich ehrlich gesagt zu früh. Signal vs. Variable war mehr
oder weniger das Schlusswort der letzten Vorlesung.
Bisher wurde gesagt, ein Signal innerhalb eines Prozesses könne man
nicht sequenziell verwenden, da es erst am Ende des Prozesszyklus
zugewiesen wird und Signale, die in der Architecture definiert sind und
nur von einem Prozess verwendet werden, wiedersprechen dem Prinzip der
Datenkapselung.
Das ist zumindest, was bisher hängen geblieben ist.
Punkt drei habe ich ja geändert, tut mir Leid. ;)
Andy L. schrieb:> tut mir Leid. ;)
Ach, Käse, uns hast du nix getan ;-)
Andy L. schrieb:> Bisher wurde gesagt, ein Signal innerhalb eines Prozesses könne man> nicht sequenziell verwenden, da es erst am Ende des Prozesszyklus> zugewiesen wird
Sequenziell verwenden ist vielleicht nicht ganz richtig ausgedrückt. Du
kannst es nicht verwenden um Zwischenergebnisse innerhalb eines
Prozessdurchlaufs zu speichern und weiter zu verwenden. Aber das braucht
man auch erst bei relativ komplizierten Prozessen.
Andy L. schrieb:> Signale, die in der Architecture definiert sind und> nur von einem Prozess verwendet werden, widersprechen dem Prinzip der> Datenkapselung.
Datenkapselung. Ja, das stimmt schon. Da sind wir wieder beim unnötig
komplizierten VHDL. Ich wünschte mir auch, dass man signale in einem
Prozess deklarieren kann. Aber das geht halt nicht, das muss man halt
akzeptieren, bis jemand ne schönere Sprache erfindet. Bis dahin ist VHDL
meiner Meinung nach halt die beste Sprache, die es halt gibt ;-) Nen
Ausweg um doch ne gute Kapselung zu haben sind block statements. Am
Anfang eines Blocks lassen sich auch jeweils neue Signale deklarieren.
Klaus schrieb:> Sequenziell verwenden ist vielleicht nicht ganz richtig ausgedrückt.> Du kannst es nicht verwenden um Zwischenergebnisse innerhalb eines> Prozessdurchlaufs zu speichern und weiter zu verwenden.
Und vor allem: nicht speichernd, sindern nur als temporäre Variable.
@ Andy L.
Ein Signal in einem Prozess ist ganz simpel: die letzte Zuweisung
gewinnt, und bis dahin ändert sich der Wert des Signals nicht.
Wenn das Signal hier also mit 40 herienkommt, dann geht es mit 42 raus,m
weil i bis zum end process den Wert 40 behält, und dann den zuletzt
zugewiesenen Wert bekommt. Und das ist 42:
1
signaltest:integer;
2
:
3
:
4
process(clk)begin
5
ifrising_edge(clk)then
6
ifi=30theni<=40;endif;
7
ifi=40theni<=42;endif;
8
ifi=42theni<=50;endif;
9
ifi=50theni<=57;endif;
10
endif;
11
endprocess;
Mit Variablen im Prozess versuchen Einige, die Hemmschwelle zu VHDL für
prozedurale Programmiersprachen (C, Basic, ...) gewöhnte Softies
niedriger zu legen.
Andy L. schrieb:> Punkt drei habe ich ja geändert, tut mir Leid.
Warum tut dir das Leid? ;-)
Im Wesentlichen habt ihr beide jetzt präzise beschrieben, was ich etwas
schwammig schon vorhin gemeint habe :) Aber danke
Allerdings habt ihr jetzt auch beide ausgespart, warum ich keine
Variablen benutzen sollte, oder ist das schon in dem verlinkten Thread
plattgetreten? Hatte noch keine Zeit dort hineinzusehen.
Insbesondere Klaus, ich verstehe dich so, dass dir in Punkto
Datenkapselung die Lösung mit Signalen nicht so richtig gefällt, warum
also nicht der Griff zur Variabeln?
Lothar, du hattest die Fallstricke angesprochen: Wenn du hier mit dem
Zusatz "Und vor allem: nicht speichernd, sindern nur als temporäre
Variable." einen der Fallstricke anführen willst, so muss ich sagen,
dass ich das vollkommen logisch finde.
Ich komme selbst aus Java und sehe einen Prozess (noch) so ähnlich wie
eine Methode. Variablen die dort drin deklariert sind leben nur zur
Laufzeit und werden bei Beendung gelöscht. Daher finde ich das jetzt
recht nachvollziehbar, dass die nicht speichern.
Eine etwas vereinfachtere Darstellung war, man solle sich Variablen wie
ein Stück Draht vorstellen, was an einem Ende ist, ist auch gleich am
anderen Ende, wohingegenn beim Signal "erst was gearbeitet wird".
Ahja, ich entschuldige mich weil ich mich in dem Punkt verseckelt fühle
:P
Andy L. schrieb:> oder ist das schon in dem verlinkten Thread plattgetreten?
Ja, ausgiebig.
> Variablen die dort drin deklariert sind leben nur zur> Laufzeit und werden bei Beendung gelöscht. Daher finde ich das jetzt> recht nachvollziehbar, dass die nicht speichern.
Richtig, aber ein Zähler ist doch genau das: speichernd.
Oder willst du nicht, dass er sich den letzten Zählerwert merkt?
Eine Variable macht da Sinn, wo es gilt, einen komplizierten Rechenweg
in kleinere Schritte aufzuteilen. Und wenn die Berechnung erledigt ist,
ist die Variable überflüssig.
Das Hauptproblem mit Variablen ist, dass du sie nicht in die
Sensitivliste eines Prozesses aufnehmen kannst. Deine Simulation
stimmt dann evtl. nicht mehr mit der Realität überein...
> Eine etwas vereinfachtere Darstellung war, man solle sich Variablen wie> ein Stück Draht vorstellen, was an einem Ende ist, ist auch gleich am> anderen Ende, wohingegenn beim Signal "erst was gearbeitet wird".
So ein Bild hätte ich mir nicht von einer Variablen gemacht.
Echt nicht. Ich finde das eher verwirrend... :-/
Lothar Miller schrieb:> Richtig, aber ein Zähler ist doch genau das: speichernd.> Oder willst du nicht, dass er sich den letzten Zählerwert merkt?> Eine Variable macht da Sinn, wo es gilt, einen komplizierten Rechenweg> in kleinere Schritte aufzuteilen. Und wenn die Berechnung erledigt ist,> ist die Variable überflüssig.
...jetzt hab ich mir mit meiner Argumentation selbst den Ast abgesägt,
verdammt. :)
Dann verwundert es mich allerdings spontan, dass das funktioniert.
Naja, werde mir dann bei Gelegenheit mal den Kampf Signal vs. Variable
durchlesen :)
Andy L. schrieb:> Ich komme selbst aus Java und sehe einen Prozess (noch) so ähnlich wie> eine Methode. Variablen die dort drin deklariert sind leben nur zur> Laufzeit und werden bei Beendung gelöscht. Daher finde ich das jetzt> recht nachvollziehbar, dass die nicht speichern.>> Eine etwas vereinfachtere Darstellung war, man solle sich Variablen wie> ein Stück Draht vorstellen, was an einem Ende ist, ist auch gleich am> anderen Ende, wohingegenn beim Signal "erst was gearbeitet wird".
So weit so gut :-) Aber: das widerspricht deinem ersten Beispiel oben.
Denn dort soll "count" ja ebend nicht nur ein Stück Draht sein, sondern
ein Zähler der seinen Zustand zwischen den Taktflanken behält.
Variablen lassen sich zum Beispiel nicht in die sensitivity list des
Prozesses eintragen. Das kann bei der Simulation von kombinatorischen
Prozessen ziemlich kuriose Fehler (=Abweichungen von der Synthese)
geben.
Andy L. schrieb:> Dann verwundert es mich allerdings spontan, dass das funktioniert.
Naja, es funktioniert, weil die Variable ihren Wert ja halten muss, da
du ja im Prozess zuerst lesend drauf zugreifst, bevor sie beschrieben
wird. Dadurch erzeugt auch die Variable bei der Synthese Flipflops. Man
muss nur wissen, wann man das machen darf, und wann es schief gehen
wird. In einen Voll-Synchronen Design sollte das auch immer gut gehen.
Oder, Lothar? :-)
Andy L. schrieb:> Zum ersten Punkt:> Das fragst mich ehrlich gesagt zu früh. Signal vs. Variable war mehr> oder weniger das Schlusswort der letzten Vorlesung.> Bisher wurde gesagt, ein Signal innerhalb eines Prozesses könne man> nicht sequenziell verwenden, da es erst am Ende des Prozesszyklus> zugewiesen wird und Signale, die in der Architecture definiert sind und> nur von einem Prozess verwendet werden, wiedersprechen dem Prinzip der> Datenkapselung.
Entschuldigung: Das ist Unsinn!
Eine Variable kann zwar speichern, aber was du i.A. damit erreichst ist,
dass du den D-Eingang deines FF verwendest, nicht den Q. Und da am
D-Eingang meistens auch noch weitere Dekoderlogik haengt: Viel Spass mit
dem Timing wenn's nur ein wenig anspruchsvoller wird...
Sag deinem Prof einen schoenen Gruss von mir, er muss noch viel ueber
(V)HDL lernen...
Klaus schrieb:> Klaus schrieb:>> In einen Voll-Synchronen Design sollte das auch immer gut gehen.> Sorry, in einen rein getakteten Prozess, meinte ich.
Ja, da geht das problemlos, das muss ich zugeben... ;-)
Denn da muss die Variable ja nicht in die Sensitivliste. Aber wenn dann
mal ein kombinatorischer Prozess auch mit den beliebten und bis dahin
bewährten Variablen aufgesetzt wird, dann hat man
schwuppdiwuppundhastdunichtgesehen ein Latch oder gar eine
Kominatorikschleife an der Backe... :-/
berndl schrieb:> Entschuldigung: Das ist Unsinn!> Eine Variable kann zwar speichern, aber was du i.A. damit erreichst ist,> dass du den D-Eingang deines FF verwendest, nicht den Q. Und da am> D-Eingang meistens auch noch weitere Dekoderlogik haengt: Viel Spass mit> dem Timing wenn's nur ein wenig anspruchsvoller wird...>> Sag deinem Prof einen schoenen Gruss von mir, er muss noch viel ueber> (V)HDL lernen...
Von wem soll ich den Gruß ausrichten, vom erfinder von VHDL oder von dem
der die Weisheit mit Löffeln gefressen hat? Es tut mir Leid, aber nicht
weniger arrogant klingt dieser Post.
Aber um mal sachlich drauf einzugehen: Es wurde recht genau so erklärt,
wie Lothar und Klaus es dargestellt haben, nagel das hier nicht auf
meine unpräzisen Worte fest.
Und was du von D und Q Eingang sprichst verstehe ich auch nicht, in
userer Welt war Q ein Ausgang.
Des Weiteren glaube ich daran, dass mein Prof seine Titel schon zu Recht
hat.
Andy L. schrieb:> Des Weiteren glaube ich daran, dass mein Prof seine Titel schon zu Recht> hat.
Dann glaub das weiter. Das sieht man hier sehr schön:
Beitrag "Re: Clockmultiplexing vom mehreren Taktsignalen"
Totaler Stumpfsinn ab Versuch 4.
Die Leute hier (Lothar) und auch meine Wenigkeit verdienen mit VHDL ihre
Brötchen anders als dein Prof. der nur 20 Jahre altes Wissen fernab
jeglicher Praxis weiter zu geben scheint. Womit du Recht hast: Er
bewertet deine Klausur nicht wir.
Es ist aber nichts ungewöhnliches dass Profs. ihren Sinn für die
Realität und die Praxis recht schnell verlieren.
D. I. schrieb:> Es ist aber nichts ungewöhnliches dass Profs. ihren Sinn für die> Realität und die Praxis recht schnell verlieren.
Ich musste auch schon einige ein wenig "umerziehen"... ;-)
Also diese Logik musst du mir jetzt erklären, D.I.
Fakt #1: Lothar scheint für dich eine feste Größe, die Recht hat, zu
sein. Er macht auch diesen Eindruck, dem stimme ich zu.
Fakt #2: Ich habe behauptet, dass es so mir in der Vorlesung so erklärt
wurde, wie er und auch Klaus es sagten und ich es lediglich etwas
schwammig (aus dem Gedächtnis) formuliert hatte.
Wie verbindest du Fakt #1 und #2, sodass du dazu kommst, dass mein Prof
Wissen fernab der Realität weitergibt? :)
Andy L. schrieb:
ok, regen wir uns wieder ab :o)
> Und was du von D und Q Eingang sprichst verstehe ich auch nicht, in> userer Welt war Q ein Ausgang.
D ist der Eingang des Flipflops, Q der Ausgang. Wenn du eine Variable
verwendest (oder wahlweise auch ein Signal als Concurrent-Statement
beschreibst), dann ist das halt der Eingang des FFs. Dieser Eingang ist
ueblicherweise mit irgendwelcher Logik realisiert (NAND, ODER, LUTs beim
FPGA, ...) und hat schon 'Laufzeit' auf dem Buckel. Wenn du jetzt diese
Variable weiter verwendest, dann addierst du wieder zusaetzliche Logik
dazu (also jedes zusaetzliche if... oder auch Verknuepfungen ala
VARIABLE or IRGENDWASANDERES).
Und dass ich mich aufgeregt hatte, bezog sich vor allem darauf,
Variablen mit 'Datenkapselung' zu begruenden. Wenn jemand kapseln will,
dann soll er eine COMPONENT anlegen und Signale verwenden...
Ich (und nein, ich habe (V)HDL weder erfunden noch nutze ich mehr als
~10% des Sprachumfangs (ausser evtl. Simulation)) verwende Variablen zu
genau einem Zweck: Wenn ich ein Logiksignal generieren muss und das an
mehreren Stellen verwenden will (es erspart mir dann Tipparbeit und bei
Aenderungen ist es nur an einer einzigen Stelle). Und wenn ich die
Variable einfach durch eine Concurrent-Anweisung umgehen kann, dann
mache ich das auch...
Spiel doch spasseshalber mal einen Prozess durch, bei dem du eine
Variable benutzt (==setzt). Und dann mal im sequentiellen Prozess
'vorher' und 'nachher' was mit der Variablen machen. Viel Spass... Dein
ohnehin sequentieller Prozess (der nur eine kuenstliche Abbildung der
echten HW ist) wird durch das sequentielle Verhalten der Variablen noch
komplizierter. HDL != Programmierung, das scheint mir heutzutage nicht
wirklich gelehrt zu werden.
Ich habe lediglich etwas überspitzt ausgedrückt, dass man nicht jedem
der einen Titel trägt Alles glauben soll.
Lothar ist für mich keine Größe sondern belegt seine Thesen auf seiner
Seite recht anschaulich durch Beispiele zum selber nachvollziehen, was
in der Praxis nun geht oder auch nicht. Nicht mehr.
Und es sind immer wieder die gleichen Fallstricke begründet auf den
gleichen Tatsachen die Anfänger oft hier aufschlagen lassen. Grad
Variablen sind da ein Garant.
Immerhin scheint ihr aber schon rising_edge zu kennen und wenn euch die
numeric_std nahegelegt wird dann sei meine aussage etwas entschärft ;)
@berndl
(Es geht doch, wenn man nur will :))
Gut, ich denke ich kann dir soweit folgen, auch wenn mir der Begriff
concurrent wenig sagt, aber ich werde das gleich noch googeln. Was du zu
der Logik und ihrer Laufzeit meinst: Ja, das sehe ich ein, aber das
Problem ist doch dann letztlich "nur" (okay, auch nicht zu
unterschätzen), dass das Design halt langsam wird, oder?
Also ich sehe da gerade kein "schweres Vergehen" wie Taktteilungen oder
sowas :) Aber ein lahmes Design ist natürlich auch nicht erstrebenswert,
das stimmt schon.
Zu deinem Experimentvorschlag: Mir erschließt sich noch nicht so ganz,
was ich dann bemerken soll, wenn ich etwas "vorher und nachher" mit
einer Variablen mache (?) Erhöhter Logikaufwand bei der Synthese oder
worauf zielst du?
@D.I.
Na dann passts ja ;)
Andy L. schrieb:> Zu deinem Experimentvorschlag: Mir erschließt sich noch nicht so ganz,> was ich dann bemerken soll, wenn ich etwas "vorher und nachher" mit> einer Variablen mache (?)
Nachher: Du benutzt den 'D' des Flipflops,
Vorher: Du benutzt den 'Q' des Flipflops.
Kann ganz gewaltige Unterschiede (einen Clock-Zyklus und bei 'nachher'
halt evtl. Timingprobleme) machen...
Andy L. schrieb:> auch wenn mir der Begriff> concurrent wenig sagt
achso, das sind diese gelegentlich zu findenen statements (ausserhalb
eines Prozesses) wie z.B. 'a <= b or c' oder auch 'a <= b when c = '1'
and d = '1' else e;
'Fliegende' Logik halt...
Nix anderes macht die Variable innerhalb eines Prozesses (ok, sie kann
auch noch von D nach Q transportiert werden und damit speichern)
D. I. schrieb:> Immerhin scheint ihr aber schon rising_edge zu kennen und wenn euch die> numeric_std nahegelegt wird dann sei meine aussage etwas entschärft ;)
Die numeric_std und ihre Vorgaenger koennte man eigentlich mal als
running-gag hier pinnen!
Andy L. schrieb:> Also ich sehe da gerade kein "schweres Vergehen" wie Taktteilungen oder> sowas :)
den kann ich mir jetzt nicht verkneifen:
Er hat Jehova gesagt!
:o)