Forum: FPGA, VHDL & Co. FloatingPoint Division von Ganzzahlen


von Stephan K. (Firma: FAU Erlangen) (sofa1780)


Lesenswert?

Guten Morgen liebes Forum,

da ich eine Division auf einem FPGA durchführen möchte und den 
Quotienten anschließend stark verstärken muss komme ich an die Grenzen 
der Quantisierung.

Als Eingänge für die Division sind mir derzeit 2 Binärvektoren (A und B) 
mit dem Format signed(14 downto 0) gegeben.

Meine Idee war es nun, die von Altera Quartus bereitgestellte IP-Core 
zur FloatingPoint Division zu nutzen. Anschließend kann ich das Ergebnis 
der Division (C) wieder normalisieren und entsprechend verstärken ohne 
auf die Genauigkeit der Division verzichten zu müssen.. bzw. erhoffe ich 
mir so ein wesentlich besseres Ergebnis, da FP..

Ist der Gedankengang soweit korrekt und nachvollziehbar?

Nun stellt sich mir folgende Frage:
Wie bekomme ich meie derzeitigen Vektoren A und B in eine normalisierte 
FP-Darstellung mit 32 Bit (Single-precision)?
Und wie gehe ich mit dem Ergebnis C richtig um? Dieses soll ja 
schließlich wieder auf die vollen 15 Bit skalliert werden.

Sehe ich das richtig, dass ich den Exponenten der FP-Darstellung 
entsprechend anpasse (auf e=-14 -> "01110001") und anschließend meine 
die Mantisse m (in der Länge angepasst) durch meine Vektoren A und B 
ersetze?
Bei einem vollskallierten signed(14 downto 0) also m -> 
"0...0111111111111111"?

Wie skalliere ich dann den Ausgangsvektor C?


Besten Gruß und einen guten Start ins Wochenende!

von Dr. Sommer (Gast)


Lesenswert?

Warum verstärkst du nicht erst, und dividierst dann? So brauchst du zwar 
viele Bits, aber kein Floating Point.

von Stephan K. (Firma: FAU Erlangen) (sofa1780)


Lesenswert?

Gute Frage!

Geht nat. auch. bis 64 Bit kann der Quartus LPM_Divider und sp viele 
werd ich sicher nicht brauchen.

Danke für den Tipp!!

Mein Problem wäre so dann doch recht elegant gelöst und sogar noch mit 
weniger Ressorucen, da kleinere Wortbreiten.

Wirklich vielen Dank!

In der Annahme ich verstärke um 1024
ergäbe mein ausgangsvektor für den Quotienten 26 Bit. Meine Information 
steckt nun wieder in den MSB's, korrekt?

von Walter T. (nicolas)


Lesenswert?

Ich schiebe (nicht FPGA, bin nur durch Zufall hier gelandet) vor einer 
Division immer weitestmöglich nach links, wenn ich maximale Genauigkeit 
brauche.

von Stephan K. (Firma: FAU Erlangen) (sofa1780)


Lesenswert?

Das würde die Verstärkung im Vorfeld auch machen, nur dynamisch (anhand 
des extern eingestellten Wertes) und mit mehr Hardware. Beschränkt eben 
durch die Größe des Binärvektors der Verstärkung.
Diesen Weg müssen wir gehen, da die Verstärkunung von äußeren 
Randbedningungen abhängt.
Wäre die Verstärkung bekannt ist das nach links schieben oder anhängen 
von Bits, rechtsseitig des Binärvektors, die sinvollere Lösung.

Da stimme ich zu.

von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Was heisst denn hier bitte "Verstärken"? Wir reden jetzt nicht von einem 
simplen Skalieren des Wertes, oder? Das sollte auf der Hand liegen.

Außerdem gibt der Core genau für diese Zwecke einen remainder ab, der 
wieder weiterprozessiert werden darf und das sogar beliebig.

Somit entfallen alle Bitgrenzen, welche die Division scheinbar aufwirft.

Vom Aufwand ist es letzlich egal, mit der konventionellen, unverstärkten 
Methode, hast Du nur schon vorab ein Zwischenergebnis, das sich 
weiterberarbeiten ließe.

