Forum: FPGA, VHDL & Co. Teil eines Signals dynamisch auswählen (VHDL)


von Harald (Gast)


Lesenswert?

Hallo,

ich arbeite an einem Modul mit VHDL bei dem ich leider nicht weiter 
komme.

Das Modul hat einen Dateneingang (data_in) an dem viele (k) 32 Bit Worte 
anliegen. Zusätzlich ist ein Ausgang vorhanden, zu dem eines dieser 32 
Bit Worte durchgeschalten werden soll. Die Auswahl welches der Worte 
verwendet wird, geschieht über einen weiteren Dateneingang (k_in). Im 
Endeffekt handelt es sich also um eine Art Multiplexer.

Der folgende (nicht funkionsfähige) VHDL Code soll die Funktion 
verdeutlichen:

entity selectunit is
    generic (
        k : positive
    );

    port (
        data_in :   in  std_logic_vector(k*32-1 downto 0);
        k_in:       in  std_logic_vector(31 downto 0);
        data_out:   out std_logic_vector(31 downto 0)
    );
end selectunit;

architecture rtl of selectunit is
begin
   data_out <= data_in ((k_in + 1)  32 - 1 downto k_in  32);
end rtl;

Da ich leider nicht besonders erfahren mit VDHL bin habe ich an zwei 
Stellen Probleme. Zum einen stimmt der Typ von k_in nicht um damit 
irgendwelche Berechnungen (multiplizieren, addieren, subtrahieren) 
durchzuführen (und die Funktion conv_integer lässt mich auch im Stich). 
Zum anderen fürchte ich, dass mir mit diesem Code Multiplizierer 
synthetisiert werden, die dann sehr viel Zeit und Chipfläche kosten.

Ich würde mich sehr freuen, wenn mir jemand einen Vorschlag machen 
würde, wie sich dieses Modul am besten realisieren lässt. (An den Ein- 
und Ausgängen sollte nach Möglichkeit nichts geändert werden müssen)

Danke im Voraus,
Harald

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ich bezweifle dass variable array slices überhaupt erlaubt sind. 
Probier's mal mit einem Array:
1
entity selectunit is
2
    generic (
3
        k : positive
4
    );
5
6
    port (
7
        data_in :   in array (k-1 downto 0) of std_logic_vector(31 downto 0);
8
        k_in:       in integer range 0 to k-1;
9
        data_out:   out std_logic_vector(31 downto 0)
10
    );
11
end selectunit;
12
13
architecture rtl of selectunit is
14
begin
15
   data_out <= data_in(k_in);
16
end rtl;

von Harald (Gast)


Lesenswert?

Ein Array zu benutzen ist eine gute Idee, danke Andreas.
1
data_in :   in array (k-1 downto 0) of std_logic_vector(31 downto 0);

Dieses Konstrukt scheint zwar nicht ganz gültig zu sein, aber mit einer 
Typdeklaration in einem Package hat es funktioniert.

Danke für den Schubs in die richtige Richtung!
Harald

von FPGA Spezialist (Gast)


Lesenswert?

Ihr werkelt an einem einfachen Konstrukt herum, um es in HDL zu 
formulieren, der aber am Ende nichts anders wird, als ein umschaltbare 
MUX.

Den kann man auch gleich per Hand formulieren....

Male Dir einfach mal auf, wie die Schaltung aussieht, und schreibe die 
genau so hin.

von Harald (Gast)


Lesenswert?

Verstehe leider nicht was du meinst ...

Das ganze Projekt wird ein Vektor-Prozessor. Das Signal data_in stellt 
den Ausgang eines kompletten Vektor-Registers dar, dessen Länge frei 
konfigurierbar sein muss. Es kann also sein, dass da jemand k=100 oder 
mehr (jeweils 32 Bit) einstellt. Selectunit ist die Schnittstelle von 
der Vektor- zur Skalar-Einheit. Damit soll ein Wort aus dem 
Vektor-Register in eins der Register der Skalar-Einheit gelenkt werden 
(Move-Befehl).

Das von Hand hinschreiben ist meiner Meinung nach wegen der Abhängigkeit 
von der Größe k nicht möglich, oder täusche ich mich da?

von FPGA Spezialist (Gast)


Lesenswert?

Kommt drauf an: Wenn man es nich teintippen kann, paast es gfs garnicht 
ins FPGA (???)

Fakt ist: Am Ende sind die einzelnen Kombinationen, die paramettriert 
werden können, ALLESAMT parallel aufzubauen - egal wie Du es 
formulierst.

