Wurzel ziehen - VHDL

Gast #1492974
Lesenswert?

Mir fällt dazu nur wieder der Quake 3 Source Code ein:
1
float InvSqrt (float x) {
2
    float xhalf = 0.5f*x;
3
    int i = *(int*)&x;
4
    i = 0x5f3759df - (i>>1);
5
    x = *(float*)&i;
6
    x = x*(1.5f - xhalf*x*x);
7
    return x;
8
}
Gast #1492989
Lesenswert?

Altera und Xilinx bieten beide ziemlich gute Funktionen dafür an die 
Platzsparend und schnell synthetisier werden.

Bei Xilinx etwa als vereinfachter Cordic-Core.

Einfach mal in den Megawizard oder coregenerator reinschauen.
Da du ohnehin scheinbar nicht interessiert bist die Funktion an sich 
selbst zu beschrieben wäre das immer die erste Anlaufstelle.


Allerdings muss man sich fragen ob du tatsächlich diese Funktion 
berechnen willst und insbesondere wieviel Zeit du dafür hast.

Wenn das eventuell sogar in einem Takt passieren soll...
Gast #1493080
Lesenswert?

schau dir mal das dsp-ch3.pdf auf der Xilinx homepage an. auf seite 59 
beschreiben sie eine möglichkeit wie du das mit dem DSP48 slice lösen 
könntest. welche hardware möchtest du den verwenden?
Gast #1493546
Lesenswert?

Vl. reicht auch schon der Wurzelalgorithmus von Heron, Dieser löst das 
Problem durch einfache Addition und Division.

x= 0,5 * (x+a/x)

Wobei x die Näherungslösung ist und a die Zahl aus der die Wurzel 
errechnet werden sol. Das ganze lässt man dann in einer Schleife solange 
ablaufen bis (x*x-a) <= ERROR_MAX ist.

Sollte nun auch in Logik eifnach zu realisieren sein.

Aber die allerschnellste wäre es wahrscheinlich eine 
Interpolationsfunktion zu erstellen und anhand dieser die Werte zu 
errechnen.
Gast #1493847
Lesenswert?

Ich würde mal sagen, dass die Funktionen sowieso in LUTs realisiert 
sind. Beim "schriftlichen Wurzelziehen" wird nur nicht soviel Platz 
verschwendet.

Wenn man eine Wurzel auf 8 Bit genau ziehen will, braucht man einen 16 
Bit-Wert. Das ist ein komplettes 64k-RAM. Mehr Verschwendung geht 
eigentlich kaum.
Gast #1495311
Lesenswert?

Hallo,

ich hatte mal diesen Code-Schnippsel nach VHDL portiert und es hat sehr 
gut funktioniert:
1
public static int sqrt(int num) {
2
        int op = num;
3
        int res = 0;
4
        int one = 1 << 14; // The second-to-top bit is set: 1L<<30 for long
5
 
6
        // "one" starts at the highest power of four <= the argument.
7
        while (one > op)
8
            one >>= 2;
9
       
10
        while (one != 0) {
11
            if (op >= res + one) {
12
                op -= res + one;
13
                res += 2 * one;
14
            }
15
            res >>= 1;
16
            one >>= 2;
17
        }
18
        return res;
19
    }

Wie du siehst, braucht man keine Multiplikation für die 
Wurzelberechnung.

Grüße,
Gast
Gast #1496058
Lesenswert?

@Stefan:

Ja, bei mir war es gut genug. Handelte sich um eine RMS-Berechnung über 
einige Audiosamples (so glaub 256 oder so). Mit dem RMS-Wert sollte dann 
ein Verstärkungsfaktor berechnet werden. Quasi eine Art 
Dynamikkompressor.

Aber noch nciht fertig ...

Grüße,
Gast
Gast #1500195
Lesenswert?

Gibt es das in kyrillisch verfasste Paper auch in westeuropäisch?

Vielleicht als link im Bronstein?

.......................

Weisst Du noch Vladimir, früher auf der Universität?
Als wir Mathe hatten, hast Du uns immer Aufgaben gemacht
mit viele Formeln und Zeichen ...
war grauenhaft ...
Gast #1500268
Lesenswert?

Frager schrieb:
> Gibt es das in kyrillisch verfasste Paper auch in westeuropäisch?
>
> Vielleicht als link im Bronstein?
>
> .......................
>
> Weisst Du noch Vladimir, früher auf der Universität?
> Als wir Mathe hatten, hast Du uns immer Aufgaben gemacht
> mit viele Formeln und Zeichen ...
> war grauenhaft ...

<3 switch
Gast #1500429
Lesenswert?

> Wofür braucht man bei einem Dynamikkompressor noch den RMS?

Weil es ohne RMS kein RMS-Dynamik-Kompressor ist ...

Hmm ... die letzten Postings werte ich so, dass es wohl mit Cordic auch 
gehen würde, auch wenn ich kein kyrillisch verstehe.