Stephan K. schrieb:
> Meine Idee war es nun, die von Altera Quartus bereitgestellte IP-Core
> zur FloatingPoint Division zu nutzen. Anschließend kann ich das Ergebnis
> der Division (C) wieder normalisieren und entsprechend verstärken ohne
> auf die Genauigkeit der Division verzichten zu müssen.
Ich möchte Dir keinesfalls zu nahe treten, lieber Stephan, aber Ich 
frage mich schon ein wenig, was ihr Jungens heute so in der Schule 
lernt. Wir hatten noch das schriftliche Dividieren, das man ganz ohne 
Core oder Libraries direkt auswendig aus dem Kopf auf alles anwenden 
konnte, was der Lehrer an die Tafel gekritzelt hat. Sieh Dir mal die 
Seite vom Kollegen Brünner an:

http://www.arndt-bruenner.de/mathe/scripts/polynomdivision.htm

Wenn Du jetzt hergehst und die darin inbegriffene Rückmultiplikation 
weglässt, wie es bei Dualzahlen ja einfach möglich ist, dann hast Du 
direkt was noch Einfacheres, nämlich die Binärdivision. Das ist Mathe 
aus der Mittelstufe und erfordert kein Studium an einer Erlanger 
Hochschule, wobei Ich das Level in Erlangen nicht so kenne :-)

In Kenntnis dieser Zusammenhänge, sollte man direkt verstehen, daß man 
den Eingang einfach beliebig schieben- und/oder den Rest beliebig 
weiterverarbeiten kann und dass das keinen Unterschied macht sondern 
genau Dasselbe ist.

Auf die Idee, eine binäre Rechnung in FP zu verwandeln, um dann "besser" 
rechnen zu können, kommen nur die, die Softcores in FPGAs stecken, damit 
die dann besser rechnen.

Hier kommt mein Vorschlag:

Packt doch einfach einen kompletten Intel-7-Multi-Kern auf eine 
Multi-Chip-FPGA-Plattform wie sie fürs ASIC-Prototyping verwendet wird, 
dann installiert Windows drauf und ladet MATLAB obenauf. Dann rechnet 
das MATLAB alles durch, was es so gibt. Auch das kleine Einmaleins. 
Fertisch.

Die anderen, die keine Resourcen verschwenden möchten, empfehle Ich ein 
Grundlagenstudium hier: https://www.thm.de/site

Dort bekommt man praktiche Lösungen beigebracht. :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Stephan K. schrieb:
> In der Annahme ich verstärke um 1024
> ergäbe mein ausgangsvektor für den Quotienten 26 Bit. Meine Information
> steckt nun wieder in den MSB's, korrekt?
Logisch, weil deine "Verstärkung" ja nur eine Verbreiterung des Vektors 
um 10 LSB ist. Da wird dann auch in der realen Hardware gar nichts 
multipliziert, sondern einfach 10 Bits dazuverdrahtet...

> erhoffe ich mir so ein wesentlich besseres Ergebnis, da FP..
Nur geht die Rechnung "mehr Aufwand = besseres Ergebnis" hier nicht auf, 
weil Float trotz der 32 Bit Breite leider nur 6 signifikante Stellen 
hat. Es kann dir also passieren, dass du rechnest 1234567.8 + 1.0 und 
hinterher kommt wieder 1234567.8 heraus... :-o

: Bearbeitet durch Moderator
von Stephan K. (Firma: FAU Erlangen) (sofa1780)


Lesenswert?

Weltbester FPGA-Pongo schrieb im Beitrag #5196400:
> simplen Skalieren des Wertes, oder?

Nur werden Vektorbreiten fest synthetisiert, sodass im Nachgang selten 
um n belibige Stellen geshiftet werden kann..

> remainderder weiterprozessiert werden darf und das sogar beliebig.
Und genau das lernt man in der Schule nicht. Dort wird dann einfach 
hingenommen, dass es einen Rest gibt, wie groß der ist und das war es 
dann auch...

> Ich möchte Dir keinesfalls zu nahe treten, lieber Stephan, aber...
aber den Spruch kann man sich sparen?


Überragender Vorschlag übrigens.. ;)


Lothar M. schrieb:
> Da wird dann auch in der realen Hardware gar nichts
> multipliziert, sondern einfach 10 Bits dazuverdrahtet...
Ein Bit dazu bedeutet aber ja immer ich verdopple den Wert.
Was ist nun, wenn ich den Wert nicht verdoppeln mag sondern nur um 
1,5(dezimal) anheben möchte?

Verstärke halt momentan mit einem 7 Bit-Vektor und shifte gleichzeitig 
das Ergebnis um 3 Bits nach rechts, was wiederum einer Division mit 2^3 
gleich kommt. So kann ich das Ergebnis mit einer Stufung von 
0,125(dezimal) verstärken.. und zwar abhänig von aktuellen 
Randbedingungen. Diese ändern sich.

