Hallo, ich möchte mit dem XILINX Cordic-Core einen Arcustangens berechen. Meine Eingangswerte sind signed 32 bit Vektoren. Laut Datenblatt sollen die Eingabewerte im Zweierkomplement dargestellt werden (2 Bit Integer+Vorzeichen, Restliche Bit für die Mantisse). Nun stellt sich mir die Frage wie ich meine 32-bit Umformen muss um den Core nutzen zu können. Datenblatt: https://www.xilinx.com/support/documentation/ip_documentation/cordic_ds249.pdf Grüße, Erik
Erik K. schrieb: > Meine Eingangswerte sind signed 32 bit Vektoren. Und wie sind die skaliert? Was ist 0x00000000 und was 0x7fffffff und was 0x80000000?
Im Idealfall skalierst du deinen gültigen Zahlenbereich auf -1 .. 1 um den Quantisierungsfehler zu minimieren, praktischer ist aber wohl die nächsthöhere Zweierpotenz. Die vollen 32 bit Eingangsgenauigkeit bekommst du leider nicht, da die Werte von +1.0 .. +1.9xx nicht zulässig sind.
Das Thema hatte Ich auch mal. Bei dem Xilinx ATAN gibt es irgendein Problem. Beitrag "Xilinx CORDIC Core - FixPoint manuell umwandeln"
Hallo, Lothar M. schrieb: > Und wie sind die skaliert? > Was ist 0x00000000 und was 0x7fffffff und was 0x80000000? 0x00000000 wird als 0 interpretiert 0x7fffffff als 2147483647 und 0x80000000 als -2147483647 Numerisch Konsistent schrieb: > Im Idealfall skalierst du deinen gültigen Zahlenbereich auf -1 .. 1 um > den Quantisierungsfehler zu minimieren, praktischer ist aber wohl die > nächsthöhere Zweierpotenz. Das heißt ich müsste meinen Zahlenbereich durch 2^30 dividieren? Also müsste ich irgendwie einen fixe point Typ in vhdl definieren. (Ich bin absoluter neuling in fixed point arithmethik und hab davon noch keine Ahnung) Klaus L. schrieb: > Das Thema hatte Ich auch mal. Bei dem Xilinx ATAN gibt es irgendein > Problem. > > Beitrag "Xilinx CORDIC Core - FixPoint manuell umwandeln" Den Thread habe ich auch schon gelesen, aber auch nicht daraus schlau geworden. Ehrlich gesagt bin ich am Überlegen, ob ich das ganze einfach als Lookup Table implementiere. Allerdings ist das bei 32 bit eine riesie Tabelle.
Erik K. schrieb: > Ehrlich gesagt bin ich am Überlegen, ob ich das ganze einfach als Lookup > Table implementiere. > Allerdings ist das bei 32 bit eine riesie Tabelle. das wäre in der Tat eine spaßige Lookup-Tabelle. Erik K. schrieb: > 0x00000000 wird als 0 interpretiert > 0x7fffffff als 2147483647 > und 0x80000000 als -2147483647 Beim Zweierkomplement ist 0x8000... wohl -214748368 (letzte Stelle 8, nicht 7). Der Zahlenbereich für signed ist also ein ganz klein wenig asymmetrisch, was vielleicht auch mit ein Grund für deine Schwierigkeiten ist. Binär betrachtet nutzt du bisher den Zahlenbereich positivste Zahl: 01111... negativste Zahl: 10000... Wenn du den Wert vorzeichenrichtig eine Stelle nach rechts schiebst erhältst du positivste Zahl: 00111... negativste Zahl: 11000... Der benötigte Zahlenbereich ist positivste Zahl: 01000... negativste Zahl: 11000... Das ist fast der selbe Bereich, den du auch nach der simplen vorzeichenrichtigen Schieberei um 1 Bit erhältst. Nur der positive Wert unterscheidet sich um eine niederwertigste Stelle. Dezimal hast du nach der Schieberei also 0.999... statt der gewünschten 1.000.. Weniger Abweichung geht wohl nicht, weil du einen assymetrischen Zahlenbereich (-214748368..214748367) auf einen symmetrischen (-1..1) abbilden willst.
Erik K. schrieb: > Das heißt ich müsste meinen Zahlenbereich durch 2^30 dividieren? > Also müsste ich irgendwie einen fixe point Typ in vhdl definieren. (Ich > bin absoluter neuling in fixed point arithmethik und hab davon noch > keine Ahnung) Nein, du musst nur Umdenken. Diese Dicvision muss in deinem Kopf stattfinden, das FPGA interpretiert das fast gleiche Bitmuster einfach anders. Achim S. schrieb: > Erik K. schrieb: >> 0x00000000 wird als 0 interpretiert >> 0x7fffffff als 2147483647 >> und 0x80000000 als -2147483647 Das ist vermutlich falsch. Du meinst sicher -2147483648. Rechne mal nach. Als Tipp: probiers mit weniger Bits wie z.B. 8, das gibt dann einen Wertebereich von -128..127 Erik K. schrieb: > Ehrlich gesagt bin ich am Überlegen, ob ich das ganze einfach als Lookup > Table implementiere. Allerdings ist das bei 32 bit eine riesie Tabelle. Die bekommst du sowieso in keines der derzeit erhältlichen FPGAs, denn du bräuchtest dafür 32*2^32 Bits, also 137438953472 Bits oder eben 128 Giga Bits... Wir genau brauchst du das? Denn evtl. ginge es ja über eine kleine Tabelle mit linearer Interpolation. EDIT: Pech, Zweiter, zu lange gebraucht... ;-)
:
Bearbeitet durch Moderator
Danke für eure Hilfe. Ich habe es jetzt schon anders implementiert, so dass ich die Lösung mit dem XILINX CORE nicht mehr testen werde. Für diejenigen die es interessiert: Ich habe den Funktionswert des Arctan mit 1000 multipliziert (in dem Fall möglich, weil mein tatsächlicher Datenbereich die 32 bit nicht ganz ausschöpft) und habe dann einen Bereichsvergleich gemacht. Auflösung des ganzen ist dann 2,5 Grad. Sieht dann so aus:
1 | function atan_e (a : SIGNED) return SIGNED is |
2 | begin
|
3 | |
4 | if(a(31) = '1') then |
5 | if(a > to_signed(0,32) and a <= to_signed(44,32)) then return to_signed(-1800,32); |
6 | |
7 | elsif(a > to_signed(44,32) and a <= to_signed(87,32)) then return to_signed(-1775,32); |
8 | |
9 | elsif(a > to_signed(87,32) and a <= to_signed(176,32)) then return to_signed(-1725,32); |
10 | |
11 | elsif(a > to_signed(176,32) and a <= to_signed(268,32)) then return to_signed(-1675,32); |
12 | |
13 | elsif(a > to_signed(268,32) and a <= to_signed(364,32)) then return to_signed(-1625,32); |
14 | |
15 | elsif(a > to_signed(364,32) and a <= to_signed(466,32)) then return to_signed(-1575,32); |
16 | |
17 | elsif(a > to_signed(466,32) and a <= to_signed(577,32)) then return to_signed(-1525,32); |
18 | |
19 | elsif(a > to_signed(577,32) and a <= to_signed(700,32)) then return to_signed(-1475,32); |
20 | |
21 | elsif(a > to_signed(700,32) and a <= to_signed(839,32)) then return to_signed(-1425,32); |
22 | |
23 | elsif(a > to_signed(839,32) and a < to_signed(1000,32)) then return to_signed(-1375,32); |
24 | |
25 | elsif(a = to_signed(1000,32)) then return to_signed(-1350,32); |
26 | |
27 | |
28 | ......
|
Die Auflösung des arctan wäre nicht so wichtig gewesen, mir ging es nur um das Eingangsdatenformat. Auf jeden Fall nochmals vielen Dank für eure Hilfe. Grüße, Erik
Erik K. schrieb: > Die Auflösung des arctan wäre nicht so wichtig gewesen, mir ging es nur > um das Eingangsdatenformat. Wow. Und diese aufwändige und schlecht auflösende Lösung ist dir lieber, als eine einfache Zuweisung: Würdest du den vollen Zahlenbereich nutzen, dann wäre es: x(31) <= a(31); x(30 downto 0) <= a(31 downto 1); Wenn du nur einen Teil des Zahlenbereichst nutzt, dann müsstest du nur den Indexbereich von a anpassen. Evtl. braucht es noch ein Typcast, um aus dem signed einen std_logic_vector zu machen (so ungefähr in der Art std_logic_vector(a(31 donwnto 1)) Aber das wäre auch schon alles.
Erik K. schrieb: > Sieht dann so aus: Wenn schon, dann hätte ich "a" in einen Integer gewandelt, dann fallen wenigstens die vielen Vergleiche kompakt und leserlich aus. Und dazu noch den kleinen Programmiertrick,dass alles, was schon abgefragt wurde nicht mehr abgefragt werden muss. Um mal deinen Code anzupassen:
1 | if(a(31) = '1') then |
2 | if(a > to_signed(0,32) and a <= to_signed(44,32)) then return to_signed(-1800,32); |
3 | |
4 | elsif(a <= to_signed( 87,32)) then return to_signed(-1775,32); -- größer all 44 ist er eh' schon, sonst wäre er nicht hierher gekommen... |
5 | elsif(a <= to_signed(176,32)) then return to_signed(-1725,32); |
6 | elsif(a <= to_signed(268,32)) then return to_signed(-1675,32); |
7 | :
|
8 | :
|
9 | elsif(a = to_signed(1000,32)) then return to_signed(-1350,32); -- für diesen einmaligen kleinen Sonderfall (Wahrschielichkeit 0,1%) eine extra Condition? |
10 | .....
|
Und was passiert eigentlich, wenn a = 0 ist? Wenn so eine krude Auflösung reicht, dann hätte ich da doch die Tabellenlösung mit der linearen Interpolation genommen...
:
Bearbeitet durch Moderator
Erik K. schrieb: > Das heißt ich müsste meinen Zahlenbereich durch 2^30 dividieren? Nein, Du musst Den Zahlenbereich des Winkels entsprechend skalieren und interpretieren. Der Xilinx-Core muss natürlich entsprechend parametriert werden, d.h. bei ATAN muss man sich entscheiden, welchen Winkel man verwendet. Es gibt z.B. die Option den Core das flippen der 4 Quadranten machen zu lassen oder es selber zu tun. Richtig ausrechnen, kann der ja nur -90 Grad bis 90 Grad jeweils abzüglich eines infinitisimalen epsilon. Die Sonderfälle Y=unendlich und x=0 kann man auch gerne selber abfangen.
Ich habe den Core gerade mit MATLAB-Simulink in Verwendung. Dort kann man die Skalierung einstellen. Geht von -0.9999 ... +0.9999. Ich habe den zum Ausprobieren auf binär gestellt und bekomme auch seltsame Werte. Sind im Negativen nur halb so groß, wie im Positiven.
Thomas U. schrieb: > Ich habe den Core gerade mit MATLAB-Simulink in Verwendung. Dort kann > man die Skalierung einstellen. Geht von -0.9999 ... +0.9999. Ich habe > den zum Ausprobieren auf binär gestellt und bekomme auch seltsame Werte. > Sind im Negativen nur halb so groß, wie im Positiven. Beispiel? Der CORDIC vom X sollte sich nicht anders verhalten, als gewöhnlich. Ansonsten wird ATAN hier gerade intensivst erörtert: www.mikrocontroller.net/topic/480840 Hier hat jemand eine Lösung gepostet, auf 51 Bits genau: Die wäre mal gegen das Xilinx-Format gegenzutesten. Beitrag "Atan function implementation"
Erik K. schrieb: > Ich habe den Funktionswert des Arctan mit 1000 multipliziert (in dem > Fall möglich, weil mein tatsächlicher Datenbereich die 32 bit nicht ganz > ausschöpft) Dann hatte dein Funktionswert schlicht und einfach zu viele Bits genutzt. Ein signed ist 32 bit breit, wenn kein Wertbereich angegeben wird. Signale etc. werden IMMER mit Werbereich deklariert (Alle coding guidelines die ich kenne wollen das auch so). Das spart 1. Ressourcen, 2. es zeigt, dass sich der Entwickler Gedanken darüber gemacht hat, wie viel es denn wirklich braucht. Erik K. schrieb: > a > to_signed(0,32) Damit es auch wiederverwendbar ist mit anderen Wertbereichen:
1 | a > to_signed(0,a'length) |
Thomas U. schrieb: > Ich habe > den zum Ausprobieren auf binär gestellt und bekomme auch seltsame Werte. Das könnte wie schon gesagt an dem Umklappen in einen andere Quadraten liegen. Christoph Z. schrieb: > Erik K. schrieb: >> Ich habe den Funktionswert des Arctan mit 1000 multipliziert (in dem >> Fall möglich, weil mein tatsächlicher Datenbereich die 32 bit nicht ganz >> ausschöpft) > > Dann hatte dein Funktionswert schlicht und einfach zu viele Bits > genutzt. Das sollte sich leicht testen / limitieren lassen. Anbei ein Bild einer Echtzeitberechnung mehrerer ATANs über Xilinx-CORDIC, um von der Position von X und Y auf den Winkel zu schließen und die Ersatzbilder für Iris und Pupille zu bilden. Lief äuf auf einem Spartan 6 (Trenz Carrier Board mit VGA Ausgabe) - geht inzwischen auch auf HDMI.
Das hier war damals übrigens der Ansatz und die Grundlage für den Augenhintergrund: Beitrag "Re: Rechenfehler grafisch angezeigt" Und hier das Video dazu: https://youtu.be/F8HvA-YQ8is
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.