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?