Hi! Ich versuche, einen Cordic Algorithmus in VHDL zu realisieren. Er
soll später einmal für einen NCO eingesetzt werden. Also brauche ich die
Sinus- und Cosinuswerte. Den Winkel nähert er gut an (also geht er auch
in die richtigen Pfade) allerdings scheinen die shift and add
Operationen nicht zu laufen. Auch den Cordic gain habe ich noch nicht
rausgerechnet.
Kann mir vielleicht jemand helfen? Ich komme nicht mehr weiter.
Anmerkung: Für die meisten wird es wahrscheinlich sehr dilettantisch
aussehen, aber ich code VHDL erst seit circa 2 Wochen...
Ich habe gerade gelesen, dass man den CORDIC Gain damit kompensieren
kann, indem man den Anfangswert der Vektorlänge auf den reziproken Wert
setzt.
Also, statt 0 + j1 auf 0 + j0.607
Hier ist nochmal die source als Datei.
Ich benutze ModelSim 6.1
Naja, mein Problem ist, dass er nicht die richtigen Sinus und
Cosinuswerte ausgibt, wenn der Algorithmus durchgelaufen ist. Ich
vermute, dass der Fehler in den Shiftings steckt, aber ich weiß nicht,
wo.
Wie du vielleicht gesehen hast, nähert sich der Winkel schon an.
("angle" ist annähernd gleich zu "phase", wenn das Programm
durchgelaufen ist.)
Nur die Sinus- und Cosinuswerte werden anscheinend falsch aufaddiert
Achso, dankeschön!
Könntest du das vielleicht nochmal als Code hier im Forum schreiben,
damit ich das als Copy-Paste einfügen kann? Ich arbeite über Remote
Desktop und kann leider die Datei nicht einfügen...
Ich hab's hinbekommen :D Der Fehler war, dass ich die geshifteten Werte
schon eine Iteration zu früh hinzuaddiert habe. Da musste noch ein
ungeshifteter Wert hinzuaddiert werden. Naja, hier ist jedenfalls die
funktionierende Version, als Inspiration für Leute, die auch an dem
Problem hängen:
Hallo,
ich bin gerade dabei den winkel zwischen einem cosinus und sinus signal
aus einem resolver zu ermitteln, also genau das gegenstück zu diesem
quellcode beispiel. hat da eventuell jemand einen satz für mich bzw.
sogar den code. ich bin leider noch nicht hinter die funktionsweise des
algorithmus gekommenen (mein englisch ist leider zu schlecht um die
literatur zu verstehen)
danke schon einmal
marcus schrieb:
> Hallo,>> ich bin gerade dabei den winkel zwischen einem cosinus und sinus signal> aus einem resolver zu ermitteln, also genau das gegenstück zu diesem> quellcode beispiel. hat da eventuell jemand einen satz für mich bzw.> sogar den code. ich bin leider noch nicht hinter die funktionsweise des> algorithmus gekommenen (mein englisch ist leider zu schlecht um die> literatur zu verstehen)>> danke schon einmal
Ein mathemaitscher Ansatz ist, das Sinus mit dem Cosinus Signal zu
ermitteln. Dabei entsteht ein Signal mit der Doppelten Frequenz und dem
Gleichanteil. Der Gleichanteil entspricht dem Winkel zwischen den
Signalen. Die Doppelte Frequenz lässt sich mit einem Tiefpassfilter
entfernen.
Hallo Benedict
für 14 Tage VHDL sieht das schon ganz gut aus.
Ich habe keinen Simulator, jedoch habe ich versucht deinen Code zu
verstehen.
Hinweise:
Der Name von RST ist unglücklich gewählt. Es ist besser "load" für diese
Signal geeignet.
An Anfang des Prozesse prüfst du in welchen Quadranten dein Winkel
liegt. Da sehe ich nur drei Quadranten. Es gibt aber vier Quadranten.
Was ist mit dem Fall -1+j0?
Für das Schieben gibt es seit VHDL-93 die Befehle srl, sll, sra, sla
shift (left, right) (logic, arithmetic).
Ansonsten viel Spaß mit VHDL
Koennte mir mal bitte jemand erklären, wie dieser Core angesteuert
werden soll? Ich habe mir eine TB geschrieben, die den core antriggert
und bekomme uach daten raus. Allerdings sind es immer dieselben. Ich
sehe nicht, dass die Ergebnisse mitlaufen mit der eingespeisten phase.
Ich habe das Teil nicht geschrieben, trotzdem kann ich dir es erklären.
Mit rst='1' wird die Phase(Winkel) geladen. Nachdem rst='0' wieder ist,
werden mit jedem Takt der Cosinus- und Sinuswert genauer.
So sollte es sein ich habe schon bemerkt, dass rst hier als Namensgebung
unglücklich gewählt ist.
Da ich keine Simulation habe, ist es interessant was hier rauskommt.
Interessiert mich auch.
Bis bald.
Hi, Leute! Kam durch Zufall wieder hierhin, als ich nach was Anderem
gesucht habe :D
Also, zuerst: slr und sll hatte ich mal probiert, ging aber nicht. Weiß
nicht mehr, wieso :)
Zu den Quadranden: Der CORDIC kann von seinem Startpunkt +/- 90°
ansteuern, von daher reichen drei Startpunkte, womit 2 Quadranten sogar
doppelt angesteuert werden könnten.
Ich habe hier mal eine kleine Testbench angefügt, die auch Ergebnisse
auspuckt. Die Ergebnisseder ModelSim Simulation habe ich als Bild
angefügt.
TB:
Ach ja: Ich hatte damals noch eine kleine Änderung gemacht: Sollte das
hier jemand ausprobieren, wird er sehen, dass der Wert vom Cosinus auf
seinem Maximum einen Einknick hat. Das hatte mit dem Anfangswert zur
CORDIC-Gain Kompensation zu tun. Da habe ich noch eine kleine Abfrage
eingefügt (im Code unter dem shifting Teil):
Hallo Bendict,
wenn du hier angemeldest bist, kannst du einen Haken setzen bei E-Mail
Benachrichtigung.
Dann bekommst du automatisch eine Email, wenn jemand hier antwortet.
Was baust du als nächstes?
Du hattes eine interessante Idee.
ausserdem hat der core cordic die typen signed waehrend die testbench
stdlogic verwendet
vielleicht postest du nochmal core und testbench komplett zueinnder
passend
So funktioniert's.
Momentan arbeite ich an nem BPSK Demodulator. Um die Carrier Frequenz zu
strippen, benutze ich aber nicht den CORDIC, da der viel zu viele
Iterationen brauch und ich nicht auf eine genaue Phase angewiesen bin.
Deswegen hab ichs mit Lookup realisiert.
Der CORDIC war sowieso nur zur Übung. Gibt es ja auch im Xilinx CoreGEN
und der hat viel bessere Werte.
Hallo,
kann jemand bitte erklären, woher die Binärzahlen kommen?
IF (phase<"110000000000") THEN
angle<="110000000000";
costemp<="0000000000";
sintemp<="1011001010"; -- das hier?
und für jede Winkel
WHEN "0001" => data := "000100101110"; -- 26.5650°??
I_shift:= (costemp(9) & costemp(9 DOWNTO 1));
Q_shift:= (sintemp(9) & sintemp(9 DOWNTO 1));
Danke für die Hilfe
viele Grüsse
CS schrieb:> IF (phase<"110000000000") THEN> angle<="110000000000";> costemp<="0000000000";> sintemp<="1011001010"; -- das hier?>> und für jede Winkel>> WHEN "0001" => data := "000100101110"; -- 26.5650°??> I_shift:= (costemp(9) & costemp(9 DOWNTO 1));> Q_shift:= (sintemp(9) & sintemp(9 DOWNTO 1));
Hi,
kein Problem, bin an sowas auch seit 2 Tagen dran.
Oberer Teil:
Du selektierst den Quadranten in dem du dich gerade aufhaelst
(phase(11:10)=00 ist 'rechts oben', 01 ist links oben und so weiter)
Das 'case' statement ist auch einfach: Das sind die Faelle fuer arctan
1, 1/2, 1/4, 1/8, usw... Das ergibt halt bestimmte Winkel. Und die
werden jeweils berechnet und addiert oder subtrahiert.
@originalposter: Dein Problem mit den Nullstellen/Uebergaengen kannst du
ganz einfach loesen: Anstatt 'IF' und 'ELSIF' zu schreiben reicht es,
anstatt ELSIF einfach ein ELSE zu verwenden. Die Sonderbehandlung geht
dann naemlich automatisch.
Ausserdem ist der Code ziemlich grottig, sowas wuerde ich mich nicht
abzuliefern trauen...
... Aber prinzipiell funktioniert es, also nicht schlecht
Hi, der Thread ist ja jahrealt mittlerweile. Aber ich habe damals den
Code hier als Basis benutzt, ihn dann doch nicht benoetigt. Aber jetzt
brauche ich ihn...
Hier mal als Anhang, was ich aus dem 'rotating' CORDIC gerade gemacht
habe.
Ich habe den redundanten Code mal eingedampft, dabei das Timing deutlich
verbessern koennen.
Ich bin deshalb wieder auf diesen alten Thread gestossen, weil ich jetzt
was mit 'CORDIC vectoring mode' machen muss, also von per ADC gelesenen
Sinuessen und Cosinuessen den Winkel berechnen... Deshalb hab' ich den
alten 'CORDIC' hier nochmal ausgegraben. Die TB dreht nur den CORDIC
kurz in positive Richtung, dann in negative Richtung. Bei 'sinout' und
'cosout' sollte man also passende Signale finden...
Nur falls es jemanden hier interessiert...
Ein thread von 2009 - wow, der Zombie lebt :-)
Finde ich aber gut, dass mal jemand ein Thema zum Abschluss bringt. Habe
den thread abboniert, weil mich das auch interessiert. Ich bastle
nämlich auch gerade mit CORDIC.
Läuft Deine Version denn so, wie oben gepostet?
Klaus L. schrieb:> Ein thread von 2009 - wow, der Zombie lebt :-)
Ja, ist auch dringend nötig.
Schau dich doch mal um, was es denn sonst so gibt. Firmen wie Xilinx
haben in ihrem IP Portfolio zwar auch sowas, aber ohne Einblick in den
echten Quellcode.
Und anderweitig sucht man sich die Augen wund, ohne wirklich was
Brauchbares zu finden - es gibt nur Zeugs zuhauf, wo sich jemand "über"
den CORDIC-Algo ausläßt, aber ohne ihn jemals tatsächlich konkret
durchzuexerzieren. Das ist genau so wie z.B. das Gelaber über den
DES-Algo, der ja auch seit langem veröffentlicht ist, aber auch (wie
CORDIC) ohne daß es konkrete und zugleich verständliche (quasi
"knuffige") Realisierungen gibt.
Natürlich kann man sich hinsetzen, das Ganze an den theoretischen
Formeln durchackern und sich daraus seinen Code selbst schreiben. Jaja,
das wäre die selbständigste Methode, aber gelegentlich sucht man einfach
nur nach einer fertigen Teillösung, damit der Aufwand für ein Projekt
noch vom Einzelnen stemmbar bleibt und man nicht bei Adam&Eva beginnen
muß.
W.S.
Klaus L. schrieb:> Läuft Deine Version denn so, wie oben gepostet?
ja, simuliert sowohl mit GHDL/Gtkwave als auch mit Modelsim. Und mit
einem anderen cordic_top gebe ich ueber DACs die Ergebnisse aus,
Plattform ist S3E und S6 von Xilinx sowie CycIII von Altera.
Ich komme nochmal drauf zurück:
Läuft der Code korrekt? Liesse der sich als Basis nehmen, um ihn zu
pipelinen und schneller zu machen?
Ich suche eine Lösung, die schneller ist, als die von Xilinx!
Der Core hat eine enorme Latenz!
Die o.g. Schaltung läuft klassisch sequenziell. Kaum anzunehmen, dass es
schneller ist, als der Core. Aus der Erinnerung benötigt der je Bit für
die Genauigkeit eine weitereren zusätzlichen Takt.
Mir persönlich ist das native VHDL aber trotzdem symphatischer, weil Ich
dann genau solche Dinge wie die Auflösung in der Hand habe. Außerdem
lässt sich der Code für wenige Iterationstiefen auch parallelisieren und
damit beschleunigen - wer's braucht. Das geht mit dem fertigen CORE
nicht. Wie Ich an anderer Stelle beschrieben hatte, war es mal nötig den
CORDIC durch einen schnellen, manuellen ARCTAN zu ersetzen:
Beitrag "Re: Implementierung eines schnellen ARCUS TANGENS"