Forum: FPGA, VHDL & Co. Genauer und schneller Sinus im FPGA


von Rolf (audiorolf)


Lesenswert?

Kennt jemand einen Algorithmus für einen Sinus, gfs als Näherung, der 
bei ähnlicher Genauigkeit schneller ist, als CORDIC?

Ich hätte da eine Ansteuerung für eine Leistungselektronik, die mehrere 
Sinusfunktionen erfordert, deren Werte sich sehr schnell ändern können. 
Der FPGA läuft aus Wärmegründen nur mit 40 MHz. Die Cordic-Funktion, die 
ich brauche, arbeitet bei der erforderlichen Genauigkeit mit 24 Takten 
und ist bei der Anzahl der Kanäle auch ziemlich ausgelastet. Es müssen 
aber 6 Phasen mit Sinus und Cosinus versorgt werden, sodas die 
Berechnungszeit in Richtung 72 Takten geht und die daraus entstehenden 
unter 500 kHz Latenz nicht reicht, um mehrere Kanäle zu steuern. Um die 
Zahl der parallelen Cordic core zu reduzieren, wäre eine schnellere 
Funktion hilfreich.

90°-RAM-Sinus ist nicht möglich, weil der BRAM für die hohe Genauigkeit 
fehlt und ein DDR zu langsam ist, für die vielen Kanäle.

Nett wäre z.B. ein Algorithmus, der pro Genauigkeitsstufe nur halb 
soviele Takte benötigt.

Wenn nicht muss ich FPGA-Takt und Gehäuse ändern.

von Rolf (audiorolf)


Lesenswert?

Ein Nachsatz noch: Ich meine mich erinnern zu können, dass es für 
Anwendungen aus früheren Zeiten, wo sie RAM sparen mussten, so einen 
Algo gegeben hat, der eine Kombi aus Auslesen und Iteration darstellte, 
also stückweise Interpolation wodurch erst die hohen und dann die 
niederen Bits berechnet wurden. Ich finde dazu aber nichts. Wenn ich 
einen Ansatz hätte, könnte ich den aufbauen und durchmessen, ob es mit 
der Genauigkeit und dem Tempo passt.

Das habe ich z.B. für den CORDIC gemacht und bin so auf die 24 Stufen / 
Bits gekommen, die ich braucht, damit es wenig genug klirrt, denn die 
Frequenz moduliert wird.

von Hendrik L. (hlipka)


Lesenswert?

Evt. hilft Dir 
https://community.element14.com/technologies/fpga-group/b/blog/posts/fpga-waves-8-fast-cordic-sine-and-cosine 
weiter? Es behauptet 'one sample per clock' (aber ich habe jetzt nicht 
weiter reingelesen wie gut das klappt).

von J. S. (engineer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hendrik L. schrieb:
> Evt. hilft Dir
Da wäre ich skeptisch :-)
Die Version ist eine ausgerollte Version, die ebenfalls mit einer Stufe 
je Winkelsegment arbeitet. Allerdings eine mit 6 Bit. Das scheint für 
die Anwendung des Erstellers offenbar zu reichen.

Hendrik L. schrieb:
> Es behauptet 'one sample per clock'
Beim Schnellen ÜBerfliegen scheinen die Module die dort ADD-MUL heißen 
einfach hintereinander gehängt. Wenn der FPGA schnell genug ist, geht 
das mit einem sample per Clock bei den angegebenen 50MHz. Das hilft aber 
nicht weiter. Man könnte es auch registrieren und bekäme auch jeweils 
ein Sample, halt nur mit Latenz, dafür aber auch gerne mit 200 MHz, also 
effektiv rascher.

Dem Ersteller ging es da wohl um klein und kompakt. Der falsche 
Y-Offset, den man in der gelben Kurve im "Oszillogramm" sieht, scheint 
auch nicht zu stören. Das ist ein ganz offensichtlicher Fehler beim 
Interpretieren des Phasenvektors beim Vorzeichenbilden und deutet auf 
ein Misverständnis beim Zeitschema: Da wird wahrscheinlich der Y-Wert 
aus einer falschen Zeit / ein Takt zu spät geschnappt und anhand der 
aktuellen Phase geflippt.

