Forum: FPGA, VHDL & Co. Anzahl Ports per GENERIC ändern


von Thommy (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein Modul, was ich gerne mehrfach wiederverwenden möchte, ohne 
immer die Port-list zu ändern und mehrere Module zu erstellen, die sich 
nur die Anzahl der Ports unterscheiden.

Je nach Instanz kann sich die Anzahl der Ports ändern.

Dazu habe ich mehrere 3-Bit breite Status-Eingänge.
1
  PORT (
2
    STATUS_0 : IN std_logic_vector(2 DOWNTO 0);
3
    STATUS_1 : IN std_logic_vector(2 DOWNTO 0);
4
    STATUS_2 : IN std_logic_vector(2 DOWNTO 0);
5
    STATUS_3 : IN std_logic_vector(2 DOWNTO 0);
6
    ...
7
    );

Genau diese Anzahl an STATUS_x Eingängen soll nun Variabel sein.
1
  GENERIC (
2
    G_STATUS_CNT : integer range 1 to 7 := 4
3
    );

Wie kann ich mit diesem GENERIC die Anzahl der Ports definieren?
Das ich bildlich gesehen sowas ähnliches erhalte:
1
  GENERIC (
2
    G_STATUS_CNT : integer range 1 to 7 := 4
3
    );
4
  PORT (
5
    STATUS_0 : IN std_logic_vector(2 DOWNTO 0);
6
    STATUS_1 : IN std_logic_vector(2 DOWNTO 0);
7
    STATUS_2 : IN std_logic_vector(2 DOWNTO 0);
8
    STATUS_3 : IN std_logic_vector(2 DOWNTO 0);
9
    ...
10
    STATUS_G_STATUS_CNT-1 : IN std_logic_vector(2 DOWNTO 0);
11
    );

Die einzige Möglichkeit, die mir eingefallen ist, dass ich ein Array 
[G_STATUS_CNT x 3] erstelle, aber dann muss ich einen extra Type in 
einem Package definieren und dieses Package dann immer mit einbinden. 
Das möchte ich vermeiden. Außerdem wäre die Instantiierung dann nicht 
sonderlich intuitiv.

Gibt es vielleicht eine andere Möglichkeit, dies zu tun?

Vielen Dank!
Thommy

von user (Gast)


Lesenswert?

Also entweder Package, oder du machst alles in einen std_logic_vektor, 
was auch nicht schön ist.

von Philip K. (philip_k)


Lesenswert?

Thommy schrieb:
> Wie kann ich mit diesem GENERIC die Anzahl der Ports definieren?

Gar nicht. VHDL ist bei solchen Dingen leider etwas unflexibel...
Der von Dir beschriebene Weg, mit Array-Typ und Package ist schon der 
Richtige. Mit einem großen Vektor würde ich das nicht machen. Ist 
umständlicher in der Indizierung und es kann passieren, dass Dein 
Synthese-Tool seltsame Dinge daraus macht.

von Christoph Z. (christophz)


Lesenswert?

Thommy schrieb:
> aber dann muss ich einen extra Type in
> einem Package definieren und dieses Package dann immer mit einbinden.

In das Package kannst du dann auch gleich die Komponenten definitionen 
reinpacken. So musst du bei der Verwendung nur noch das Package 
einbinden und die Instanzierung machen.

Ja, VHDL zwingt einem hier zu etwas Fleissarbeit, habe mich aber daran 
gewöhnt und am Ende siehts dann auch übersichtlich aus.


Der Vorteil von einem extra definiertem Array Typ kommt dann sowieso 
erst bei der Beschreibung zum Tragen, da du die Variable Port Anzahl 
vermutlich mit einem for...generate abhandeln willst. Dann kannst du die 
Laufvariable des generate direkt als Array index benutzen.

von Thommy (Gast)


Lesenswert?

Die Theorie war klar, jetzt hapert es an der Praxis ;)

Ich habe mein Package:
1
PACKAGE test_package IS
2
3
  CONSTANT C_NUM   : integer := 3; -- number of ports
4
  CONSTANT C_WIDTH : integer := 3; -- port width
5
6
  TYPE test_type is array (0 to C_NUM-1) of std_logic_vector(C_WIDTH-1 downto 0);
7
8
END test_package;

Mein Entity incl. dem Port sieht dann so aus:
1
ENTITY test_entity IS
2
  PORT (
3
    ...
4
    STATUS : IN test_type;
5
    ...
6
    );
7
END test_entity;

