Forum: FPGA, VHDL & Co. Problem bei Zuweisung mit nicht konstantem Range im std_logic_vector


von Matthias G. (mgottke)


Lesenswert?

Ich habe ein Modul geschrieben in dem vereinfacht dargestellt 4 Byte 
Eingangsdaten (von einem 32-Bit Datenbus) ankommen und nacheinander in 
ein durch ein generic festgelegten Ausgangsvektor (typ std_logic_vector) 
kopiert werden. Dabei ist in einer Tabelle festgelegt in welcher 
Reihenfolge und wie viele Bytes aus den 32-Bit Eingangsdaten und mit 
welchem Offset jeweils in den Ausgabevektor kopiert werden sollen.
Zur Darstellung mal ein Ausschnitt aus dem Erstentwurf:
1
entity my_modul is
2
generic
3
(
4
   NO_OF_BYTE  : positive -- Breite des Ausgabevektors in Byte
5
);
6
port
7
(
8
   ...
9
   indata    : in  std_logic_vector (31 downto 0);
10
   outdata   : out std_logic_vector (NO_OF_BYTE*8-1 downto 0);
11
   ...
12
);
13
end my_modul;
14
architecture behavior of my_modul is
15
   ...
16
   type copy_param is record
17
      offset   : natural  range 0 to 3;
18
      cnt      : positive range 1 to 4;
19
      posi      : natural  range 0 to NO_OF_BYTE-1;
20
   end record;
21
   constant MAX_COPYS : natural := ((NO_OF_BYTE + 3)/4) + 1;   -- max. Anz. der Kopiervorgänge
22
   type   copy_list is array (0 to MAX_COPYS-1) of copy_param; -- Liste der Kopiervorgänge
23
   ...
24
begin
25
   ...
26
   copy_proc : process (clk)
27
   begin
28
      if rising_edge(clk) then
29
         ...
30
         outdata((copy_list(list_pos).posi + copy_list(list_pos).cnt)*8-1 downto copy_list(list_pos).posi*8)
31
                <= avm_readdata((copy_list(list_pos).offset + copy_list(list_pos).cnt)*8-1 downto copy_list(list_pos).offset*8); -- Zeile der Fehlermeldung (413)
32
         ...
33
      end if;
34
   end process;
35
end behavior;
Soweit so gut, das funktioniert auch sehr schön in der Simulation, aber 
die Synthese meckert an:
1
Error (10394): VHDL error at my_modul.vhd(413): left bound of range must be a constant
Die Synthesetools (zumindest das verwendete) sind noch zu "dumm" um den 
Sinn dahinter zu erkennen. Nun stehe ich vor dem Problem wie ich das 
gelöst bekommen.
Dazu habe ich eine synthetisierbare Variante realisiert. Da ist für jede 
Kombination im Record mit generate ein kombinatorischer Vektor 
generiere, den ich dann auf meinen Ausgang muxe. Das führt aber leider 
dazu, dass die Synthese das nicht vernünftig auflösen kann und das 
Design in seiner Größe explodiert. Vermutet habe ich das schon vorher, 
aber einen Versuch war es schon Wert. Mein NO_OF_BYTE in meinem Projekt 
mehrfach instanziiert und liegt zwischen 1 und 16.
Hier mein mein "Explosionsansatz":
1
...
2
architecture behavior of my_modul is
3
   ...
4
   signal outdata_i : std_logic_vector (NO_OF_BYTE*8-1 downto 0);
5
   type   type_table is array (0 to 3, 1 to 4, 0 to NO_OF_BYTE-1) of std_logic_vector (32+NO_OF_BYTE*8-1 downto 0);
6
   signal outdata_table : type_table;
7
   ...
8
begin
9
   ...
10
   copy_proc : process (clk)
11
   begin
12
      if rising_edge(clk) then
13
         ...
14
         outdata_i <= outdata_table(copy_list(list_pos).offset, copy_list(list_pos).cnt, copy_list(list_pos).pos)(NO_OF_BYTE*8-1 downto 0);
15
         ...
16
      end if;
17
   end process;
18
      
19
   outdata <= outdata_i;
20
21
   gen_offset : for offset in 0 to 3 generate
22
      gen_cnt : for cnt in 1 to 4 generate
23
         gen_posi : for posi in 0 to NO_OF_BYTE-1 generate
24
             table_proc : process (indata, outdata_i)
25
                variable v_indata : std_logic_vector (63 downto 0);
26
             begin
27
                user_readdata_table(byte_offset,byte_cnt,user_byte_pos) <= x"00000000" & outdata_i;
28
                v_indata := x"00000000" & indata;
29
                outdata_table(offset,cnt,posi)((posi+cnt)*8-1 downto posi*8)
30
                   <= v_indata((offset+cnt)*8-1 downto offset*8);
31
            end process;
32
         end generate;
33
      end generate;
34
   end generate;
35
      
36
end behavior;
An sich sollte das ohne nennenswerten Ressourcenverbrauch gelingen 
können, da ja jedem Byte im Ausgangsvektor maximal 4 verschiedene Byte 
von den Eingängen her zugewiesen bekommen können. Das sollte doch die 
Synthese das mit einem einfachen Mux hin bekommen. Für jedes Bit im 
Ausgangsvektor müsste ein Mux mit 4 Eingängen entstehen. Bleibt also nur 
noch die Mux-Logik übrig. Allein der Ansatz dazu fehlt mir im Moment.
Hat jemand einen gute Idee wie ich das vielleicht lösen könnte?

von Matthias G. (mgottke)


Lesenswert?

Nach dem ich so viele Antworten bekommen habe, habe ich das ganze Modul 
nochmal neu aufgesetzt und die Funktionalität mit einem etwas anderen 
Ansatz gelöst. So ein Projekt wächst und verwächst sich auch manchmal. 
Das neue Design ist jetzt schlanker, schicker und schneller. :-)
Leider war aber dafür ein ganzer Tag Arbeit nötig. :-(
Zum Glück gab es schon die Testbench und die Testpattern, so dass an 
dieser Stelle nichts mehr zu tun war. Die Schnittstelle und die 
Funktionalität ist ja gleich geblieben.

Allerdings würde mich schon noch interessieren ob jemand eine Idee hat 
wie ich das Problem mit dem alten Design gelöst bekommen hätte.

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


Lesenswert?

> Die Synthesetools (zumindest das verwendete) sind noch zu "dumm" um den
> Sinn dahinter zu erkennen.
Ja nun, sowas ist ja noch ein stupider Multiplexer:
1
outdata((copy_list(list_pos).posi + copy_list(list_pos).cnt)*8-1 downto copy_list(list_pos).posi*8)
Aber weil du das Ganze taktest, muß auch das Clock-Enable der FFs 
entsprechend umgeschaltet werden. Ich könnte mir vorstellen, dass das 
Probleme machen könnte...

Bei deinem 2. Ansatz ist das alles statisch und die Toolchain kann deine 
Absicht eher erkennen.

> Das neue Design ist jetzt schlanker, schicker und schneller. :-)
Mich hat auch der Verdacht beschlichen, dass du mit dem obigen Ansatz 
irgendwas ziemlich umwegbehaftet lösen wolltest.

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.