Wie auch immer ...

Den kompaktesten und genauesten Sinus bekommt man im FPGA mit einem 
virtuellen Oszillator nach DGL 2.Ordnung. Das geht in etwa bis zur 
Frequenz Clock / N*N*N  bitgenau, wenn man alles gut genug aufgelöst 
rechnet und gut rundet. Bei 200MHz sind 15kHz bei 24 Bit und dann 48 Bit 
breiten Vektoren.  Das geht voll als pipeline in etwa 12-15 Takten, 
wegen 3 verketteten ADDs und MULs auf breiten Vektoren. Mit weniger 
Genauigkeit geht es auch mit 6 Takten, was dann die minimale 
Iterationslänge festlegt -> 6 Kanäle / Latenz. Nimmt man jetzt eine 
Länge von hier 16, bekommt man 16 Kanäle mit denen man arbeiten kann. 
Bei einem 6 Phasensystem wären eventuell 18 sinnvoll.

Der Oszillator reagiert sofort auf Parameteränderungen, allerdings eben 
wie eine realer, d.h. mit Schwingungen und einer Art "Hineingleiten" in 
den neuen Zustand (Amplitude / Frequenz).

Will man das nicht, braucht es eine DDS mit FIR-Filterung. Auch einen 
Cordic könnte man filtern.

: Bearbeitet durch User
von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

Wieviel Stützstellen werden denn benötigt? Ich bezweifle, das da 
wirklich zu wenig RAM ist. und aus den 40 MHz könnte man im FÜGA auch 
für einen bgrenzten Bereich Vielfache erzeugen und so die absolute 
Durchlaufzeit erhö
hen.

Und ein pißchen Capazität in der schaltung rundet auch die Stufen ab... 
also da sollte man vielleicht mal an ein FPGA-Evalboard eine Scope, 
Speckie anschliessen und schauen was rauskommt.

von Andreas M. (amesser)


Lesenswert?

Wenn du genug Addierer/Multiplizierer hast, dann kannst Du die Cordic 
doch einfach als Pipeline umsetzen.

von Bradward B. (Firma: Starfleet) (ltjg_boimler)


Lesenswert?

> Wenn du genug Addierer/Multiplizierer hast, dann kannst Du die Cordic
> doch einfach als Pipeline umsetzen.

Um welchen FPGA-Typ geht es hier eigentlich, Spartan XL aus der 
Mottenkiste?.

von Gerhard H. (ghf)


Lesenswert?

Bradward B. schrieb:
>> Wenn du genug Addierer/Multiplizierer hast, dann kannst Du die Cordic
>> doch einfach als Pipeline umsetzen.
>
> Um welchen FPGA-Typ geht es hier eigentlich, Spartan XL aus der
> Mottenkiste?.

Ich habe einen DDS veröffentlicht auf opencores.org.
Der geht natürlich auch mit table lookup.
project = sincos  in der Abteilung arith.
Die opencores web site ist so langsam am Vergammeln, notfalls
kann ich ein zip schicken.

Der DDS liefert sin und cos gleichzeitig ohne weiteren Mehraufwand.
Auf einem Spartan-6-eval board aus der Mottenkiste läuft
er mit 200 MHz ohne Optimierungsgetue. Pipelinestufen sind
kombinatorisch bis ??? durch ein generic einstellbar.
Symmetrie wird ausgenutzt soweit es geht.
Reines VHDL ohne Hersteller-Macros.

Die Sunderland-Technik zum Zerlegen der Sinus-Tabelle
in 2 viel kleinere habe ich nicht gebraucht, mir kam es
auf kleine Latenz an,  für einen Demodulator auf 70 MHz.
Viel delay macht die Stabilität der digitalen PLL schwer
beherrschbar, deshalb auch kein Cordic.

Mit der Sunderland-Technik kann man die Größe der Tabelle
auf 1/10  ..  1/50 der Speicherbits insgesamt runterbringen,
je nach Rom-Abmessungen.

Beschrieben wird das in James A. Crawford:
Frequency Synthesizer Design Handbook

