Forum: FPGA, VHDL & Co. Lattice Radiant crash


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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?
1
library IEEE;
2
3
use IEEE.std_logic_1164.all;
4
use IEEE.numeric_std.all;
5
6
entity test is
7
        port (
8
                v: in integer range 0 to 2**16 - 1
9
        );
10
end test;
11
12
architecture behavioral of test is
13
        type dv_array is array(3 downto 0) of std_logic_vector(3 downto 0);
14
        variable digitval: dv_array;
15
        variable v_bits: std_logic_vector(15 downto 0);
16
17
begin
18
        process (v) is
19
        begin
20
                if v'event then
21
                        v_bits <= std_logic_vector(to_unsigned(v, 16));
22
                        L1: for i in range 0 to 3 loop
23
                                digitalval(i) <= v_bits(i * 4 + 3 downto i * 4)
24
                        end loop L1;
25
                end if;
26
        end process;
27
end behavioral;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

ps: Wenn ich die Schleife manuell ausrolle, dann sagt er mir, dass das 
mit den Variablen so nicht geht, aber crasht zumindest nicht mehr:
1
      digitalval(0) <= v_bits(3 downto 0);
2
      digitalval(1) <= v_bits(7 downto 4);
3
      digitalval(2) <= v_bits(11 downto 8);
4
      digitalval(3) <= v_bits(15 downto 12);

Wäre meine Schleife denn als solches syntaktisch korrekt gewesen?

von Pat A. (patamat)


Lesenswert?

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.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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. :(

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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. :-/

von Pat A. (patamat)


Lesenswert?

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:
1
    if v'event and v = '1' then   -- risinge edge

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Pat A. (patamat)


Lesenswert?

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:
1
    signal v_p: integer range 0 to 2**16 - 1; 
2
...
3
    process (clock) is
4
    begin
5
        if rising_edge(clock) then
6
            v_p <= v;
7
            if (v_p /= v) then
8
...
9
            end if;
10
        end if;
11
    end process;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von PCB (Gast)


Lesenswert?

Damit das überhaupt synthetisierbar ist, müsstest du dann nicht noch 
irgendeine Ausgabe haben?
Die Synthese müsste dir doch so alles 'wegoptimieren'.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
         for i in range 0 to 3 loop
5
             digitalval(i) := v_bits(i * 4 + 3 downto  i * 4);
6
         end loop;
7
     end process;
dann wäre der "nebenläufige Weg" ohne Prozess ein "Generate":
1
   v_bits := std_logic_vector(to_unsigned(v, 16));
2
   GEN_route: for I in 0 to 3 generate
3
        digitalval(i) <= v_bits(i * 4 + 3 downto  i * 4);
4
   end generate GEN_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
     variable v_bits: std_logic_vector(15 downto 0);
3
     begin
4
         v_bits <= std_logic_vector(to_unsigned(v, 16));
5
         for i in range 0 to 3 loop
6
             digitalval(i) <= v_bits(i * 4 + 3 downto  i * 4);
7
         end loop;
8
     end process;
Und da wäre der "nebenläufige Weg" und saubere Weg dann ein "Generate" 
mit Signalen statt Variablen:
1
signal v_bits: std_logic_vector(15 downto 0);
2
:
3
   v_bits <= std_logic_vector(to_unsigned(v, 16));
4
5
   GEN_mapping: for I in 0 to 3 generate
6
   begin
7
        digitalval(i) <= v_bits(i * 4 + 3 downto  i * 4);
8
   end generate GEN_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: for I in 0 to 3 generate
2
   variable v_bits: std_logic_vector(15 downto 0);
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 + 3 downto  i * 4);
6
   end generate GEN_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.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
    variable v_bits: std_logic_vector(15 downto 0);
3
  begin
4
    v_bits := std_logic_vector(to_unsigned(v, 16));
5
    digitval(0) <= v_bits(3 downto 0);
6
    digitval(1) <= v_bits(7 downto 4);
7
    digitval(2) <= v_bits(11 downto 8);
8
    digitval(3) <= v_bits(15 downto 12);
9
  end process;

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. :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
signal  v_bits: std_logic_vector(15 downto 0);
2
:
3
:
4
    v_bits <= std_logic_vector(to_unsigned(v, 16));
5
    digitval(0) <= v_bits(3 downto 0);
6
    digitval(1) <= v_bits(7 downto 4);
7
    digitval(2) <= v_bits(11 downto 8);
8
    digitval(3) <= v_bits(15 downto 12);

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...  ;-)

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.