> Nur geht die Rechnung "mehr Aufwand = besseres Ergebnis" hier nicht auf,
> weil Float trotz der 32 Bit Breite leider nur 6 signifikante Stellen
> hat. Es kann dir also passieren, dass du rechnest 1234567.8 + 1.0 und
> hinterher kommt wieder 1234567.8 heraus... :-o

Ist mir mittlerweile auch schon klar geworden.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Stephan K. schrieb:
> Was ist nun, wenn ich den Wert nicht verdoppeln mag sondern nur um
> 1,5(dezimal) anheben möchte?
Dann würde ich das Ganze auf eine Addition des Ausgangswertes mit seiner 
Hälfte reduzieren und bräuchte wieder keine Multiplikation...

> Verstärke halt momentan mit einem 7 Bit-Vektor und shifte gleichzeitig
> das Ergebnis um 3 Bits nach rechts, was wiederum einer Division mit 2^3
> gleich kommt.
Dabei wird bei signed Werten aber in die falsche Richtung "gerundet".

von Stephan K. (Firma: FAU Erlangen) (sofa1780)


Lesenswert?

Lothar M. schrieb:
> Stephan K. schrieb:
>> Was ist nun, wenn ich den Wert nicht verdoppeln mag sondern nur um
>> 1,5(dezimal) anheben möchte?
> Dann würde ich das Ganze auf eine Addition des Ausgangswertes mit seiner
> Hälfte reduzieren und bräuchte wieder keine Multiplikation...
Schon, wenn ich vorher weiß, dass es immer die hälfte ist, wie in diesem 
Beispiel eben. Es war allerdings auch nur ein Beispiel, nichts weiter.
Wir haben es leider nicht mit fest vorhersagbaren "skalierungen" zu tun.
Wie startk skaliert werden muss ist abhängig von externen Modulen.. 
verschiedene Sensoren z.B.

>> Verstärke halt momentan mit einem 7 Bit-Vektor und shifte gleichzeitig
>> das Ergebnis um 3 Bits nach rechts, was wiederum einer Division mit 2^3
>> gleich kommt.
> Dabei wird bei signed Werten aber in die falsche Richtung "gerundet".

Hmm das kann ich nicht gleich nachvollziehen.
Kannst du mir vllt. einen Denkhinweis geben? Stelle mir den Vektor grad 
vor, ich gehe nur soweit mit der "Verstärkung", bis mein Ausgangsvektor 
voll skalliert ist. Die MSB's bleiben allso stets unbesetzt. Sollten sie 
doch einen Wert annehmen.. Dann wird das Ausgangssignal auf den 
maximalen wert, bzw. auf den minimalen Wert gesetzt.
Ich schneide also MSB ab, welches meinen Wert repräsentiert. Wie wird 
dann da falsch gerundet?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Stephan K. schrieb:
> Wie wird dann da falsch gerundet?
Zeichne mal ein paar Bitmuster von negativen Zahlen auf und schneide die 
MSB ab.
Rechne das selbe mit dem Taschenrechner... ?

von Stephan K. (Firma: FAU Erlangen) (sofa1780)


Lesenswert?

Si claro,
meinst sowas hier?


3d*3d = [011]b*[011]b = [001001]b = 9d
linksshift (/2)       =  [00100]b = 4d

Also doch lieber meine Ausgangsvektoren mit einem variablen Wert 
aufaddieren?!

Macht man das bei der Skallierung dann immer so? Ich gebe dem Wert ja 
damit einen Offset.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

Stephan K. schrieb:
> linksshift (/2)

???

Rechts ist da, wo der Daumen links ist.

von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Stephan K. schrieb:
> Nur werden Vektorbreiten fest synthetisiert, sodass im Nachgang selten
> um n belibige Stellen geshiftet werden kann.
Erstens geht das sehr wohl und zweitens ist das das hier unerheblich. 
Alles, was zur Laufzeit passiert, müsste mit FP auch getan werden und 
das Umskalieren ist in VHDL nun wirklich kein Problem.