Du must also zumindest ein for-Schaleife definieren, die dies Fälle ALLE 
beschreibt. IM Prinzip hast du ja einen ganzen Baum an Fällen.

Man muss ich fragen, ob man das nicht logistisch / mathematisch, also 
mit Shift-Operationen (unter Verlust einiger Clock) realisieren sollte, 
statt 100% in die Fläche zu gehen.

von Klaus F. (kfalser)


Lesenswert?

> dessen Länge frei konfigurierbar sein muss. Es kann also sein, dass da jemand 
k=100 oder mehr (jeweils 32 Bit) einstellt.

Wie stellst Du Dir das vor?
32 Bit x 2^32 sind 128 GByte. Wie sollen die in einem FPGA Platz haben?

Wenn Du wirklich ein Register brauchst, das in 32 Bit Worten organisiert 
ist und auf die man wahlweise zugreifen kann, dann solltest Du dir die 
BLOCKRAM Elemente (Xilinx) ansehen.

Klaus

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Wie kommst du auf 32 * 2**32?

von Techniker (Gast)


Lesenswert?

Ist der Bus denn nicht immer von derselben Breite und schiebt sich 
nur????

von Klaus F. (kfalser)


Lesenswert?

Wenn man das im ersten Posting angegebene Beispiel anschaut, dann ist 
k_in 32 Bit lang, also 2^32 Möglichkeiten und data_in folglich bis zu 32 
* 2^32 lang.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Das ist doch nichts als ein Multiplexer, der aus k 32-Bit-Worten eines 
auswählt. Wo sind die 128 GB?

von Klaus F. (kfalser)


Lesenswert?

GBit nicht GByte.
Wenn k wie geschrieben mit 32 Bit dargestellt wird, also maximal 
4.294.967.296 groß sein kann, dann braucht der Multiplexer 32 x 2^32 = 
128 GBit Eingangssignale.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ach so, na der Indexbereich ist ja mit dem Array schon auf k 
eingeschränkt. Dass es nicht wirklich geplant war den Bereich 2^32 
auszunutzen kann man wohl annehmen.

von Harald (Gast)


Lesenswert?

Die 32 Bit für k_in ergeben sich daraus, dass der Wert aus einem 
32-Bit-Register des skalaren Teils des Prozessors kommt. Ich bin mir 
natürlich bewusst, dass niemand diese 32 Bit wirklich ausschöpfen will, 
aber ich wollte hier auch keine harten Grenzen ziehen. Das soll 
letztendlich derjenige entscheiden, der den Prozessor konfiguriert.

von Klaus F. (kfalser)


Lesenswert?

Trotzdem ist das nicht praktikabel.
Zwischen einem Multiplexer für 5 Signalen und einem zwischen 100 ist in 
Hardware ein großer Unterschied.
Schon  mit 100 macht dir der MUX die Schaltung sehr langsam, 1000 kannst 
Du vergessen.
Entscheide dich für vernünftige Grenzen und versuche dann die Schaltung 
auszulegen.

von Mark (Gast)


Lesenswert?

Hallo Harald,

lass Dich mal nicht von den Praktikern einschüchtern, von wegen nicht 
praktikabel... ;.) Hier wird manchmal etwas weit ausgeholt.
Natürlich wird ein 32bit x n zu 32bit MUX groß und langsam. Das sollte 
jedem
klar sein. Aber wenns das FPGA hergibt kann man das ruhig machen
- why not?
Das Beispiel von Andreas Schwarz ist OK.

von Harald (Gast)


Lesenswert?

Gibt es hier vielleicht statt einer Multiplexerschaltung Alternativen? 
Die einzelnen Wörter von data_in kommen ja aus jeweils einem eigenen 
Register. Ist es eventuell möglich die Ausgänge aller dieser Register 
auf eine gemeinsame Leitung zu legen, an allen Ausgängen 'Z' anzulegen 
und nur das Register k einen Wert auf diese Leitung schreiben lassen? 
(Die Ganze Vektor-Einheit ist in Scheiben aufgebaut, lediglich die 
Selectunit bzw. ein geplantes Schuffle müssen irgendwie übergreifend 
werden.)


(Register)
----------------------------------------
|  k=0    |  k=1    |   k=2   |  K=3   |<--- k_in
----------------------------------------
     |        |          |        |
     |        |          |        |
   Data       Z          Z        Z
     |        |          |        |
     |        |          |        |
