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
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; |
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
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
Ist der Bus denn nicht immer von derselben Breite und schiebt sich nur????
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.
Das ist doch nichts als ein Multiplexer, der aus k 32-Bit-Worten eines auswählt. Wo sind die 128 GB?
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 | 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]
@ 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?
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; |
@ 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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.