Forum: FPGA, VHDL & Co. Array mit generate füllen lassen


von Ralf (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem.
Ich möchte gerne möglichst übersichtlich ein Array füllen.

Dazu habe ich einen 128 Bit Vector:
1
Vector : std_logic_vector(127 downto 0);
Zusätzlich habe ich das folgende Array definiert:
1
type array128x8 is array (0 to 127) of std_logic_vector(7 downto 0);
2
signal Vector_array : array128x8;

Nun möchte ich gerne das Array wie folgt mit dem Inhalt des Vector 
füllen, nämlich einfach immer 8 Bit pro Eintrag und am Ende mit einer 
Art Überlauf, der bei Bit 0 wieder anfängt:
1
Vector_array(  0) <= Vector(  7 downto   0);
2
Vector_array(  1) <= Vector(  8 downto   1);
3
Vector_array(  2) <= Vector(  9 downto   2);
4
...
5
Vector_array(120) <= Vector(127 downto 120);
6
Vector_array(121) <= Vector(127 downto 121) & Vector(0         );
7
Vector_array(122) <= Vector(127 downto 122) & Vector(1 downto 0);
8
Vector_array(123) <= Vector(127 downto 123) & Vector(2 downto 0);
9
Vector_array(124) <= Vector(127 downto 124) & Vector(3 downto 0);
10
Vector_array(125) <= Vector(127 downto 125) & Vector(4 downto 0);
11
Vector_array(126) <= Vector(127 downto 126) & Vector(5 downto 0);
12
Vector_array(127) <= Vector(           127) & Vector(6 downto 0);

Der erste Part ist eigentlich klar:
1
table : for i in 0 tp 127 generate
2
  Vector_array(i) <= Vector(i+8-1 downto i);
3
end generate;

Nun ist die Frage, wie ich das nach der ersten Zeile des zweiten Teils 
gestalten soll. Denn da würde ja bei i=121 ohne Verkettung (0 downto 
121) rauskommen (sofern i nach 0 überläuft), was ja Blödsinn ist.

Ich wollte aber auch vermeiden, die letzten 7 Zeilen auszuschreiben. So 
ein komplettes generate wäre schon übersichtlich.

Gibt es da eine schöne Vairante?

Klar, ich könnte den Vector einfach um 7 Bit erweitern und in die 7 MSB 
nochmal die 7 LSB kopieren, aber ob das schöner ist, keine Ahnung. Ich 
suche eher eine rafinierte Variante :)

Vielen Dank!
Ralf

von Thomas W. (donka)


Lesenswert?

Also ich würde das z.B. so machen:

table : for i in 0 to 127 generate
    Vector_array(i) <= Vector(i+8-1 downto i) when i < 121 else
                       Vector(127 downto i) & Vector(i-121 downto 0);

end generate;

von Fritz J. (fritzjaeger)


Lesenswert?

Thomas Wendt schrieb:

> table : for i in 0 to 127 generate
>     Vector_array(i) <= Vector(i+8-1 downto i) when i < 121 else
>                        Vector(127 downto i) & Vector(i-121 downto 0);
>
> end generate;

Hm, nicht "loop" statt "generate"?!

von user (Gast)


Lesenswert?

auserhalb eines processes "generate"
innerhalb eines processes "loop"

von Ralf (Gast)


Lesenswert?

Hallo,

ich habe gerade einen Knoten im Gehirn.
Ich wollte die ganze Sache etwas variabler gestalten, dass ich auch 
größere Arrays einfach erstellen kann. Sowohl die Zeilen, als auch 
Spalten Anzahl sollte variabel sein. Der Eingang Vector sollte aber 
maximal 512 Stellen haben... dieser wird vom MSB aus durchlaufen und die 
virtuelle Überlaufgrenze ist da, wo die Zeilenanzahl erreicht ist und 
die MSBs angehängt werden, obwohl der Eingangsvector bei Zeilenwerten < 
512 noch weiter gehen würde. Ich fange also entgegen dem Startpost nun 
beim MSB an und nicht beim LSB.
1
fill_Vector_array : for i in 0 to 511 generate
2
    Vector_array(i) <= Vector(511-i downto (511-i-SPALTEN)+1) when i<(ZEILEN-SPALTEN)+1 else
3
                       Vector(511-i downto (511-ZEILEN)+1) & Vector(511 downto 511+((ZEILEN-SPALTEN-i)+1));
