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
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
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.
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?
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.
> 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
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.
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.
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.
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.
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.
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.
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.
@ 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
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 :)
@ 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
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.
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
entityselectunitis
2
port(
3
data_in:invectordata_type;
4
k_in:instd_logic_vector(31downto0);
5
data_out:outstd_logic_vector(31downto0)
6
);
7
endselectunit;
8
9
architecturertlofselectunitis
10
begin
11
data_out<=data_in(conv_integer(k_in));
12
endrtl;
Die Variante mit der Definition von k_in
1
k_in:inintegerrange0tok-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]
@ 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
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?
@ 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
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?