Er gibt einen pointer:
Sunderland, D.A. et al. CMOS/SOS Frequency synthesizer LSI
circuit for spread spectrum communications
IEEE J. Solid State Circ. Vol. SC-19   August 84  pp 495-505

Wenn Du's irgendwo erlegst, würde mich eine Kopie freuen.

Man könnte auch eine Tabelle für mehrere Kanäle multiplexen
wenn der Takt schnell genug ist.

Gerhard H

: Bearbeitet durch User
von Gerhard H. (ghf)


Angehängte Dateien:

Lesenswert?

Ich glaube, das geht noch als fair use durch.

von Matthias 🟠. (homa)


Angehängte Dateien:

Lesenswert?

Leider war die Quelle nicht besser ;-)
Hier als kleines PDF (scantailor + naps2).

von J. S. (engineer) Benutzerseite


Lesenswert?

Gerhard H. schrieb:
> Die Sunderland-Technik zum Zerlegen der Sinus-Tabelle
... stammt ja noch aus einer Zeit, wo RAM sehr knapp und teuer war - 
bzw. es FPGAs noch gar nicht gab. Es ist am Ende auch eine 
Interpolation, die wie CORDIC und alle diese DDS-Verfahren immer einen 
Restfehler produziert. Den muss man sich ansehen. Sunderland ist da 
nicht so glücklich, weil er "unten" viele kleine Miniaturbögen hat. Das 
auszugleichen kostet am Ende wieder mehr Rechenaufwand. Wenn man 
ausreichend RAM hat, ist das direkte Ablesen immer das Beste, wenn es 
DDS sein soll - zumal man mit heutigen BRAMs eben zwei Adressen / Werte 
gleichzeitig bekommt.

Die anschließende Filterung ist dann das Entscheidende, um Oberwellen zu 
beseitigen, die unerwünscht sind. Dort muss man den Kompromiss zwischen 
"glatt" und "schnell" hintrimmen. Da hängt man an die beiden Ausgänge 
der DDS einfach ein paar Register dahinter und setzt einen FIR drüber.

Eine gewisse Filterung braucht es ja eigentlich immer, weil alle diese 
Funktionen einen Sprung erzeugen, wenn man die Frequenz oder die Phase 
umstellt. Das einfachste und "weicheste" ist da dann immer noch der 
Sinus-Resonator, da dieser selber ein Filter ist. Wenn man den breit und 
damit genau genug aufbaut, hat man direkt auch Sinus und Cosinus über 
die beiden höchsten Integrationssstufen.

von Rick D. (rickdangerus)


Lesenswert?

J. S. schrieb:
> Eine gewisse Filterung braucht es ja eigentlich immer, weil alle diese
> Funktionen einen Sprung erzeugen, wenn man die Frequenz oder die Phase
> umstellt.
Kann man dafür nicht das Anti-aliasing Filter vom DAC etwas anders 
auslegen?
Mit einer niedrigeren Grenzfrequenz dürfte das doch die selbe Funktion 
erfüllen...

von J. S. (engineer) Benutzerseite


Lesenswert?

Rick D. schrieb:
> Kann man dafür nicht das Anti-aliasing Filter vom DAC etwas anders
> auslegen?
Wenn das konkret möglich ist, ja - aber:

a) werden die analogen Filter bei entsprechender Güte NOCH langsamer und 
träger, als die digitalen.

b) sind gute analoge Filter in der Regel teurer, als intern filtern und 
richtig sauber ausgeben

c) streuen analoge Filter mehr in der Produktion

d) hat man keine Kontrolle über das, was der DAC mit den kleinen 
Sprüngen und Knicken so macht in Sachen dithering und overshot etc

e) gibt es ein Problem, weil man die Frequenz nicht kennt.

Zu a)-c) ersetzen wir ja eher analoge Filterfunktionen nach dem DAC 
durch SW, um diese schneller und stabiler zu machen ...

... bezüglich d) werden Wandler vorkompensiert um deren Verhalten 
anzupassen, d.h. die Bandbreite und Schwinger zu optimieren. Das gleiche 
gilt für die nachfolgenden Verstärker der Signale.