Mit Cordic kenn ich mich leider garnicht aus, obwohl ich viel darüber 
gelesen habe ...

Grüße,
Gast
(Firma: www.dossmatik.de) #1500437
Lesenswert?

Die Formel-Sprache der Mathematiker ist international.
Leider fehlen ein paar Diagramme oder ein Strukturgramm für den 
Algorithmus, um einen Einstieg zu haben. Das ist das eigentliche Problem 
Vladimir's.

Es handelt sich bei allen Problemen um Kegelschnitte. Auf diesen 
Schnittebenen gibt es mit jedem Schritt eine Bewegung, die sich dem 
Ergebnis nähert. Die Schrittweite wird mit jedem Schritt auch kleiner. 
Diese Schritte muss man sich mal in ein Diagramm eintragen, dann 
versteht man es.



Ander blöde Frage was ist RMS?
RMS ist bei mir root mean square, der Quadratische Mittelwert
Gast #1500627
Lesenswert?

Das mit den Kegelschnitten ist gut erklärt, finde ich. Aber die Theorie 
dahint kann man auch im Wiki nachlesen.

True RMS braucht man bei der Leistungsbetrachtung über einen gewissen 
Freqenzbereich. Man muss mindestens über die Periode der geringsten 
Frequenz integrieren.
(Firma: www.dossmatik.de) #1500987
Lesenswert?

Ich habe mich mit Cordic nochmal beschäftigt.
Es lässt sich die Wurzel nur indirekt berechnen.
Mit der hyperbolische Variante lässt sich folgende Funktion annähern.

Nimmt man für
 und

So berechnet man:

So die Theorie. Es könnte sein, dass es noch eine einfachere Cordic 
Variante gibt. Das ist meine eigene Herleitung.
(Firma: www.dossmatik.de) #1501154
Lesenswert?

>>Jürgen

ich habe leider in deinem Link nicht gefunden, wie man eine Wurzel 
berechnet.

>> Melanie

>>die formel ist:

>>1/sqrt(1+2^(-2*i))

Wenn mich nicht alles täucht, ist das der der reziproke Cordic gain? Bei 
Cordic ist das eine Konstante! Also wenn du Cordic vor hast, dann ist 
dieser Wert nicht ständig zu berechnen.
Gast #2307931
Lesenswert?

Crest schrieb:
> Mir fällt dazu nur wieder der Quake 3 Source Code ein:
>
1
> float InvSqrt (float x) {
2
>     float xhalf = 0.5f*x;
3
>     int i = *(int*)&x;
4
>     i = 0x5f3759df - (i>>1);
5
>     x = *(float*)&i;
6
>     x = x*(1.5f - xhalf*x*x);
7
>     return x;
8
> }
9
>

Kann mir das bitte mal jemand entschlüsseln?

"df" , "f"?

Ist das rekursiv?

>Quake 3
?
Moderator (Firma: Titel) Persönliche Seite #2308454
Lesenswert?

ralf schrieb:
>> Mir fällt dazu nur wieder der Quake 3 Source Code ein:
1
 float InvSqrt (float x) {
2
     float xhalf = 0.5f*x;
3
     int i = *(int*)&x;
4
     i = 0x5f3759df - (i>>1);  // hier muß man sich mal den Aufbau einer IEEE float-Zahl genauer anschauen
5
     x = *(float*)&i;
6
     x = x*(1.5f - xhalf*x*x);
7
     return x;
8
 }
> Kann mir das bitte mal jemand entschlüsseln?
Spiel doch mal selber Prozessor und sieh dir dazu vorab den Aufbau von 
IEEE 754 float-Zahlen mal sehr genau an. Da wird nämlich auf Bit-Ebene 
in einer solchen Zahl herumgemantscht...
Als Tipp:
es kommt (mit hinreichender Genauigkeit) der Kehrwert der Wurzel raus
InvSqrt(36.000000) = 0.166477 --> 6.006850
InvSqrt(49.000000) = 0.142762 --> 7.004646
InvSqrt(64.000000) = 0.124788 --> 8.013566
InvSqrt(81.000000) = 0.111086 --> 9.002046

> Ist das rekursiv?
Nein, weil InvSqrt() nicht innerhalb von InvSqrt() aufgerufen wird.
Gast #2310270
Lesenswert?

>Weil es ohne RMS kein RMS-Dynamik-Kompressor ist ...
Bei Dynamikkompressoren muss man immer ein wenig aufpassen, was man über 
welche Zeiträume komprimiert. Bei kurz eingestellten Integrationszeiten 
und Bezug auf die Anplitudenwerte kommt es zu starken 
Signaldeformationen.
Persönliche Seite #2317242
Lesenswert?

Das ist das Newton'schen Näherungsverfahren, bei der einfach die erste 
Division des 1/k-Wertes weggelassen wurde, wodurch man folglich 1/sqrt() 
erhält. Keine Hexerei. Der wirklich kluge Kunstgriff dieses Ansatzes 
besteht im trickreichen Ermitteln des Startwertes, damit die Folge schon 
nach der ersten Korrektur gut konvergiert.