im test_entity muss ich das Package ja sichtbar machen, damit er die 
Konstanten sieht und ich diese auch in meiner for-Schleife zu generieren 
der Logik verwenden kann:
1
USE work.test_package.ALL;

Nur wie mache ich das nun bei der Instantiierung?
Das Package sichtbar machen im Toplevel brauche ich ja nicht, solange 
ich den Port komplett "ausfülle":
1
  i0_test_entity : entity work.test_entity
2
  port map (
3
    ...
4
    STATUS => ("000", "001", "010"), -- geht das so?
5
    ...
6
    );

Nur jetzt habe ich ein festes Package, das mir eine feste Anzahl 
vorgibt. Das hilft mir ja nichts... dann kann ich den Type auch direkt 
via Generic festlegen und habe keine Probleme mehr.

Jetzt arbeite ich ja noch mit Konstanten, so dass diese mehr oder minder 
fest sind.
Wie mache ich es aber, damit ich ein GENERIC verwenden kann, der mir 
dann irgendwie via Package verschiedene Instanzen mit verschiedener 
Anzahl an Ports festlegt?

Ich stehe gerade auf dem Schlauch!
Vielen Dank!
Thommy

von Philip K. (philip_k)


Lesenswert?

1
PACKAGE test_package IS
2
3
  CONSTANT C_NUM   : integer := 3; -- number of ports
4
  CONSTANT C_WIDTH : integer := 3; -- port width
5
6
  TYPE test_type is array (natural range<>) of std_logic_vector(C_WIDTH-1 downto 0);
7
8
END test_package;
9
 
10
...
11
12
ENTITY test_entity IS
13
  GENERIC (
14
  G_NUM : integer)
15
  PORT (
16
    ...
17
    STATUS : IN test_type(0 to C_NUM-1);
18
    ...
19
    );
20
END test_entity;

Leider gibt es m.W. keine Möglichkeit die zweite Dimension auch 
generisch zu halten.

: Bearbeitet durch User
von Thommy (Gast)


Lesenswert?

Hallo,

ich habe es mit Modelsim und Synthese Check so simuliert, wie ich es 
aufgeschrieben habe und beide Dimensionen werden korrekt aufgelöst.
Ich erhalte also ein 3x3 array!
Auch die Belegung des Ports funktioniert, wo ich mir erst unsicher war.
1
  i0_test_entity : entity work.test_entity
2
  port map (
3
    ...
4
    STATUS => ("000", "001", "010"), -- das geht!
5
    ...
6
    );


Die Frage ist nur, wie ich jetzt die Dimensionen für verschiedene 
Instanzen ändern kann.
Denn bisher habe ich eine Instanz mit einem 3x3 Array.

Wenn ich jetzt in der gleichen Toplevel Entity noch eine weitere Instanz 
mit einem 4x4 Array haben möchte, geht das nicht, weil meine Dimensionen 
fest im Package definiert sind.

Gibt es dafür eine Abhilfe?

Ich möchte quasi folgendes instantiieren:
1
  i0_test_entity : entity work.test_entity
2
  port map (
3
    ...
4
    STATUS => ("000", "001", "010"), -- 3x3 Array
5
    ...
6
    );
7
8
  i1_test_entity : entity work.test_entity
9
  port map (
10
    ...
11
    STATUS => ("0000", "0001", "0010", "0011"), -- 4x4 Array
12
    ...
13
    );

Das bleibt mir mit dem aktuellen Package verwehrt!

Vielen Dank!
Thommy

von Christoph Z. (christophz)


Lesenswert?

Philip K. schrieb:
> Leider gibt es m.W. keine Möglichkeit die zweite Dimension auch
> generisch zu halten.

Jain, mit VHDL2008 ist das möglich. Ob alle deine Tools VHDL2008 können 
ist leider eine ganz andere Frage.

Aber genau solche eigentlich einfachen Beispiele machen deutlich, wieso 
VHDL2008 so wichtig ist.

von Thommy (Gast)


Lesenswert?

Ok, hatte das hier übersehen :)
1
ENTITY test_entity IS
2
  GENERIC (
3
  G_NUM : integer)
4
  PORT (
5
    ...
6
    STATUS : IN test_type(0 to C_NUM-1);
7
    ...
8
    );
9
END test_entity;

Mir reicht es vorerst aus, dass ich nur die Anzahl der Ports festlegen 
kann.
Die WIDTH war als Bonus gedacht.

Habe es jetzt erstmal hinbekommen und es läuft!
DANKE!!!

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.