Was e) angeht: Gerade Motorsteuerungen fahren ja völlig unterschiedliche 
Frequenzen. Das ist wie Audio. Bandlimitieren kann man das nur ganz 
"oben" am Ende. Will man eine Frequenz weiter unten "fahren" dann muss 
die auch Sinus sein, - ist es aber nicht, weil der Filter zu hoch 
ansetzt. Man kann das nicht dem RC-System im DAC oder einem 
nachgeschalten Tiefpass im System überlassen und auch keinesfalls der 
Motor-Induktivitär oder der Achsenträgheiten.

Es braucht also eine adaptive Glättung für die jeweilige Fahrfrequenz -> 
parametrierbares IIR-/FIR-Filter. Was man generell tun kann, ist, bei 
sehr langsamen Sinüssen zu dithern und noiseshaping zu betreiben, sodaß 
dass Störspektrum der Knicke und Fehlinterpolationen und Stufen nach 
oben wandert. Dann ist es einfacher zu filtern.

von Rick D. (rickdangerus)


Lesenswert?

Man merkt, Du hast Dich schon mal intensiver damit beschäftigt :)
Danke für die ausführliche Antwort!

von Rbx (rcx)


Lesenswert?

Rolf schrieb:
> Wenn nicht muss ich FPGA-Takt und Gehäuse ändern.

Oder einen DSP einfliegen, und den wirklich effektiven CORDIC-Algo im 
FPGA "Legacy" nennen.
(https://www.reddit.com/r/FPGA/comments/kdnkzf/how_prevalent_is_cordic_these_days/)

von J. S. (engineer) Benutzerseite


Lesenswert?

Jetzt mal ehrlich: Wie relevant ist eine Frage
a) eines so unerfahrenen Nutzers
b) in einem solchen Forum, der
c) irgendwo lernt, wo die Professoren angeblich noch nie was vom CORDIC 
gehört haben wollen?

Ist das die Pampa-Universität?

Die Aussage des Antwortenden ist auch am Thema vorbei, da der schon mal 
nicht kapiert, wie hoch die Bandbreite in FPGAs im Vergleich zu den DSPs 
ist und nur einen einmaligen Rechenvorgang vergleicht. Man kann und muss 
man keinesfalls immer und überall einen DSP ankleben, um dessen 
Recheneffizienz zu nutzen.

Gleichwohl wird das durchaus gemacht und Teile von Rechnungen aus FPGAs 
herausgeholt. In den mir bekannten realen Fällen in der Industrie aber 
war das meistens aus Stromspargründen, weil das Gerät mit Batterien 
betrieben wird und weit fliegen soll bzw. es in der Wüste steht und 
wenig Raum für interne Hitzeentwicklung gab. Der teilweise Umstieg auf 
DSP war notgedrungen, der Situation geschuldet, teuer und umständlicher 
und wäre andernfalls unterblieben.

In den allermeisten Systemen, die wegen Berechnubgsbandbreiten einen 
FPGA erfordern, macht man auch den CORDIC und Sinus im FPGA, auch wenn 
die für sich als Modul betrachtet, umständlicher sind.

Heute lernen aber die meisten Studenten an SOPCs die ARM-Cores drin 
haben. Da ist der erste Griff für alles Mathematische natürlich der DSP 
und C.