----------------------------------------
(Datenbus)


Es handelt sich bei dem ganzen Projekt übrigens um meine Diplomarbeit 
und meine Erfahrungen in VDHL bestehen nur aus dem Inhalt einer 
Vorlesung bei der nur sehr einfache Schaltungen behandelt wurden. Von 
daher bin sehr dankbar über eure Hinweise, weil ich solche Probleme 
selbst noch nicht sehe.

von adpat (Gast)


Lesenswert?

In den meisten FPGAs kann man intern kein hochohmiges 'Z' nutzen, 
Treiber dadür haben nur die Pins.

von Falk B. (falk)


Lesenswert?

@ Harald (Gast)

>Gibt es hier vielleicht statt einer Multiplexerschaltung Alternativen?
>Die einzelnen Wörter von data_in kommen ja aus jeweils einem eigenen
>Register. Ist es eventuell möglich die Ausgänge aller dieser Register

Wieso? Solche grossen Datenmengen handhabt man normalerweise wesentlich 
bsser und schneller in einemRAM, hier BRAM.

>auf eine gemeinsame Leitung zu legen, an allen Ausgängen 'Z' anzulegen
>und nur das Register k einen Wert auf diese Leitung schreiben lassen?

Das wäre ein MUX auf Tristate Basis. Ist heute a) in den modernen FPGAs 
nciht mhr machbar und b) soweso langsamer.

>Es handelt sich bei dem ganzen Projekt übrigens um meine Diplomarbeit

Was sind das für Daten? Was wird damit gemacht?

MFG
Falk

von Harald (Gast)


Lesenswert?

Das ganze Projekt wird ein Prozessor der aus einer skalaren Einheit und 
einer Vektor Erweiterung besteht. (Ähnlich eines Pentiums mit MMX 
Erweiterung, nur viel einfacher).

Die Register sind Teil der Vektor-Einheit. Es sollen deren Länge (k) und 
deren Anzahl n konfiguriert werden können. Eine Zeile davon wird 
Vektor-Register genannt. Eine Spalte wird im VHDL Code als 
32-Bit-Scheibe beschrieben.

Hier ein Beispiel mit k=6 und n=3

    31    0
    -------------------------------------------
n=0 | k=0 | k=1 | k=2 | k=3 | k=3 | k=4 | k=5 |
    -------------------------------------------
    -------------------------------------------
n=1 | k=0 | k=1 | k=2 | k=3 | k=3 | k=4 | k=5 |
    -------------------------------------------
    -------------------------------------------
n=2 | k=0 | k=1 | k=2 | k=3 | k=3 | k=4 | k=5 |
    -------------------------------------------

Es werden jeweils 2 Vektor-Register in einer Alu (genau gesagt in k 
parallelen Alus) verknüpft und zurück geschrieben. Zusätzlich soll der 
Datenaustausch mit  dem skalaren Teil des Prozessors möglich sein. Dafür 
ist die oben beschriebene "Selectunit" gedacht. Es soll ein Wort aus 
einem
k Wörter breiten Vektor-Register ausgewählt und bereit gestellt werden 
können.

k=100 scheint von mir tatsächlich viel zu hoch gegriffen worden zu sein, 
damit würde ich die Kapazität meines FPGAs mehr als nur sprengen. 
Realistisch wäre vielleicht ein Wert von 10, da habe ich keine größeren 
Probleme mit den Signallaufzeiten, denke ich.

Die Idee mit den Tristate vergesse ich auch wieder :)

von Falk B. (falk)


Lesenswert?

@ Harald (Gast)

>Die Register sind Teil der Vektor-Einheit. Es sollen deren Länge (k) und

Na also. Das löst man, wie bereits gesagt, mit einm RAM-Block.

>Es werden jeweils 2 Vektor-Register in einer Alu (genau gesagt in k
>parallelen Alus) verknüpft und zurück geschrieben. Zusätzlich soll der

Gleichzeitiger paralleler Lesezugriff auf zwei verschiedene Register 
macht man über zwei parallele Dual-Port RAMs.

>k Wörter breiten Vektor-Register ausgewählt und bereit gestellt werden
>können.

Genau das macht ein RAM!

>k=100 scheint von mir tatsächlich viel zu hoch gegriffen worden zu sein,
>damit würde ich die Kapazität meines FPGAs mehr als nur sprengen.

Nööö, kein Thema. Bei Spartan3 sind die BRAMS 16+2 kBit gross. Da mit 
kannst du 512 32 Bit Register speichern. Mit 200 MHz++.