4
end generate;
Wieso meldet mir der Compiler hier
"Slice range (15 downto -1) does not belong to the prefix index range 
(511 downto 0); ???

Selbst wenn ich es mal mit
ZEILEN  = 512
SPALTEN = 17
durchrechne, komme ich nie auf -1 als rechte Grenze.
1
fill_Vector_array : for i in 0 to 511 generate
2
    Vector_array(i) <= Vector(511-i downto 495-i) when i<496 else
3
                       Vector(511-i downto 0) & Vector(511 downto 511+(496-i));
4
end generate;

Die Simulation klappt mit Zeilenwerten von 5-496. 497-512 gehen nicht 
mehr :(
Habe ich da noch einen kompletten Denkfehler, oder wo habe ich Mist 
gebaut?

Vielen Dank!
Ralf

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


Lesenswert?

Ralf schrieb:
> Wieso meldet mir der Compiler
Welcher denn überhaupt?

> Wieso meldet mir der Compiler hier
> "Slice range (15 downto -1) does not belong to the prefix index range
> (511 downto 0); ???
Wann meldet er das?
Zur Übersetzungszeit (dann meldet es der Compiler) oder zur 
Simulationslaufzeit (dann meldet es der Simulator)?


Ralf schrieb:
> Habe ich da noch einen kompletten Denkfehler
Ja, aber der liegt schon da:
> dass ich auch größere Arrays einfach erstellen kann.
WIE sollen denn diese Arrays in HARDWARE abgebildet werden? Wie wird 
sowas mit "normalen" Bausteinen gelöst (RAM, Flipflops und Gatter)? 
Kannst du dir in etwa vorstellen, was aus deiner Beschreibung werden 
wird?

Mit dieser aufwändigen Umschalterei undwasweißichauchimmer bringst du 
nur den Synthesizer durcheinander. Gerade bei Arrays tun sich die dinger 
sowieso noch etwas schwer. Denn die müssen genau diese Frage beantworten 
und umsetzen: WIE sollen denn diese Arrays in HARDWARE abgebildet 
werden?

von Ralf (Gast)


Lesenswert?

Hallo Lothar,

Lothar Miller schrieb:
> Welcher denn überhaupt?
Ich arbeite mit Modelsim.

Lothar Miller schrieb:
> Wann meldet er das?
> Zur Übersetzungszeit (dann meldet es der Compiler) oder zur
> Simulationslaufzeit (dann meldet es der Simulator)?
Dann ist es der Simulator. Da hast du recht, dass die Differenzierung 
noch sinnvoll ist. Ich kompiliere (vcom) die Dateien in meine work-Lib 
und lade dann mit vsim die Simulation. Hier wird dann der Fehler 
ausgegeben.

Lothar Miller schrieb:
> WIE sollen denn diese Arrays in HARDWARE abgebildet werden?
Das Array dient nur der Simulation und der Abbildung eines Modells. Es 
wird also nur im Testbench instantiiert und wird nie in Hardware 
abgebildet werden müssen.

Vielen Dank!
Ralf

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


Lesenswert?

Ralf schrieb:
> Die Simulation klappt mit Zeilenwerten von 5-496.
Sicher, dass es nicht bei 496 auch schon hakt?
Denn generate macht eigentlich nur eine textuelle Ersetzung (wie der 
Präprozessor vom Compiler). Und dann steht da:
1
     --                             15   downto   -1   
2
     Vector_array(496) <= Vector(511-496 downto 495-496) when i<496 else
3
                          Vector(511-496 downto 0) & Vector(511 downto 511+(496-496));
Und das geht schief...

Ich würde die Initialisierung in einem Prozess machen. Da kann ich mit 
einem if richtig "umschalten"...

von Thomas W. (donka)


Lesenswert?

Ralf schrieb:
> Hallo,
>
>
>
> ich habe gerade einen Knoten im Gehirn.

Hallo Ralf,

Vielleicht hilft das den Knoten zu lösen.

Entweder als concurrent statement

fill_Vector_array_low : for i in 0 to ZEILEN-SPALTEN generate
    Vector_array(i) <= Vector(i+SPALTEN-1 downto i);
end generate;

fill_Vector_array_high : for i in (ZEILEN-SPALTEN)+1 to ZEILEN-1 
generate
    Vector_array(i) <= Vector(ZEILEN-1 downto i) &
        Vector(i-(ZEILEN-SPALTEN+1) downto 0);
end generate;

oder als process geschrieben.

process(Vector)
begin
    for i in 0 to ZEILEN-1 loop
        if i < (ZEILEN-SPALTEN+1) then
            Vector_array(i) <= Vector(i+SPALTEN-1 downto i);
        else
            Vector_array(i) <= Vector(ZEILEN-1 downto i) &
                Vector(i-(ZEILEN-SPALTEN+1) downto 0);
        end  if;
    end loop;
end process;

von Ralf (Gast)


Lesenswert?

Hallo,

Lothar Miller schrieb:
> Sicher, dass es nicht bei 496 auch schon hakt?
> Denn generate macht eigentlich nur eine textuelle Ersetzung (wie der
> Präprozessor vom Compiler). Und dann steht da:
1
                       --15   downto   -1   
2
Vector_array(496) <= Vector(511-496 downto 495-496) when i<496 else
3
                     Vector(511-496 downto 0) & Vector(511 downto 511+(496-496));
> Und das geht schief...
Die Abfrage i<496 lässt doch die erste Möglichkeit mit i=496 gar nicht 
zu?!
Bis 495 ist die erste Auswahl aktiv und ab 496 die zweite, so dass (15 
downto -1) gar nicht möglich ist? Oder habe ich da noch einen 
Denkfehler?

Thomas Wendt schrieb:
> Vielleicht hilft das den Knoten zu lösen.
> Entweder als concurrent statement
> oder als process geschrieben.
Vielen Dank!
Ich werde das mal austesten...

Prinzipiell sehe ich keinen Unterschied zwischen einem generate 
außerhalb  und einer loop innerhalb eines Prozesses. Ich mach das immer 
davon abhängig, wie übersichtlich es sich beschreiben lässt.

Vielen Dank!
Ralf

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


Lesenswert?

Ralf schrieb:
> Die Abfrage i<496 lässt doch die erste Möglichkeit mit i=496 gar nicht
> zu?!
Der Ausdruck wird von links nach rechts compiliert. Also wird erst mal 
die Range berechnet, und danach erst käme "überraschend" die if-Abfrage. 
Nur: soweit kommt der Simulator nicht, denn der Range ist ja schon 
überschritten. Und du hast Glück, denn deine Fehlermeldung sagt ja noch 
halbwegs was sinnvolles. ISIM sagt z.B. nur noch:
1
ERROR: FATAL ERROR:ISim: This application has discovered an exceptional
2
condition from which it cannot recover. Process will terminate. 
3
ERROR: The simulation failed to launch for the following reason:
4
The Simulation shut down unexpectedly during initialization.  
5
6
Please shut down ISim and retry the simulation. 
7
If the problem persists, please contact Xilinx support.

Active HDL ist da wieder aussagekräftiger und meint
1
ELAB2: Fatal Error: ELAB2_0014 tb_range.vhd (50): 
2
    Range (2 downto -1) exceeds range (6 downto 0) of "v".


> Prinzipiell sehe ich keinen Unterschied zwischen einem generate
> außerhalb  und einer loop innerhalb eines Prozesses.
Es ist aber genau dieser prinzipielle Unterschied, dass beim Prozess 
zuerst die if-Abfrage kommt, und dann die Auswertung...


Hier mal mein kleiner Test-Dreizeiler zum Thema:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.numeric_std.ALL;
4
 
5
ENTITY tb_range IS
6
END tb_range ;
7
 
8
ARCHITECTURE behavior OF tb_range IS 
9
    signal v   : std_logic_vector(6 downto 0) := "0001000";
10
    type vatyp is array (0 to 5) of std_logic_vector (3 downto 0);
11
    signal va  : vatyp;
12
BEGIN 
13
   fill_va : for i in 0 to 3 generate -- geht gut.
14
   fill_va : for i in 0 to 5 generate -- geht nicht!
15
       va(i) <= v(6-i downto 3-i) when i<4 else "0101";
16
   end generate; 
17
 
18
   process (v) begin
19
      for i in 0 to 5 loop    -- geht gut.
20
         if i<4 then
21
            va(i) <= v(6-i downto 3-i);
22
         else 
23
            va(i) <= "0101";
24
         end if;
25
      end loop;
26
   end process;
27
END;

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.