von J. S. (engineer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Wenn man die Diskussion weiter verfolgt, findet man überwiegend Ideen, 
die eine Verallgemeinerung der Erfahrungen aus eigenen Projekten 
beinhaltet, ohne aber wirklich Übersicht über allemöglichen Anwendungen 
zu haben. Manchmal scheinen mir auch die Optionen der Haardware oder von 
FPGAs nicht verstanden zu sein. Da schreibt z.B. einer, daß er den 
CORDIC (und dessen Multiplikationen) nicht gut findet und es nun selber 
mit den "DSPs" in FPGAs gemacht haben will. :x

Auch sind die Anwendungen, die da bearbeitet werden, offenbar nicht 
sonderlich anfordernd an die Genauigkeiten gewesen, siehe das Beispiel 
mit den 18 Bit und der quadratischen Interpolation der Sinuswerte, die 
dann aber offenbar nur 2 Punkte involviert, was keinen Sinn macht.

Mein Tipp: Bevor man sich da zuviel abmüht mit Rekursionen, Iterationen 
und Zugriffen auf Speicherzellen, die ja in DSPs auch stattfinden müssen 
und das RAM fordern, ist es oft schlauer, statt eines zusätzlichen DSPs 
mit RAM, einfach über den Bus, den es zum DSP ja bräuchte, zu einem sehr 
geringen Preis direkt das RAM an den FPGA zu hängen. Die haben je genug 
Fläche und Bandbreite, um ausreichend hochgenaue Werte zu liefern. Dann 
gibt es mit 32Bit über die Ausgabe eines Wertes und der Steigung direkt 
die Option einer Interpolation von 16 auf ca. 22-24 Bit und mit einer 
orthogonalen Rechnung auch den Cosinus in ähnlicher Qualität. 
Interpoliert werden muss sowieso. Auch wenn nur linear interpoliert und 
gefiltert wird, kriegt man aus einer 16 Bit-Tabelle einen maximalen 
Fehler von 0,0002.

Wer keine DDR-Controller oder deren Latenzen will, der könnte auch ein 
SRAM dranhängen. Damit packte man um 2005 schon SIN/COS IQ mit 80Mhz.

von Rbx (rcx)


Lesenswert?

J. S. schrieb:
> Ist das die Pampa-Universität?

Wenn man den Punkt jetzt mal "aufspießt": notwendigerweise.

Zuerst mal fand ich die Sache mit den Veröffentlichungen interessant. 
Das war doch bei Haskell ganz ähnlich. Hochzeiten so von 2008 bis 2012 - 
danach kaum noch Einträge in der Bibliothek. Später gab es dann noch 
Lambda-Kalkül-Importe bei Java und bei C++ und das wars dann. 
Traditionell haben C-Basierte Programmier-Sprachen halt auch ihre 
Vorteile (und Bibs).

Und DSPS? Die sind schon lange mit (vielbändiger) Telefonbuchdicker 
Literatur unterfüttert, die teilweise auch noch wertvolles naheliegendes 
KnowHow aus der Analogwelt importiert.

So gesehen ist jedes FPGA-Projekt notwendigerweise ein Privatprojekt mit 
einer, passend aus gedrückt:
Pampa-Universität ;)