Im Grunde wäre es auch für FPGAs gut nutzbar, allerdings liegen im FPGA 
die Werte so selten im float vor :-)

Um zu einem guten Startwert zu gelangen, muss man anders vorgehen. Ich 
habe da selber schon einiges probiert, allerdings kosten die meisten 
Überlegungen zuviel Zeit, um noch effizient zu sein. Ein VHDL-Wurzel 
Core auf binärer Basis braucht mitunter deutlich weniger Takte, als die 
Eingangsbitbreite.
Persönliche Seite #5631559
Lesenswert?

Morten schrieb:
> Ist bekannt, worum hier das "INT I=1" sein soll? Das wird weder
> fortgeschrieben, noch verwendet. Ist das überhaupt von Nöten?

Offenbar nicht. Könnte sein, dass es ein Überbleibsel des original Algos 
von Dijkstra ist, wobei ich nicht genau weiß, wie der aussieht. Ich sehe 
auch nicht, was daran jetzt so Schlaues sein soll, bzw. worin wiederum 
die Modifikation der Autoren besteht.

Die vorgestellte Methodik ist ein iteratives Näherungsverfahren, welches 
weitgehend dem schriftlichen Wurzelziehen aus der Schule entspricht, das 
seinerseits wiederum auf selbiges von Heron zurückgeht, wie ich weiter 
oben schon angemerkt hatte.


Morten schrieb:
> Welche Möglichkeit gibt es für die Lösung des Problems?
Welches Problem besteht? Der Algo als solcher funktioniert ja.
Ich denke, "I" ist ein Zähler, der die Anzahl der Iterationen und damit 
Rechentiefe mitprotokolliert. Diese ist allerdings durch die Wahl der 
Breite des Eingangsvektors bereits implizit determiniert. Redundante 
Info.
Gast #5666440
Lesenswert?

Jürgen S. schrieb:
> Morten schrieb:
>> Ist bekannt, worum hier das "INT I=1" sein soll? Das wird weder
>> fortgeschrieben, noch verwendet. Ist das überhaupt von Nöten?
> Offenbar nicht
Irgendeine Bedeutung muss es haben denke ich.
Immerhin ist es ja ein wissenschaftlicher Artikel auf IEEE.
Vielleicht fehlt etwas vom Code?

> Die vorgestellte Methodik ist ein iteratives Näherungsverfahren, welches
> weitgehend dem schriftlichen Wurzelziehen aus der Schule entspricht, das
> seinerseits wiederum auf selbiges von Heron zurückgeht
Mir ging es hauptsächlich um den Weg wie es gemacht wurde um besonders 
schnell zu sein mit der Wurzelbildung. Es muss einen Vorteil bei der 
Methode geben bei FPGA.
Persönliche Seite #5864178
Lesenswert?

Entwickler schrieb:
> Wenn es den gäbe, müsste man nicht einen Core dafür entwickeln:

Ob man pauschal von der Existenz eines Cores in der Bib eines 
Herstellers darauf schließen kann, dass dieser das nun plus ultra ist 
und es nicht Besseres gibt, sei mal dahin gestellt. Ich verweise an 
dieser Stelle auf die anderweitig gepostete Gegenüberstellung meiner DDS 
und der von Xilinx :-)


Nochmals zu dem Dokument hier:

Mir ist beim nochmaligen Überfliegen nicht so ganz klar, worin jetzt 
genau die Errungenschaft besteht. Irgendwie liest es sich, als hatten 
die Autoren nur Probleme, die in C formulierte "Rotation" des 
Zwischenvektors in VHDL abzubilden, weil es keinen Befehl dafür gab und 
das irgendwie klug gelöst.

Ich nehme an, dass das (nicht publizierte) VHDL den links in der Box 
dargestellten Algorithmus tatsächlich sequenziell abbildet und dort 
wirklich Zwischenwerte rotiert werden.

Dass man aber in VHDL eine Rotation durch ein Verschieben bzw Umgreifen 
realisiert, muss hier eigentlich nicht erwähnt werden und sicher auch 
nicht, dass man nicht nur auf das Hineinpassen des Probevektors mit 
Faktor 2 auf Ja und Nein testen kann, um zu entscheiden, ob man eine 1 
oder 0 in den Ergebnisvektor setzt.

Ich habe das z.B. in "meiner" VHDL-Wurzel mit 4 Fragezweigen realisiert 
und kann folglich in einem Takt 2 Ergebnisbits bilden. Damit kriegt man 
aus den 32 Eingangsbits die 16 Ausgangsbits in 8 Takten raus.

Daraus mache ich jetzt aber kein paper :-)

... sondern verweise auf den einfachen Algo hier:
Beitrag "Re: Wurzel ziehen - VHDL"

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren