Hmm. Dieses Stückchen VHDL lässt bei mir Radiant erfolgreich crashen
(segmentation fault).
Vermutlich ist damit ja irgendwas nicht korrekt, aber ein Crash ist
natürlich eine blöde Antwort … kann mir jemand sagen, ob meine Idee
grundsätzlich so geht?
Wahrscheinlich ist das "v'event" nutzlos, da es genügt, dass "v" in der
Sensitivitätsliste des Prozesses steht, oder?
Jörg W. schrieb:> digitalval(0) <= v_bits(3 downto 0);
Variablen werden mit := zugewiesen:
digitalval(0) := v_bits(3 downto 0);
Die for-Schleife als solches sollte so wie sie ist schon korrekt sein.
Pat A. schrieb:> Variablen werden mit := zugewiesen:
Ja, hat mir Radiant dann auch gesagt … aber das ist ja nicht das primäre
Problem. Auch, wenn ich das korrigiere, sowie die Schleife statt des
manuellen Entrollens drin ist, knallt mir Radiant weg. :(
Pat A. schrieb:> Die for-Schleife als solches sollte so wie sie ist schon korrekt sein.
Dann darf ich wohl mal wieder einen Bugreport an Lattice schreiben. :-/
Wie gut, dass ich Radiant nicht benutzen muss ;-)
Allerdings könnte evtl. "if v'event then" ein Problem für die Synthese
darstellen, da damit IMHO auf Rising- und Falling-Edge reagiert wird.
Überlicherweise wird bei der Verwendung von 'event die Bedingung
erweitert:
Pat A. schrieb:> Allerdings könnte evtl. "if v'event then" ein Problem für die Synthese> darstellen
OK, er crasht ja allerdings schon beim Elaborieren, also wenn man die
Datei speichert. Das ist noch lange vor der Synthese …
Naja, "v" ist ja ein Integer, kein std_logic. Die Idee war, dass der
Prozess angestoßen wird, sowie sich der Integer ändert.
Habe mal einen Bugreport eingereicht.
Jörg W. schrieb:> Naja, "v" ist ja ein Integer, kein std_logic. Die Idee war, dass der> Prozess angestoßen wird, sowie sich der Integer ändert.
Oh, ja, dass habe ich übersehen. So ein Konstrukt habe ich tatsächlich
noch nie ausprobiert. Wenn das wirklich funktioniert, dann wäre es schon
eine schöne, elegante Schreibweise. Das Ergebnis wäre allerdings ein
kombinatorischer Prozess und kein getakteter.
Bisher habe ich dazu das (Integer-) Signal registriert und auf ungleich
getestet:
Pat A. schrieb:> Wenn das wirklich funktioniert, dann wäre es schon eine schöne, elegante> Schreibweise.
Ja, mal sehen, was die Synthese dann dazu sagt und daraus macht.
Jörg W. schrieb:> Naja, "v" ist ja ein Integer, kein std_logic. Die Idee war, dass der> Prozess angestoßen wird, sowie sich der Integer ändert.
Das soll synthetisiert werden?
Da solltest du aber mal den User Guide zum Synthesizer abklopfen, was
der beim Attribut 'event erwartet.
Was du mit dem' event erreichen willst, das macht im Grunde ja schon die
Sensitivliste.
Und in der Hardware werden da sowieso nur Drähte weiter verbunden.
Jörg W. schrieb:> sowie die Schleife statt des manuellen Entrollens drin ist, knallt mir> Radiant weg. :(
Manchmal stolpern die Synthesizer über simpleste Berechnungen. Gerade
mit solchen Berechnungen für Indices kann man sie leicht an die Grenze
bringen. Inzwischen bin ich soweit, dass ich mich damit abfinde... ?
> Habe mal einen Bugreport eingereicht.
Bin gespannt.
Lothar M. schrieb:> Jörg W. schrieb:>> Naja, "v" ist ja ein Integer, kein std_logic. Die Idee war, dass der>> Prozess angestoßen wird, sowie sich der Integer ändert.> Das soll synthetisiert werden?
Jein :-)
LSE synthetisiert es klaglos. SynplifyPro erzählt dagegen, dass event
nur für 1-Bit-Signale unterstützt sei. ;-)
Aber gut, es war ja in der Diskussion eigentlich schon klar, dass das
Nennen von v in der Sensitivliste völlig ausreicht, und dass ohnehin aus
dem Ganzen eine kombinatorische Logik wird.
Insofern generiert LSE auch mit dem v'event praktisch das gleiche RTL
wie ohne.
> Und in der Hardware werden da sowieso nur Drähte weiter verbunden.
So ist es.
> Jörg W. schrieb:>> sowie die Schleife statt des manuellen Entrollens drin ist, knallt mir>> Radiant weg. :(> Manchmal stolpern die Synthesizer über simpleste Berechnungen.
In dem Falle war es ja noch nicht einmal der Synthesizer. Radiant crasht
beim Speichern der Datei, weil sie da stets ein Elaborieren durchführen.
Danach kann man natürlich nicht einmal mehr das Projekt laden, ohne
zuvor diese Datei extern editiert zu haben …
> Gerade> mit solchen Berechnungen für Indices kann man sie leicht an die Grenze> bringen. Inzwischen bin ich soweit, dass ich mich damit abfinde... ?
Eigentlich schade, denn ich hatte mich gefreut, deine Anmerkungen über
die for-Anweisung verstanden zu haben, dass in diesem Falle ja
nebenläufiger Code erzeugt wird. Damit ist das eigentlich eine schöne
Möglichkeit, die exakte Bitbreite des Vektors als Parameter übergeben zu
können statt hart zu codieren.
>> Habe mal einen Bugreport eingereicht.> Bin gespannt.
Ich auch.
Lothar M. schrieb:>> Habe mal einen Bugreport eingereicht.> Bin gespannt.
Radiant 2.1 hat laut Auskunft der Supporter den Bug behoben und soll
Anfang Juli freigegeben werden.
Aber positiv: sie reagieren relativ schnell und scheinen die Reports
zumindest nicht ungesehen wieder zu schließen.
PCB schrieb:> Damit das überhaupt synthetisierbar ist, müsstest du dann nicht noch> irgendeine Ausgabe haben?
Der finale Code sieht dann sowieso anders aus – aber Radiant crashte ja
bereits beim Elaborieren, also bei der grundlegenden VHDL-Analyse
überhaupt (die machen sie beim Abspeichern einer geänderten Datei bzw.
beim Einlesen eines Projekts).
Bei der Synthese war das noch lange nicht angekommen.
Aber ja, natürlich hängen da noch andere Dinge rundrum dran. Die
for-Schleife war nur das von einem größeren (den Crash verursachenden)
Projekt rausgezogene Minimalbeispiel. Sinn der Sache war die Aufteilung
einer 16-Bit-Zahl auf 4 4-Bit-Zahlen, um sie auf einer vierstelligen
Siebensegmentanzeige hexadezimal darstellen zu können.
Jörg W. schrieb:>> Gerade mit solchen Berechnungen für Indices kann man sie leicht an die>> Grenze bringen. Inzwischen bin ich soweit, dass ich mich damit>> abfinde... ?> Eigentlich schade
Richtig. An so einer simplen Berechnung sollte kein Teil der Toolchain
hängen bleiben. Nicht im Jahr 2020.
> denn ich hatte mich gefreut, deine Anmerkungen über> die for-Anweisung verstanden zu haben, dass in diesem Falle ja> nebenläufiger Code erzeugt wird.
Der Code an sich ist ja in einem Prozess und schon deshalb nicht
"nebenläufig", denn "Nebenläufigkeit" ist im Grunde nur ein
Syntaxelement. "Nebenläufige" Beschreibungen ergeben bei entsprechender
Codierung einfach mit anderen Anweisungen die selbe Hardware.
Das sieht man
Wenn dein Prozess mit einer "globalen" Varibale also so aussieht:
1
process(v)is
2
begin
3
v_bits:=std_logic_vector(to_unsigned(v,16));
4
foriinrange0to3loop
5
digitalval(i):=v_bits(i*4+3downtoi*4);
6
endloop;
7
endprocess;
dann wäre der "nebenläufige Weg" ohne Prozess ein "Generate":
1
v_bits:=std_logic_vector(to_unsigned(v,16));
2
GEN_route:forIin0to3generate
3
digitalval(i)<=v_bits(i*4+3downtoi*4);
4
endgenerateGEN_REG;
Allerdings sind beide Beschreibungen ein wenig "unsauber", denn es ist
eher unüblich, in der architecture Variablen zu deklarieren. Variablen
werden üblicherweise doch eher lokal im Prozess gehalten:
1
process(v)is
2
variablev_bits:std_logic_vector(15downto0);
3
begin
4
v_bits<=std_logic_vector(to_unsigned(v,16));
5
foriinrange0to3loop
6
digitalval(i)<=v_bits(i*4+3downtoi*4);
7
endloop;
8
endprocess;
Und da wäre der "nebenläufige Weg" und saubere Weg dann ein "Generate"
mit Signalen statt Variablen:
1
signalv_bits:std_logic_vector(15downto0);
2
:
3
v_bits<=std_logic_vector(to_unsigned(v,16));
4
5
GEN_mapping:forIin0to3generate
6
begin
7
digitalval(i)<=v_bits(i*4+3downtoi*4);
8
endgenerateGEN_mapping;
Der "nebenläufige Weg" über ein "Generate" mit Deklarationsblock ist
hier unsauber, denn dort lässt sich zwar eine Variable deklarieren, aber
eigentlich enthält ein Generate Block nur nebenläufige Anweisungen, die
nicht sequentiell abgearbeitet werden und deshalb keine von der
Reihenfolge abhängigen Abhägigkeiten haben dürfen. Und das ist hier
jetzt wieder ein arger Spezialfall, den ein Synthesizer (schon aufgrund
absoluter Unüblichkeit) vermutlich auch nicht umsetzen kann:
1
GEN_mapping:forIin0to3generate
2
variablev_bits:std_logic_vector(15downto0);
3
begin
4
v_bits:=std_logic_vector(to_unsigned(v,16));-- diese Zeile muss vor der folgenden Zeile ausgeführt werden
5
digitalval(i)<=v_bits(i*4+3downtoi*4);
6
endgenerateGEN_mapping;
Siehe auch:
https://stackoverflow.com/questions/47302553/vhdl-why-are-you-not-allowed-to-use-variables-in-generate-loops
Zum Abschluss hier nochmal der Tipp: nimm Signale.
Wenn du ein spezielles Problem hast, das mit Signalen nicht gelöst
werden kann, dann denk erst nochmal über das Problem und dann ggfs. über
Variablen nach... ;-)
Oder andersrum: Variablen werden für synthesefähigen Code bei mir nur im
Deklarationsblock von Prozessen deklariert. Und die Fälle, wo ich
Variablen ausserhalb von Prozessen gebraucht habe (weil alles andere zu
umständlich gewesen wäre), die kann ich an einer Hand abzählen.
Lothar M. schrieb:> Oder andersrum: Variablen werden für synthesefähigen Code bei mir nur im> Deklarationsblock von Prozessen deklariert.
Das ist ja bei mir (in der fertigen Version) auch der Fall:
1
process(v)is
2
variablev_bits:std_logic_vector(15downto0);
3
begin
4
v_bits:=std_logic_vector(to_unsigned(v,16));
5
digitval(0)<=v_bits(3downto0);
6
digitval(1)<=v_bits(7downto4);
7
digitval(2)<=v_bits(11downto8);
8
digitval(3)<=v_bits(15downto12);
9
endprocess;
Vermutlich hätte es genausogut ein Alias getan. Ich wollte ja nur die
Vektorisierung des Integers damit in eine separate Zeile schreiben
können.
Variable statt Signal nur deshalb, weil ich ja ansonsten innerhalb eines
Prozesses nicht hätte auf den zugewiesenen Wert sofort zugreifen können.
Danke für den Hinweis mit "generate"; dieser Konstrukt war mir bislang
noch nicht vorbei geschlittert. Habe ich sicher mal irgendwann irgendwo
gelesen, aber aus dem Blick verloren.
Es führen also immer viele Wege nach Rom. :-)
Jörg W. schrieb:> Variable statt Signal nur deshalb, weil ich ja ansonsten innerhalb eines> Prozesses nicht hätte auf den zugewiesenen Wert sofort zugreifen können.
Richtig, deshalb hättest du den Wert einfach ausserhalb des Prozesses
zuweisen können. Denn das passiert ja auch in der Hardware: ständig wird
da dieser "Zwischenwert" neu "berechnet". Und in letzter Konsequenz
hättest du dir den ganzen Prozess gespart und alles
concurrent/nebenläufig erledigt:
1
signalv_bits:std_logic_vector(15downto0);
2
:
3
:
4
v_bits<=std_logic_vector(to_unsigned(v,16));
5
digitval(0)<=v_bits(3downto0);
6
digitval(1)<=v_bits(7downto4);
7
digitval(2)<=v_bits(11downto8);
8
digitval(3)<=v_bits(15downto12);
Ich habe da eine ungeschriebene Regel, die ich in mehr als 80% der Fälle
einhalten kann: Prozesse sind getaktet, Kombinatorik wird nebenläufig
gemacht. Manchmal muss ich diese Regel brechen und manchmal bringt es
unbestreitbare Vorteile.
Jörg W. schrieb:> Es führen also immer viele Wege nach Rom. :-)
Gut fährt, wer daraus auswählen kann... ;-)
Lothar M. schrieb:> Und in letzter Konsequenz hättest du dir den ganzen Prozess gespart und> alles concurrent/nebenläufig erledigt:
Jo. :)
Im Prinzip ist mir ja klar, wie Hardware so tickt :), aber an manches
muss ich mich bei HDL in der Tat erst noch gewöhnen.