(https://www.youtube.com/watch?v=TBCf1p7BSek)

von J. S. (engineer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Das Video von Cesare habe ich mal überflogen, kriege aber deinen Punkt 
nicht so recht: Geht es jetzt um ein Beispiel des CORDIC? oder um SOUL? 
- Mein Einwurf mit der "Pampa" war so gemeint, daß es eigentlich nicht 
möglich sein sollte, daß "ein Prof noch nie was davon gehört haben 
soll".

Wie auch immer: Was er hier beschreibt ist ja nichts anderes als (s)eine 
Form der Synthese der Sinuswellen, um einen additiven Synthesizer zu 
bauen mit Hinweis auf die Vorteile u.a. der Bandlimitierung. Das ist 
wohl irgendwie effektiver (als was?), wobei ich noch nicht so recht 
sehe, was er da ganz genau anders/besonderes macht, weil ich SOUL nicht 
kenne.

Was FPGA angeht, gibt es für die mehrdimensionale Wellensynthese auch 
die Option, einen sehr genauen Sinus zu bauen und die Oberwellen per 
Multiplikation auszurechnen, wie ich das hier ja schon mal gezeigt 
hatte:
Vervielfachung der Frequenz mittels Multiplikation
Im rechten Bild sieht man die Oberwellen in Chipscope im damaligen 
Spartan 3 FPGA.

Auch dann habe ich ja die Bandkontrolle in den Händen und in FPGAs geht 
ja die Multiplikation sehr einfach. Nur den initialen Sinus muss man 
lösen. Da hat ein DSP sicher Vorteile, unbestritten. Hauptvorteil ist 
die Auflösung der Berechnungen, pro Schritt. Da muss man eben im FPGA 
bei der Grundwelle einmal richtig investieren. Für jede Oberwelle, die 
man generieren will, muss man mindestens 1 Stelle an Auflösung vorher 
reservieren. Der 24 Bit Sinus, um ein perfektes Rechteck bis 20kHz zu 
bauen bräuchte demnach rund 36 Bit Auflösung.

Ich sehe diesbezüglich das Problem bei CORDIC aber nach wie vor in der 
Approximation, die einen Prinzipfehler enthält, den man nur unterdrücken 
kann, wenn man über die geforderte Genauigkeit des Ziels deutlich hinaus 
geht und das dadurch entstehende Fehlerrauschen filtert. Das wäre ganz 
besonders beim Audio wichtig. Ein so genauer CORDIC ist aber sehr 
rechenaufwändig, wenn er das für alle Wellen machen möchte.

Was ich mir aus dem Video mitnehmen, war der Taschenrechner:

von Rbx (rcx)


Lesenswert?

J. S. schrieb:
> Was ich mir aus dem Video mitnehmen

Ja gell? Ein wenig verfänglich diesbezüglich fand ich das Video auch. 
Ich konnte den Erklärungen da jedenfalls besser folgen als dem hier:
https://www.mikrocontroller.net/articles/Audio-DSP_mit_Spartan_3-FPGA

Wichtig finde ich auch, dass es hilft, so ein paar grundsätzliche 
Hintergründe zu erarbeiten. Das muss man doch vor allem selber tun, und 
sowas kann kaum über einen Forenbeitrag übertragen werden.
Im Video zwar einiges Wichtige nur schnell schnell im Schweinsritt 
verklickert (Shift,Add, Vector(+loop)..) - aber so als Schnittstelle zu 
den 50ern fand ich den Vortrag schon ok. Man darf ja auch nicht 
vergessen, dass die Leute damals noch richtig gut mit Logarithmen 
rechnen konnten, und Bleistift-, Zirkel- und Karopapiermathe auch noch 
aus dem FF konnten.
Darüberhinaus konnten die damals auch schon Aussagen zur 
Parallelrechnerei machen: Lisp zwar eine gute Idee - aber zum Rechnen 
selber hatte man doch lieber Fortran eingesetzt ;)

Hinsichtlich der Ausgangsfrage wäre aus meiner Sicht zu empfehlen, den 
Aufbau für das "Gerät" zuerst mit ASIC, CPU oder DSP zu machen. Bei ARM 
bietet sich ja beides an (also CPU + DSP), wäre sogar noch besser.

von Rolf (audiorolf)


Lesenswert?

J. S. schrieb:
> Dem Ersteller ging es da wohl um klein und kompakt. Der falsche
> Y-Offset, den man in der gelben Kurve im "Oszillogramm" sieht, scheint
> auch nicht zu stören. Das ist ein ganz offensichtlicher Fehler beim
> Interpretieren des Phasenvektors
An dem Programm-Code stimmt noch mehr nicht, wie mir scheint. Und wie 
richtig gesehen ist die Auflösung viel zu gering.

Andreas M. schrieb:
> Wenn du genug Addierer/Multiplizierer hast, dann kannst Du die Cordic
> doch einfach als Pipeline umsetzen.
Ja natürlich. Wenn ich den entsprechend parametrisiere, ist der voll 
pipeline-fähig. Da behebt aber das Problem nicht, weil er eben bei 
entsprechender Genauigkeit sehr viele (zuviele) Takte benötigt.

Gerhard H. schrieb:
> Ich habe einen DDS veröffentlicht auf opencores.org.
Welche Vorteile hätte dieser gegenüber dem Core aus dem Coregenerator?
Ich habe den Programm-Code angesehen, fürchte aber dass auch der nicht 
schnell genug ist. Die Methode ist ja dieselbe. Oder?

Gerhard H. schrieb:
> Mit der Sunderland-Technik kann man die Größe der Tabelle
> auf 1/10  ..  1/50 der Speicherbits insgesamt runterbringen,
> je nach Rom-Abmessungen.
Der geht nicht, wegen der umständlichen Berechnung.

Es wird wohl auf eine Tabelle hinauslaufen in einem größeren FPGA.

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.