>> remainder der weiterprozessiert werden darf und das sogar beliebig.
> Und genau das lernt man in der Schule nicht. Dort wird dann einfach
> hingenommen, dass es einen Rest gibt
Du solltest aber in der Lage sein, anhand der Vorgehensweise des 
schriftlichen Dividierens diese Schlussfolgerungen zu ziehen. Das ist 
doch anschaulich. Ich konnte sie ja auch ziehen und hatte nie etwas von 
FPGAs in der Schule gehabt. Es geht doch nur ums Gucken, Nehmen, 
Hinschreiben, Entscheiden obs reinpasst und dann so oder so 
weiterrechnen. Dann schiebt man die Guckebrille eins nach rechts und 
macht wieder dasselbe. Genau so schreibt man das beim FPGA hin. 
Auswählen, wie man weitermacht, ist halt ein Multiplexer. Man kann das 
Ganze Gedöhns sogar mit Generate-Anweisungen dynamisch hinschreiben, von 
der Auflösung und Tiefe abhängig machen. Macht aber keiner, sondern 
verdrahtet brute force aufs Maximum, lässt untern die Bits weg und die 
Synthese darf dann entscheiden, was sie davon einbauen möchte.

> Lothar M. schrieb:
>> Da wird dann auch in der realen Hardware gar nichts
>> multipliziert, sondern einfach 10 Bits dazuverdrahtet...
> Ein Bit dazu bedeutet aber ja immer ich verdopple den Wert.
> Was ist nun, wenn ich den Wert nicht verdoppeln mag sondern nur um
> 1,5(dezimal) anheben möchte?
Dann nimmts Du eben das Einfache + die Hälfte. Das sind 50% mehr. Auch 
das sollte man direkt ersehen. Du hast aber ein anderes Problem:

Dir ist nicht klar, was Du wann tun musst. Wenn Du etwas zur Laufzeit 
ändern willst, dann musst Du das Umrechnen ins FPGA einbauen. D.h. die 
Skalierung mit einer Multiplikation lösen. Also wird es einen 
Skalierfaktor geben, denn man in einem Register wo einstellt und der 
dann die Rechnung zurechtbiegt. Dies bitte so, das keine Divisionen 
durch X entstehen sondern nur solche durch n hoch 2.

Das kriegst Du hin.

Wenn nicht, dann kriegst Du es auch mit FP nicht hin.

> Verstärke halt momentan mit einem 7 Bit-Vektor und shifte gleichzeitig
> das Ergebnis um 3 Bits nach rechts
Vergiss mal die Begriffe "verstärken" etc, Du verhaspelst Dich. Ich 
denke, in Deinem Fall ist es wirklich besser, Du baust eine variable 
Division ein und verzichtest auf Bit-Operationen.

von Stephan K. (Firma: FAU Erlangen) (sofa1780)


Lesenswert?

Markus F. schrieb:
> Rechts ist da, wo der Daumen links ist.

.. oder innen.

Weltbester FPGA-Pongo schrieb im Beitrag #5196637:
> das Umskalieren ist in VHDL nun wirklich kein Problem.

Nattürlich nicht.^^

Weltbester FPGA-Pongo schrieb im Beitrag #5196637:
> Du solltest aber in der Lage sein, anhand der Vorgehensweise des
> schriftlichen Dividierens diese Schlussfolgerungen zu ziehen.

Bin ich, nur bin ich auf den Gedanken, mit dem Rest einfach weiter zu 
arbeiten nicht gekommen..

Weltbester FPGA-Pongo schrieb im Beitrag #5196637:
> Wenn Du etwas zur Laufzeit
> ändern willst, dann musst Du das Umrechnen ins FPGA einbauen. D.h. die
> Skalierung mit einer Multiplikation lösen. Also wird es einen
> Skalierfaktor geben, denn man in einem Register wo einstellt und der
> dann die Rechnung zurechtbiegt. Dies bitte so, das keine Divisionen
> durch X entstehen sondern nur solche durch n hoch 2.

Genau das mache ich doch z.Z. Ich skaliere mit einem 7 Bit Vektor und 
teile gleichzeitig durch 8... (um 3 Bits geshiftet) Das ergbit mir einen 
Skalierungsfaktor, den ich über register beliebig von außen einstellen 
kann.. und zwar mit der Genauigkeit von 1/8 in den Bereichen von 0,125 
bis 16.

von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Stephan K. schrieb:
> Genau das mache ich doch z.Z. Ich skaliere mit einem 7 Bit Vektor und
> teile gleichzeitig durch 8... (um 3 Bits geshiftet) Das ergbit mir einen
> Skalierungsfaktor, den ich über register beliebig von außen einstellen
> kann.. und zwar mit der Genauigkeit von 1/8 in den Bereichen von 0,125
> bis 16.

Dann verstehe Ich das Problem nicht. Willst du diese Funktion irgendwie 
wegsparen?

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.