>Realistisch wäre vielleicht ein Wert von 10, da habe ich keine größeren
>Probleme mit den Signallaufzeiten, denke ich.

Du musst dein Problem grundsätzlich anders lösen. Siehe oben.

MFg
Falk

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

So grundsätzlich anders muss das nicht sein; wenn das Lesen und 
Schreiben der Register getaktet ist wird die Synthese von alleine auf 
ein BlockRAM kommen (zumindest ISE). Kann allerdings sein dass man dazu 
die Prozesse ein bisschen umstellen muss.

von Harald (Gast)


Lesenswert?

Ja, das Synthese-Tool versucht tatsächlich die Register im Block-RAM 
abzulegen. Von daher spare ich mir momentan noch die Arbeit das 
umzustellen, und mache das eventuell später, wenn der Prozessor läuft 
und ich noch etwas mehr Geschwindigkeit oder Fläche rausholen will.

Habe aber noch eine Frage zu Arrays: Mir wird bei der Synthese immer die 
Warnung ausgegeben, dass ich eventuell über die Array Grenzen hinweg 
darauf zugreife, was auch nachvollziehbar ist. Was würde auf dem FPGA 
passieren, wenn ich tatsächlich so zugreifen würde? Bei einer Simulation 
wird diese dann abgebrochen, aber ich kann mangels FPGA momentan leider 
nicht ausprobieren was tatsächlich passiert.
1
entity selectunit is
2
    port (
3
        data_in :   in  vectordata_type;
4
        k_in:       in  std_logic_vector(31 downto 0);
5
        data_out:   out std_logic_vector(31 downto 0)
6
    );
7
end selectunit;
8
9
architecture rtl of selectunit is
10
begin
11
   data_out <= data_in(conv_integer(k_in));
12
end rtl;

Die Variante mit der Definition von k_in
1
k_in: in integer range 0 to k-1;
klingt zwar logisch, aber ich muss k_in ja aus einem 32-Bit-Register 
füttern und weiss leider auch nicht was passieren würde, wenn der 
Registerinhalt größer als dieser Bereich wäre.

Viele Grüße,
Harald
[/vhdl]

von Falk B. (falk)


Lesenswert?

@ Harald (Gast)

>darauf zugreife, was auch nachvollziehbar ist. Was würde auf dem FPGA
>passieren, wenn ich tatsächlich so zugreifen würde? Bei einer Simulation

Das kommt darauf an, wie die Synthese die Umwandlung vornimmt. Werden 
einfach die oberen Bis abgeschnitten, dann machst du einen 
Modulo-Zugriff. Sprich Register 5 ist gleich Register 5+Maximalzahl.

Wird vollständig dekodiert dann geht dein Zugriff ins Leere und das 
Ergebnis ist Null oder undefiniert.

Ich tippe auf letzteres.

MFG
Falk

von Harald (Gast)


Lesenswert?

Danke für die Antwort.

Was genau bedeutet undefiniert in diesem Zusammenhang? Könnte dann im 
Ergebnis etwas anderes als Einzen und Nullen stehen (sowas wie 'U', 'X' 
oder 'Z') oder ist das auf dem FPGA ausgeschlossen?

Für den Fall mit 'U', 'X', 'Z', wie würde man das am besten abfangen?

Hier wäre mein Vorschlag, gibt es da bessere Methoden?
1
architecture rtl of selectunit is
2
    signal index: natural;
3
begin
4
   index <= conv_integer(k_in) when (conv_integer(k_in) < k) else k-1;
5
   data_out <= data_in(index);
6
end rtl;

von Falk B. (falk)


Lesenswert?

@ Harald (Gast)

>Was genau bedeutet undefiniert in diesem Zusammenhang? Könnte dann im
>Ergebnis etwas anderes als Einzen und Nullen stehen (sowas wie 'U', 'X'
>oder 'Z') oder ist das auf dem FPGA ausgeschlossen?

Im FPGA gibts nur 0 oder 1.

MfG
Falk

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Schau mal in den Schaltplan (RTL schematic) wie das die Synthese gemacht 
hat. Wahrscheinlich sind so viele Adressleitungen wie nötig 
(ceil(log2(n))) ans RAM angeschlossen und der Rest offen?

von Harald (Gast)


Lesenswert?

Danke euch beiden, das hilft mir echt weiter.

Hab das jetzt ohne extra Überprüfung gelassen und mir etwas Logik 
gespart.

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.