Wie kann man einen 16 Bit Vektor in VHDL am schnellsten auf die 5 benötigten Dezimalstellen (6.5.5.3.5) umrechnen, ohne das dividieren oder look up zu verwenden? Ich habe es mal so versucht, dass ich jeweils anhand der vorderen Stelle entscheide, ob 1,2,3 ... 9 rauskommen soll und den Rest weitergegeben, und dann 5 von den Konstukten kaskadiert. Scheint mir aber verbesserungsfähig.
Das Millerdesign braucht offenbar 581 slices! Ach Du Schreck! :-) Spartanist schrieb: > Scheint mir aber verbesserungsfähig. In der Tat, der Direktvergleich lohnt nur bei der 3-Stellen-Version mit 8 Bit, wie ich gefunden habe. Da sind es ja nur 3 Zweige und eine Restberechung. Wenn es schnell sein muss, wirst Du ums Dividieren = inverses Multiplizieren nicht herum kommen. Wie schnell muss das sein? In der Regel ist das doch gut zu pipelinen und man kann in jedem Takt einen Wert verarbeiten. Die Division durch 10 lässt sich mit genügender Genauigkeit in geschätzt 10 Bit machen, - beim o.g. Beispiel wären es 13 Bit, wenn ich richtig rechne (y = (51 * x + 50 ) / 512). Für die Einerstellen müsste auch (25 * x + 24) / 256 reichen, denke ich. Die meisten embedded Multiplier können das in einer Stufe und die dann nötige Restbetrachtung durch Abziehen von n*x kann im folgenden Akku passieren. Mit einer Schleife bekommt man das in einem aktuellen DSP-element in 6 Takten hin. Wenn man es nur ausgeben will, müssen die Ergebnisse nicht mal zwischengespeichert werden, sondern die Ziffern purzeln in natürlicher Reihenfolge (MSF ... LSF) heraus.
J. S. schrieb: > Das Millerdesign braucht offenbar 581 slices! Ach Du Schreck! :-) Welches? Lies alles!
1 | Dieser Ansatz ist also nur geeignet, wenn Ressourcen keine Rolle spielen. |
Das heißt übersetzt: es ginge zwar, aber man macht das nicht kombinatorisch. Bei vielen Stellen nimmt man einfach das Shift-Add-6 Verfahren: http://www.lothar-miller.de/s9y/archives/34-Vektor-nach-BCD.html
Lothar Miller schrieb: > Bei vielen Stellen nimmt man einfach das Shift-Add-6 Verfahren: Wie ich aus der TB erkenne, benötigt das etwa 12-14 Takte nach dem Start. Das ist für meinen Fall leider zu langsam. J. S. schrieb: > Wie schnell muss das sein? Ich brauche das Ergebnis möglichst sofort, einige Takte Verzögerung wären akzeptabel. J. S. schrieb: > wenn ich richtig > rechne (y = (51 * x + 50 ) / 512). Für die Einerstellen müsste auch (25 > * x + 24) / 256 reichen, denke ich. Könntest Du das etwas erklären, wie das gemeint ist? >Mit einer Schleife bekommt man das in einem aktuellen > DSP-element in 6 Takten hin. Wäre das die Latenz oder die Gesamtzeit inklusive Ausgabe aller Stellen?
Spartanist schrieb: > Das ist für meinen Fall leider zu langsam. Was ist denn dein Fall? > Ich brauche das Ergebnis möglichst sofort, einige Takte Verzögerung > wären akzeptabel. Und wie schnell bräuchtest du es denn? > Wäre das die Latenz oder die Gesamtzeit inklusive Ausgabe aller Stellen? Nein. Es wäre eine einzige Zehnerstelle ohne jegliche Ausgabe wo auch immer hin (weil die Ausgabe mit der Wandlung ja schon gleich überhaupt nichts zu tun hat, und ausserdem parallel erfol > Könntest Du das etwas erklären, wie das gemeint ist? Kannst du mal erklären, WAS du machen willst und WOFÜR du das brauchst?
was spricht gegen die LUT ? in zwei Takten bist du durch... Gut, is ä weng mehr Arbeit. Cheers
ähmm.. schrieb: > was spricht gegen die LUT ? Wie groß würdest du die LUT denn machen? Es könnte sein, dass da die Lösung mit den 581 Slices noch klein aussieht dagegen... :-o > in zwei Takten bist du durch... Zeig mal...
Lothar Miller schrieb: > Spartanist schrieb: >> Das ist für meinen Fall leider zu langsam. > Was ist denn dein Fall? Eine Datenausgabe über einen herstellerspezifischen Bus. Die Daten kommen als 32Bit-Vektoren an und sollen in Echtzeit ausgeben werden. Damit die (langsame) embedded CPU das nicht tun muss, soll es der FPGA machen und schon mal wandeln. >> Ich brauche das Ergebnis möglichst sofort, einige Takte Verzögerung >> wären akzeptabel. > Und wie schnell bräuchtest du es denn? So schnell wie möglich, weil ich die Daten zu sammen mit anderen ausgeben muss und diese sonst in einem Fifo halten muss, was je Takt etwa 50-80 Register-FFs braucht. >> Wäre das die Latenz oder die Gesamtzeit inklusive Ausgabe aller Stellen? > Nein. Es wäre eine einzige Zehnerstelle ohne jegliche Ausgabe D.h. 6 Takte je Zehnerstelle? Ich brauche 32 Bit und damit 8 Stellen.
Spartanist schrieb: > Eine Datenausgabe über einen herstellerspezifischen Bus. Die Daten > kommen als 32Bit-Vektoren an und sollen in Echtzeit ausgeben werden. Und warum muss das Dezimal geschehen? Rechner arbeiten am besten und schnellsten Binär... > Die Daten > kommen als 32Bit-Vektoren an und sollen in Echtzeit ausgeben werden. Wie schon mal erwähnt: Lothar Miller schrieb: >> Und wie schnell bräuchtest du es denn? Zeiten werden in us angegeben, Datenraten in Bytes/s oder auch Worten/s usw. usf. > D.h. 6 Takte je Zehnerstelle? Ich brauche 32 Bit und damit 8 Stellen. Ja, dann rechne das mal aus. Und am besten noch ein wenig Handlingsgebühr dazu... >>> Ich brauche das Ergebnis möglichst sofort, einige Takte Verzögerung >>> wären akzeptabel. >> Und wie schnell bräuchtest du es denn? > So schnell wie möglich, weil ich die Daten zu sammen mit anderen > ausgeben muss und diese sonst in einem Fifo halten muss, was je Takt > etwa 50-80 Register-FFs braucht. Du könntest da mit einem Fifo im BRAM was dagegen tun...
Lothar Miller schrieb: > Spartanist schrieb: >> Eine Datenausgabe über einen herstellerspezifischen Bus. Die Daten >> kommen als 32Bit-Vektoren an und sollen in Echtzeit ausgeben werden. > Und warum muss das Dezimal geschehen? Rechner arbeiten am besten und > schnellsten Binär... Weil sie halt ausgegeben werden sollen und die Umrechnung im schnellen FPGA erfolgen soll. >> kommen als 32Bit-Vektoren an und sollen in Echtzeit ausgeben werden. >Lothar Miller schrieb: > Zeiten werden in us angegeben, Datenraten in Bytes/s oder auch Worten/s Die Datenrate ist am Anschlag. Es kann nichts zwischengespeichert werden. >> D.h. 6 Takte je Zehnerstelle? Ich brauche 32 Bit und damit 8 Stellen. > Ja, dann rechne das mal aus. Und am besten noch ein wenig > Handlingsgebühr dazu... Schon passiert, 50 Takte ist zuviel >> So schnell wie möglich, weil ich die Daten zu sammen mit anderen > Du könntest da mit einem Fifo im BRAM was dagegen tun... Braucht auch wieder Verwaltung und Platz, was ich mir gerne ersparen würde.
Bann nimm "meinen" bin2bcd-Wandler und instantiiere 20 davon. Deinen ersten 32-Bit-Wert schickt du in den ersten Wandler, den nächsten 32-Bit-Wert in den zweiten und so fort... So hast du ein paar Takte Latency, aber einen guten Durchsatz... ;-)
Lothar Miller schrieb: > Bann nimm "meinen" bin2bcd-Wandler und instantiiere 20 davon. Deinen > ersten 32-Bit-Wert schickt du in den ersten Wandler, den nächsten > 32-Bit-Wert in den zweiten und so fort... > So hast du ein paar Takte Latency, aber einen guten Durchsatz... ;-) Ich glaube, ich belasse es besser bei meinem IF-Konstrukt, wie oben beschrieben. Der geht im schlimmsten Fall auch in einem Takt.
Spartanist schrieb: >> Ich habe es mal so versucht, dass ich jeweils anhand der vorderen Stelle >> entscheide, ob 1,2,3 ... 9 rauskommen soll und den Rest weitergegeben, >> und dann 5 von den Konstukten kaskadiert. Spartanius schrieb: > Der geht im schlimmsten Fall auch in einem Takt. Ja, das ist so. Die Taktfrequenz muss nur langsam genug sein für (in deinem aktuellen 32-Bit-Fall) annähernd 80 Vergleicher, dann 8 Subtrahierer, einige Multiplexer und was sonst noch dazukommt. Wie schnell ist denn dieses Elaborat? Was sagt die Synthese zum Thema maximale Taktfrequenz?
Lothar Miller schrieb: > J. S. schrieb: >> Das Millerdesign braucht offenbar 581 slices! > Welches? Lies alles! Langsam, langsam, ich bezog mich auf das von "Duke Scarring" gelinkte Design. Das ist das einzige, dass die Kriterien des TE erfüllt (also, schneller wäre, als seine Methode) und dieses hat diesen Bedarf. >Dieser Ansatz ist also nur geeignet, wenn Ressourcen keine Rolle spielen. Das habe ich selbstverständlich gelesen, aber auch in dem Fall, in dem man einseitig auf Tempo setzt und Resourceneinsatz ok wäre, ist das nicht der Weisheit letzter Schluss: Ich hatte hier... Beitrag "Re: Schnelle Conversion bin2dec" ... ja bereits beschrieben, wie das funktioniert, wenn man auf Tempo designen möchte. Die Methode ist sowohl für sequenziellen Betrieb, als auch parallelen Betrieb machbar und dies im Übrigen sogar komplett kombinatorisch, in dem man die Multiplier durch Adder ersetzen lässt (es sind nur 4 Additionen) und alles in einen Takt schreibt. Dann kann die Synthese das auch runteroptimieren und Teile der Additionen mit der Subtraktion und Restbildung zusammenfassen. Lothar Miller schrieb: >> Wäre das die Latenz oder die Gesamtzeit inklusive Ausgabe aller Stellen? > Nein. Es wäre eine einzige Zehnerstelle ohne jegliche Ausgabe wo > auch immer hin (weil die Ausgabe mit der Wandlung ja schon gleich > überhaupt nichts zu tun hat, und ausserdem parallel erfolt Ihr habt das wohl beide nicht verstanden, wie ich das gemeint habe, also nochmal: Jede der Dezimalstellen wird von einem DSP-Element gerechnet und das bei den meisten FPGAs in einem einzigen Takt! Die Ausgabe hat mit der Wandlung insofern zu tun, als das bei der üblichen Nutzung zuerst die höherwertigen Stellen auf eine Anzeige gebracht werden und danach jede weitere in einem anderen Takt, sei es ein VGA-Buffer oder ein Display. Daher macht es Sinn, das sequenziell mit nur einem DSP-Element zu machen und pro Stelle einen Taktzyklus zu investieren. Das Dingens rechnet dann iterativ und wirf mit jedem Takt die anzuzeigende Ziffer raus. Klappt bestens. Die Nutzung des DSP-Elementes, also genauer eines Multiplizierers und Subtrahierers tritt zusammen mit der geschickten Rundung an die Stelle der oben ebenfalls vorgeschlagenen LUT, bzw im anderen Vorschlag des Shift-Adders-Elementes. Dieses wäre, nebenbei gesagt, auch pipelinebar und / oder voll kombinatorisch aufzubauen, wenn man die FSM entfernt und die ablaufenden Zyklen schon während der Synthese per generate in eine Schaltung umsetzt. Das Shift-Adder Element macht nämlich bei genauerer Betrachtung nicht anderes, als partiell bedingt zu multiplizieren. Es ist eben nur aus Slices aufgebaut, während der MUL i.d.R schon vorhanden ist. Spartanist schrieb: > D.h. 6 Takte je Zehnerstelle? Ich brauche 32 Bit und damit 8 Stellen. Das ist eben genau nicht richtig! Du bekommst aus einem 16 Bit-Vektor 5 Stellen und damit insgesamt die o.a. 6 Takte. In Deinem Fall, bei 32 Bit, sind das zudem auch nicht 8 Stellen, wie Du meinst, sondern 10, jedenfalls, wenn der Vektor voll ausgesteuert wird. Wenn Du das mit einer MUL-SUB-Anordnung wie oben beschrieben, machst, brauchts Du 11 Takte, gfs 12 für das gesamte Rechnen und Übertragen der letzen Ziffer. Wenn Du die nicht sofort wegschicken kannst, oder darfs, musst Du eben mit allem warten, bis die letzte Ziffer parat ist. Die Rechnung kann mit einem schnellen FPGA aber locker auf 250MHz getaktet werden, was immerhin 20MHz Datenrate wären. Viel mehr dürfte Deine CPU nicht abkönnen, sage ich mal. Anders heum gesehen muss man sich fragen, ob man nicht doch die CPU das rechnen lässt, denn iterieren sollte die wohl auch können.
Die oben angesprochenen Verfahren habe ich nicht verstanden und bin deshalb nicht sicher, ob das, was ich jetzt vorschlage, etwas neues ist oder mit einem dieser Verfahren übereinstimmt: Die 2er-Potenzen 2^0 .. 2^15 sind 16 5-stellige BCD-Konstanten. Man bildet die per 15-facher BCD-Addition gebildete Summe (Konstante0)*(b0) + .. + (Konstante15)*(b15) wobei b0 .. b15 die Eingangs-Bits sind.
Josef G. schrieb: > Die 2er-Potenzen 2^0 .. 2^15 sind 16 5-stellige BCD-Konstanten. > Man bildet die per 15-facher BCD-Addition gebildete Summe > (Konstante0)*(b0) + .. + (Konstante15)*(b15) > wobei b0 .. b15 die Eingangs-Bits sind. Das habe jetzt ich nicht verstanden. Ist das nicht der umgekehrte Weg von BCD-to-DEZ? Lothar Miller schrieb: > Bann nimm "meinen" bin2bcd-Wandler und instantiiere 20 davon. Deinen > ersten 32-Bit-Wert schickt du in den ersten Wandler, den nächsten > 32-Bit-Wert in den zweiten und so fort... Ich habe probehalber die angegebene Schaltung mit dem Schieberegister im Original synthetisiert und erhalte 18 Takte für einen 16 Bit-Vektor, bei 20 slices und 64 registern. Für 32 Bit sind es dann wohl geschätzt 34 Takte bei 40 slices. Bei 32 Schaltungen also 1200 slices. J. S. schrieb: > In Deinem Fall, bei 32 Bit, sind das zudem auch nicht 8 Stellen, wie Du > meinst, sondern 10, jedenfalls, wenn der Vektor voll ausgesteuert wird. ok, kann sein, der range ist 0 ... 2hoch32-1. > Wenn Du das mit einer MUL-SUB-Anordnung wie oben beschrieben, machst, > brauchts Du 11 Takte, gfs 12 für das gesamte Rechnen und Übertragen der > letzen Ziffer. Klingt nicht schlecht. Leider ist mir der Weg immer noch nicht verständlich, wie man auf diese Formel kommt: > rechne (y = (51 * x + 50 ) / 512) ?
Spartanius schrieb: > Für 32 Bit sind es dann wohl geschätzt 34 Takte bei 40 slices. > Bei 32 Schaltungen also 1200 slices. Brauchst du 32 solcher Schaltungen? Kommt jeden Takt ein neues Wort herein? Wie sendest du die Daten dann wieder raus (wenn/weil ja aus jedem 32-Bit-Vektor 10 Stück 4-Bit-BCD-Vektoren werden)...
Lothar Miller schrieb: > Spartanius schrieb: >> Für 32 Bit sind es dann wohl geschätzt 34 Takte bei 40 slices. >> Bei 32 Schaltungen also 1200 slices. > Brauchst du 32 solcher Schaltungen? war ja Dein Vorschlag :-) > Kommt jeden Takt ein neues Wort herein? Es wird pro FPGA-Takt (letztlich ~60-70MHz) / 16 eine Datengruppe berechnet, die zu wahrscheinlich 6 bis 8 Werten führt. Das sind 30MHz Daten unterschiedlicher Breite. Einige Werte müssen zusammen mit anderen Werten an die CPU. Diese müssen teilweise gewandelt werden. Die Daten werden berechnet und gesendet und sobald die letzten Daten berechnet sind, stehen mir auch die Werte zu wandeln zur Verfügung. Die müssen sofort raus (60 MHz x 32 Bit), weil ich keine Bustakte verlieren darf. Lücke ist nicht, da die CPU noch andere Sachen machen muss. Wenn ich zum Umrechnen Takte brauche, muss ich die anderen Daten zwischenspeichern, damit das Paket kompakt bleibt. > Wie sendest du die Daten dann wieder raus ~60MHz x 32 Bit, also bezüglich der Dezimalzahlen max 4 Zahlen je Takt.
Spartanius schrieb: > Ist das nicht der umgekehrte Weg von BCD-to-DEZ? Die Frage im Eröffnungsbeitrag war, eine 16bit-Dualzahl solle in eine 5 Ziffern lange Dezimalzahl umgewandelt werden. Jede Dezimalziffer wird dargestellt durch 4 Bit im Bereich 0000 bis 1001. "BCD" und "DEZ" sind in diesem Sinne dasselbe. Die Zahl ist gegeben in Dualdarstellung (2^0)*(b0) + .. + (2^15)*(b15) Man schreibt 2^0 .. 2^15 einzeln als Dezimalzahlen, multipliziert mit b0 .. b15 und addiert die Ergebnisse dezimal. So erhält man die gesuchte Dezimaldarstellung der Zahl. Die Additionen kann man baumartig zusammenfassen und parallel ausführen. Einziges Problem dabei ist, dass man Dezimal-Addierer braucht. Ob der Hardware-Aufwand dann noch vertretbar ist, wenn jetzt statt 16bit von 32bit die Rede ist, weiss ich nicht.
Josef G. schrieb: > Die Zahl ist gegeben in Dualdarstellung (2^0)*(b0) + .. + (2^15)*(b15) > Man schreibt 2^0 .. 2^15 einzeln als Dezimalzahlen, multipliziert > mit b0 .. b15 und addiert die Ergebnisse dezimal. So erhält man > die gesuchte Dezimaldarstellung der Zahl. Ich stehe da irgendwie auf dem Schlauch! Angenommen, ich habe die 16-bit-Zahl 51432. (den 32-bit-Fall lassen wir jetzt mal beiseite). Diese binäre Zahl liegt vor als: 1100.1000.1110.1000 Was fange ich damit an? Rauskommen muss 0101.0001.0100.0011.0010 So mache ich das bisher: IF (Zahl >= 60000) THEN OUT5 <= 6; REST <= Zahl - 60000; ELSIF (Zahl >= 50000) THEN OUT5 <= 5; REST <= Zahl - 50000; ... ELSIF (Zahl >= 10000) THEN OUT5 <= 1; REST <= Zahl - 10000; ELSE OUT5 <= 0; REST <= Zahl Das geht dann in die nächste Stufe, die genau so aussieht und OUT4 berechnet. Frage: Was ist bei Dir jetzt "b"? So wie Du das beschreibst, errechnest Du doch einfach den Dezimalwert aus der BSD-Darstellung, oder nicht?
Spartanius schrieb: > So wie Du das beschreibst, errechnest Du doch einfach den Dezimalwert > aus der BSD-Darstellung, oder nicht? Verstehe ich nicht. Gegeben ist die Dualzahl c8e8 (in Hex-Schreibweise). Ich erhalte mit meinem Verfahren die Dezimalzahl 51432 (*) wobei die einzelnen Ziffern binär codiert sind. Da hast Du doch die Ziffern, die Du brauchst? Oder blick jetzt ich nicht durch? (*) würde ich evtl. vorrechnen, aber nur wenn erforderlich.
(*) Mach das bitte mal. Meinetwegen auch mit einer kleineren Zahl. Ich habe da einen Verdacht...
Ich rate mal: C x 256 x 256 x 256 8 x 256 x 256 E x 256 8 liefert die Einzelergebnisse. Dann schlägt der Dezimaladdierer zu. Sowas konnten früher einige 8-Bit Prozessoren, wenn man sie auf BCD umgeschaltet hat. Letztlich ist das aber nichts anderes. Die "Intelligenz" (und auch der Aufwand) steckt im Addierer. Das muss von der Hardware vorgesehen sein, wenn es effektiv sein soll, was aber bei FPGAs definitiv nicht so ist. Spartanius schrieb: > Klingt nicht schlecht. Leider ist mir der Weg immer noch nicht > verständlich, wie man auf diese Formel kommt: >> rechne (y = (51 * x + 50 ) / 512) Das ist die benötigte Division durch 10 und zwar die kleinst denkbarste, die gerade keine Rundungsfehler produziert. Allerdings sehe ich gerade, dass das die für 8 Bit ist. Sie ist genau bis 255. Für eine Stelle reicht auch weniger. Du rechnest einfach Folgendes: Zehntausender = Eingabezahl / 10000. Die 10000 bilstest du ab auf z.B. 16384 und multiplizierst zuvor mit 1.6384. Die Auflösung der jeweiligen MUL muss so gewählt werden, dass sie nach dem Abschneiden der Stellen nicht zu einem Fehler kommt. In der Regel muss man mit +0.5 runden. Aufgrund der Genauigkeit ist die Rechnung bei der grössten Zahl am Aufwändigsten. Beispiel: Ausgabezahl = (3435973 * Eingabe + 343597) / 34359738368 Rest = Eingabe - 10000 * Ausgabezahl. Du musst jetzt die kleinste mögliche Rechung finden, um sie den einzelnen Stufen anzupassen. Wenn du sequenziell arbeitest, nutzt Du diese eine eben mehrfach. Die Rechnung macht letztlich das, was Deine IF-THENs tun, nur halt in einem Takt. Ein aktueller FPGA hat z.B. 18x25 Bit-MULS.
Lothar Miller schrieb: > (*) Mach das bitte mal. Meinetwegen auch mit einer kleineren Zahl. Beispiel: Dual 6c / Soll-Ergebnis Dezimal 108 6c Hex = (ab hier ist alles dezimal) 1*0 + 2*0 + 4*1 + 8*1 + 16*0 + 32*1 + 64*1 + 128*0 = 4 + 8 + 32 + 64 = 108 Letzte Zeile ausgeführt mit BCD-Addierern: 4 + 8 --> 0000.0000.0100 + 0000.0000.1000 = 0000.0001.0010 32 + 64 --> 0000.0011.0010 + 0000.0110.0100 = 0000.1001.0110 Gesamtsumme = 0001.0000.1000 Begründung: In Zeile 4+8 : 0100 + 1000 --> 1100 (duale Addition) --> 1.0010 (nach BCD-Korrektur) Bei Bildung der Gesamtsumme Berechnung der mittleren Stelle: --> 1010 (duale Addition) --> 1.0000 (nach BCD-Korrektur) http://next-internet.com/ti_1/texte/ti1_2005_01_31_4f.pdf (Abschnitt 5.2.4)
Um eine 32bit Dualzahl in die Dezimaldarstellung umzuwandeln, braucht man die Konstanten 2^0 .. 2^31 in Dezimaldarstellung. Jede Konstante wird mit 0 oder 1 multipliziert je nach dem entsprechenden Bit der gegebenen Dualzahl. Die 32 Resultate sind mit BCD-Addierern zu addieren. Man kann die Zahl der Addierer verringern, indem man zB. die untersten zwei Schichten des Addierer-Baums dadurch ersetzt, dass man die Summen vorab berechnet und dann die richtige Summe per Multiplexer auswählt: Gegeben sei die Dualzahl H7.H6.H5.H4.H3.H2.H1.H0, wobei die Hi die Hex-Ziffern sind. Man hat die Dezimal-Konstanten 0*(16^7), 1*(16^7), ..., 15*(16^7) H7 wählt eine davon aus 0*(16^6), 1*(16^6), ..., 15*(16^6) H6 wählt eine davon aus ... 0*(16^1), 1*(16^1), ..., 15*(16^1) H1 wählt eine davon aus 0*(16^0), 1*(16^0), ..., 15*(16^0) H0 wählt eine davon aus Man erhält so 8 Dezimalzahlen und braucht noch 4+2+1=7 BCD-Addierer, um alles zu addieren.
Josef G. schrieb: > Um eine 32bit Dualzahl in die Dezimaldarstellung umzuwandeln, > braucht man die Konstanten 2^0 .. 2^31 in Dezimaldarstellung. Aber die muss ich auch erst mal wieder erzeugen, dann brauche ich die ominösen BCD-Addierer. Die Multiplexer, die Du beschreibst, brauchen auch wieder Platz und Zeit und wehe, sie sind nicht in einem Takt zu machen, dann müssen die breiten Vektoren registriert werden. Ich kann mir beim besten Willen nicht vorstellen, dass das schneller ist. Ich glaube zudem immer noch, dass Deine Interpretation der Fragestellung eine andere ist: Du schreibst: Josef G. schrieb: > 32 + 64 --> 0000.0011.0010 DAS!!! ist aber genau der Stiefel! Wie kommt man in einem Schlag auf die Umrechnung der Binärzahl auf die Deziamldarstellung? Du nimmst in Deinem Beispiel die 11.0010 = 0.3.2 einfach an, aber vorliegen "tut" die Zahl als 0010000. Ich denke, wir drehen uns da im Kreis. Alles, was ich da erkenne, ist mehr und aufwändiger. Die Umrechung mit dem Shift-Addierer leistet ja dasselbe udn ist kleiner und schneller. Einzige das hier werde ich noch prüfen: J. S. schrieb: > Ausgabezahl = (3435973 * Eingabe + 343597) / 34359738368 > Rest = Eingabe - 10000 * Ausgabezahl. Soweit habe ich das kapiert - Du teilst einfach durch 10 und rechnest den Rest. Das Problem, das ich sehe, sind die 32Bit breiten Zahlen: Ich müsste sie mit einem so grossen Teiler bearbeiten, dass die Genauigkeit gerade noch reicht. Das sind aber aber 32Bit immerhin 10-1=9 Stellen. Ich brauche also einen geschätzt 32 Bit breiten Multiplizierer, der ein Ergebnis mit 64 Bit fassen kann. Das geht in keinem Fall mit nur einem Element, zumal in meinem FPGA nur 18x18 Multis zur Verfügung stehen. Ich werde mal versuchen, es zu bauen und schauen, wie schnell es ist. Ich gehe davon aus, dass ich mindestens 3 Takte brauche, um die Multiplikation hinzubekommen und einen weiteren für die Addition des Offsets / bzw die Subraktion. Jede Stufe hätte also 4 Takte = 40 Takte insgesamt. Das kommt dann schon in dieselbe grössenordnung, wie die Miller-Methode und sich verbraucht wertvolle Multiplier!
Spartanist schrieb: > Aber die muss ich auch erst mal wieder erzeugen, Nein, die rechnest du im Kopf oder mit dem Taschenrechner aus und definierst sie im VHDL-Design als Konstanten. > Die Multiplexer, die Du beschreibst, brauchen auch wieder Platz Da die gemultiplexten Werte Konstanten sind, besteht ein Multiplexer nur aus einer einzigen LUT für jedes Bit. > Josef G. schrieb: >> 32 + 64 --> 0000.0011.0010 > > DAS!!! ist aber genau der Stiefel! Wie kommt man in einem Schlag auf die > Umrechnung der Binärzahl auf die Deziamldarstellung? Du hast den Zwischenschritt aus meinem Beitrag weggelassen: > 32 + 64 --> 0000.0011.0010 + 0000.0110.0100 = 0000.1001.0110 Die beiden Einzelwerte werden als Konstanten in das Design hineingesteckt. Die Summe liefert der BCD-Addierer. > Alles, was ich da erkenne, ist mehr und aufwändiger. Ich will nicht behaupten, dass mein Verfahren besser ist. War nur ein Hinweis auf eine Alternativ-Möglichkeit.
Ich gebe zu, ich kapiere nicht, wie das gehen soll und an welcher Stelle man was tun muss. Könnte man das anhand einer Formel oder eines VHDL-Beispiels beschreiben? Josef G. schrieb: > Du hast den Zwischenschritt aus meinem Beitrag weggelassen: > >> 32 + 64 --> 0000.0011.0010 + 0000.0110.0100 = 0000.1001.0110 > > Die beiden Einzelwerte werden als Konstanten in das Design > > hineingesteckt. Die Summe liefert der BCD-Addierer. Ich glaube, so langsam komme ich auf den Trichter: Du hängst Dich an der Bildung der Endsumme auf. Darum geht es aber nicht. Es geht um den Wert 0000.0011.0010. Wie kommt man im allgemeinen Fall zu diesem? aus dem Kopf kann ich das sofort sehen, ja, aber wie sieht es der FPGA? Ich habe doch diesen Wert nicht, ohne in zu berechen. Dass ich ihn in einen BCD Addierer schieben kann, ok, mag sein. Wobei noch zu klären wäre, wie der dann aussehen müsste.
Spartanist schrieb: > Es geht um den Wert 0000.0011.0010. constant zweihochfuenf : std_logic_vector (11 downto 0) := x"032"; (bin nicht sicher bzgl. der genauen Syntax)
Ok, JETZT habe ich es: Du verwendest die einzelnen Bits des Vektors jeweils einzeln und multiplizierst Dir 32 Teilergebnisse in BCD-format hin. Das sieht dann offenbar so aus: 1) XXXX.XXXX.XXXX 2) + XXXX.XXXX.XXXX 3) + XXXX.XXXX.XXXX ... 32) + XXXX.XXXX.XXXX Da sehe ich 3 Problme: 1) Muss man sich überlegen, was man womit addiert, oder man muss alles formulieren und die Synthese das Gewurschtel zusammenfassen lassen. 2) Ich bekomme eine gewaltige Menge an Scheinaddieren, die sich gfs nicht vernüftig zusammenfassen lassen, bzw die Synthese kreigt es nicht 100% hin 3) Ich muss diese BCD-Addierer bauen und die scheinen mir nicht anders funktionieren zu können als selektive Addierer mit Umschaltungen, wenn ein Überlauf entseht. Ich denke, dass das mathematisch 100% funktioniert, aber umsetzungstechnisch schon ein bischen ein overkill ist. Ich glaube auch nicht, dass das kleiner wird. Ich synthetisiere gerade mein design für S3E: Hat 210 slices mit 30 MHz netto ohne irgendwas. Wenn ich es in ein design packe, 3 FF stage dahinter packe und retiming verwende, gelange ich zu den gewünschten 60MHz
Spartanist schrieb: > Ich synthetisiere gerade mein design für S3E: > Hat 210 slices mit 30 MHz netto ohne irgendwas. > > Wenn ich es in ein design packe, 3 FF stage dahinter packe und retiming > verwende, gelange ich zu den gewünschten 60MHz Ich kann das hier bieten: 1 Takt pro BCD-Stelle, Takt 70MHz auf einem S3, Verbrauch 78 Slices, Aufwand 15 Minuten... (ich hatte nur den Thread aus dem Auge verloren ;-)
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity Vector2BCD is |
6 | Port ( clk : in std_logic; |
7 | vector : in std_logic_vector (15 downto 0); |
8 | start : in std_logic; |
9 | busy : out std_logic; |
10 | bcd : out std_logic_vector (19 downto 0)); |
11 | end Vector2BCD; |
12 | |
13 | architecture Behavioral of Vector2BCD is |
14 | type states is (idle,calc); |
15 | signal state : states := idle; |
16 | signal stelle : integer range 0 to 4; |
17 | signal wert : integer range 0 to 100000; |
18 | begin
|
19 | process
|
20 | variable x : integer range 0 to 100000; |
21 | begin
|
22 | wait until rising_edge(clk); |
23 | busy <= '0'; |
24 | case state is |
25 | when idle => |
26 | wert <= to_integer(unsigned(vector)); |
27 | if (start='1') then |
28 | stelle <= 4; |
29 | busy <= '1'; |
30 | state<=calc; |
31 | end if; |
32 | |
33 | when calc => |
34 | x := wert; |
35 | if (x>=90000) then x:=x-90000; bcd(stelle*4+3 downto stelle*4) <= x"9"; |
36 | elsif (x>=80000) then x:=x-80000; bcd(stelle*4+3 downto stelle*4) <= x"8"; |
37 | elsif (x>=70000) then x:=x-70000; bcd(stelle*4+3 downto stelle*4) <= x"7"; |
38 | elsif (x>=60000) then x:=x-60000; bcd(stelle*4+3 downto stelle*4) <= x"6"; |
39 | elsif (x>=50000) then x:=x-50000; bcd(stelle*4+3 downto stelle*4) <= x"5"; |
40 | elsif (x>=40000) then x:=x-40000; bcd(stelle*4+3 downto stelle*4) <= x"4"; |
41 | elsif (x>=30000) then x:=x-30000; bcd(stelle*4+3 downto stelle*4) <= x"3"; |
42 | elsif (x>=20000) then x:=x-20000; bcd(stelle*4+3 downto stelle*4) <= x"2"; |
43 | elsif (x>=10000) then x:=x-10000; bcd(stelle*4+3 downto stelle*4) <= x"1"; |
44 | else bcd(stelle*4+3 downto stelle*4) <= x"0"; |
45 | end if; |
46 | wert <= x*10; |
47 | |
48 | if stelle=0 then |
49 | busy <= '0'; |
50 | state <= idle; |
51 | else
|
52 | busy <= '1'; |
53 | stelle <= stelle-1; |
54 | end if; |
55 | |
56 | end case; |
57 | end process; |
58 | end Behavioral; |
ok, das sieht nicht schlecht aus. Ist eine Mischung aus meinem Design und einer zyklischen Bearbeitung. Vom speed her passt es ja auch, dann probiere ich es gfs mal aus, wenn ich die Zeit habe, leider plagen mich einige andere technische Sorgen: Beitrag "Resourcenproblem mit Spartan6"
Spartanist schrieb: > Soweit habe ich das kapiert - Du teilst einfach durch 10 und rechnest > den Rest. Das Problem, das ich sehe, sind die 32Bit breiten Zahlen: Das stimmt natürlich, für 32 Bits wird das bei den schwachbrüstigen FPGAs nicht mehr in einem Takt machbar sein, wobei ich denke, dass dann die LÖsung mit der Kombinatorik besser sein müsste, weil sich die Folgeschritte, z.B. die Subraktion etc. damit verheiraten lassen und weniger Logik-Tiefe rauskommt, als bei verketteten Multipliern samt Adder-chain. Käme auf einen Versuch an. Ich würde aber mal denken, dass in diesem Fall die internen LUT-/Bitkombinationen, die bei der Optimierung des kombinatorischen Multipliers entstehen, irgendwo dieselben sein müssten, wie sie bei der ausdrücklichen Abfragemethode mit den 10 Zweigen entstehen, da es ja derselbe Informationsgehalt ist, der verarbeitet wird und alles Unbenutzte an Bitausgängen rausflöge, weil der gleiche Vektor abgefragt wird. Das Problem ist in beiden Fällen die Bitbreite. Lothars Code müsste dann auch auf die volle Stellenzahl aufgebohrt werden, also auf sogar 9.000.000.000 abgefragt werden, wegen der unteren Stellen. Der Code sollte am Ende aber nicht ineffektiver sein, als Deine verketteten Abfragen, weil deren Ergebnisse auch irgendwie registriert werden müssten um auf die Geschwindikeit zu kommen. In 1-2 Takten bekommt man das aufgrund der Grösse einfach nicht hin. Die verketteten Abfragen also alle hinzuschreiben, wie Du es machst, hat damit nur den Vorteil der vollen Bandbreite, wenn wirklich mit jedem FPGA-Takt auch Daten kommen.(?) Vielleicht kann man je jeweils 2 Stufen zusammenfassen, vierfach pipelinen und 4fach takten, um den Umrechner genügend schnell gegenüber der datenspeisenden domain zu machen. Ich denke aber, dass alle Versuche letztlich immer wieder zu mehr FFs führen werden und kein Einspareffekt erzielt werden kann.
J. S. schrieb: > Lothars Code müsste dann > auch auf die volle Stellenzahl aufgebohrt werden, also auf sogar > 9.000.000.000 abgefragt werden, wegen der unteren Stellen. Ich habe nun bei beiden Versionen (der letzten von Lothar und der meinen) das Problem, dass ich nicht durch den Endwert teilen kann. Ich habe das o.g. design auf 9.000.000.000 erweitert und schlage, wie bei meinem an dem Integerwert für 32 Bit an, wobei er mir 2h31 schon nicht mehr baut. Ich müsste also erst auf die erste Stelle prüfen (1,2,3,4) da 32 Bit ja 4 Mia sein können und danach mit den unteren Stellen fortfahren. So, wie es jetzt ist, funzt die Schaltung nur für Werte <= 999.999.999. Gibt es dafür eine elegante Abfrage, die nicht an der INT-Granze scheitert?
Spartanist schrieb: > Gibt es dafür eine elegante Abfrage, die nicht an der INT-Granze > scheitert? Man kann unsigned nehmen, das geht auch weit über die integer Grenze raus:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity Vector2BCD is |
6 | Port ( clk : in std_logic; |
7 | vector : in std_logic_vector (31 downto 0); |
8 | start : in std_logic; |
9 | busy : out std_logic; |
10 | bcd : out std_logic_vector (39 downto 0)); -- 10 BCD-Stellen |
11 | end Vector2BCD; |
12 | |
13 | architecture Behavioral of Vector2BCD is |
14 | type states is (idle,calc); |
15 | signal state : states := idle; |
16 | signal stelle : integer range 0 to 9; |
17 | signal wert : unsigned (35 downto 0); |
18 | begin
|
19 | |
20 | process
|
21 | variable x : unsigned (35 downto 0); |
22 | begin
|
23 | wait until rising_edge(clk); |
24 | busy <= '0'; |
25 | case state is |
26 | when idle => |
27 | wert <= "0000"&unsigned(vector); |
28 | if (start='1') then |
29 | stelle <= 9; |
30 | busy <= '1'; |
31 | state<=calc; |
32 | end if; |
33 | |
34 | when calc => |
35 | x := wert; |
36 | if (x>=x"218711a00") then x:=x-x"218711a00"; bcd(stelle*4+3 downto stelle*4) <= x"9"; |
37 | elsif (x>=x"1dcd65000") then x:=x-x"1dcd65000"; bcd(stelle*4+3 downto stelle*4) <= x"8"; |
38 | elsif (x>=x"1a13b8600") then x:=x-x"1a13b8600"; bcd(stelle*4+3 downto stelle*4) <= x"7"; |
39 | elsif (x>=x"165a0bc00") then x:=x-x"165a0bc00"; bcd(stelle*4+3 downto stelle*4) <= x"6"; |
40 | elsif (x>=x"12a05f200") then x:=x-x"12a05f200"; bcd(stelle*4+3 downto stelle*4) <= x"5"; |
41 | elsif (x>=x"0ee6b2800") then x:=x-x"0ee6b2800"; bcd(stelle*4+3 downto stelle*4) <= x"4"; |
42 | elsif (x>=x"0b2d05e00") then x:=x-x"0b2d05e00"; bcd(stelle*4+3 downto stelle*4) <= x"3"; |
43 | elsif (x>=x"077359400") then x:=x-x"077359400"; bcd(stelle*4+3 downto stelle*4) <= x"2"; |
44 | elsif (x>=x"03b9aca00") then x:=x-x"03b9aca00"; bcd(stelle*4+3 downto stelle*4) <= x"1"; |
45 | else bcd(stelle*4+3 downto stelle*4) <= x"0"; |
46 | end if; |
47 | wert <= resize(x*10, 36); |
48 | |
49 | if stelle=0 then |
50 | busy <= '0'; |
51 | state <= idle; |
52 | else
|
53 | busy <= '1'; |
54 | stelle <= stelle-1; |
55 | end if; |
56 | |
57 | end case; |
58 | end process; |
59 | |
60 | end Behavioral; |
Aber jetzt brauchen wir schon 182 Slices und haben nur noch 60MHz...
Lothar Miller schrieb: > Man kann unsigned nehmen, das geht auch weit über die integer Grenze Das ist gut, das baue ich so um! Prima! Lothar Miller schrieb: > Aber jetzt brauchen wir schon 182 Slices und haben nur noch 60MHz... Da lässt sich sicher noch ein wenig machen. Man schauen, was geht ...
Spartanist schrieb: > Da lässt sich sicher noch ein wenig machen. Man schauen, was geht ... Mit einer expliziten Reduzierung auf die nötigen 34 Bits (0...9999999999) sind es noch 164 oder gar 157 Slices:
1 | signal wert : unsigned (33 downto 0); |
2 | :
|
3 | :
|
4 | variable x : unsigned (33 downto 0); |
5 | :
|
6 | -- damit braucht das Design 164 Slices und schafft noch 60MHz:
|
7 | if (x>="10"&x"18711a00") then x:=x-"10"&x"18711a00"; bcd(stelle*4+3 downto stelle*4) <= x"9"; |
8 | elsif (x>="01"&x"dcd65000") then x:=x-"01"&x"dcd65000"; bcd(stelle*4+3 downto stelle*4) <= x"8"; |
9 | :
|
10 | :
|
11 | |
12 | -- so brauchts 157 Slices bei nur 50MHz:
|
13 | if (x>=resize(x"218711a00",34)) then x:=x-resize(x"218711a00",34); bcd(stelle*4+3 downto stelle*4) <= x"9"; |
14 | elsif (x>=resize(x"1dcd65000",34)) then x:=x-resize(x"1dcd65000",34); bcd(stelle*4+3 downto stelle*4) <= x"8"; |
15 | :
|
16 | :
|
Wobei mich der Unterschied schon ein wenig verwundert... :-o
Weniger slices kann auch darin begründet liegen, dass er in manchen Pfaden keine FFs meht braucht, was dann die speed limitiert. Wenn man mit "timing driven placement" und "register duplicating" arbeitet, sollte das nicht passieren. Ich brauche jetzt 75MHz. Doppelte Architektur will ich in keinem Fall, lieber ein paar slices mehr.
Spartanist schrieb: > Ich synthetisiere gerade mein design für S3E: > Hat 210 slices mit 30 MHz netto ohne irgendwas. > Wenn ich es in ein design packe, 3 FF stage dahinter packe > und retiming verwende, gelange ich zu den gewünschten 60MHz Spartanist schrieb: > Ich brauche jetzt 75MHz. Das ist ja fast schon inflationär...
Spartanist schrieb: > Lothar Miller schrieb: > >> Aber jetzt brauchen wir schon 182 Slices und haben nur noch 60MHz... > > Da lässt sich sicher noch ein wenig machen. Man schauen, was geht ... Versuche mal maximale Syntheseeinstellungen: "timing driven" + manuell eingestellt: "Register Duplication" - das ist nämlich nicht mit voreingestellt, wie ich zumindest bei der aktuellen ISE sehen muss. Auch "retiming" (physical resynthesis) und "restructure multiplexers" (sehr wichtig hier um klein & schnell zu werden). Dann kannst du sehen, ob das überhaupt geht und dann ein wenig rückbauen. Rumprobieren ist da durchaus nicht falsch, bei der verkrüppelten XST, die taugt nämlich nicht so arg viel. Wenn, dann verwende Ich gerne den SMART Explorer. Der hat mir heute wieder mal ein Überraschungsergebnis geliefert. Da in den thread nun schon recht viel rein gesteckt würde, schlage ich vor, wir machen einen Artikel daraus und jeder postet seine Version rein. Dann kann man mal vergleichen, bei welchen Bedingungen, welche die beste ist.
J. S. schrieb: > schlage ich vor, wir machen einen Artikel daraus Lohnt sich nicht. Das Dezimalsystem wird ja eh bald abgeschafft.
Josef G. schrieb: > Lohnt sich nicht. > > Das Dezimalsystem wird ja eh bald abgeschafft. Hat wer festgelegt?
Spartanist schrieb: > Hat wer festgelegt? Vielleicht hätte ich explizit dazuschreiben sollen: Kleiner Scherz.
Zwischenfrage: Wozu benötigt man eine deart schnelle Konversion zum BCD Formamt, dass man mit MHz da ran gehen muss? Was baut ihr da für Monsterapplikationen?
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.