mikrocontroller.net

Forum: FPGA, VHDL & Co. Sinustabelle in fpga initialisieren


Autor: xxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo

für mein projekt soll ich einen NCO (numerical controlled oscillator) 
realisieren, dazu benötige ich eine sinustabelle. wie ich sie realisiere 
und so ist klar, das problem ist, ich darf die sinustabelle im fpga 
nicht erst errechnen, sondern sie soll zu beginn schon vorhanden sein.
da sie aber ne größe von 2^16 addressen hat, kann ich die tabelle nicht 
per hand reinschreiben. welche möglichkeiten gibt es denn noch. habe es 
mit ner externen textdatei versucht, wo ich später herausgelesen hab, 
das man die datei erst über fpga schreiben muss, bevor man sie einlesen 
kann.

dann gibt es noch die .mfc-datei, wenn ich mich täusche ist diese auch 
nicht für reine vhdl-programmierung geeignet und dsp-programmierung ist 
nicht erlaubt.

einzige alternative die ich sonst noch kenn, das ich mir den rom mit der 
tabelle beschreibe und dann immer darauf zugreife

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> da sie aber ne größe von 2^16 addressen hat
Wozu brauchst du eine Sinustabelle mit 65536 Werten?
Mal abgesehen davon, dass übliche FPGAs intern gar keine so großen 
Speicher (64kByte) haben, könntest du damit einen Sinus auf 
360°/(65536*4)=0,0014° auflösen (mal 4 weil du ja nur 1/4 eines Sinus 
ablegen mußt, die anderen 3 Quadranten lassen sich dann leicht 
berechnen).

Das ist schon extrem genau ;-)

Ich würde behaupten, das brauchst du nicht. Mach doch eine kleine 
Tabelle und interpoliere zwischen den Stützpunkten. Das wäre m.E. der 
bessere Weg.

Konkret zu deiner Frage:
Welchen FPGA-Hersteller willst du einsetzen?

> einzige alternative die ich sonst noch kenn,
> das ich mir den rom mit der
> tabelle beschreibe und dann immer darauf zugreife
Dann kannst du (zumindest bei Xilinx-Config-Proms) aber nur gaaaanz 
niedrige Frequenzen erzeugen, die sind nämlich seriell ;-)

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit Cordic den Sinus berechnen - oder ist das zu langsam?
http://www.xilinx.com/bvdocs/ipcenter/data_sheet/cordic.pdf

Autor: xxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups 2^12, sorry hab mich vertippt, und die anzahl wurd mir so vorgegeben

benutzt wird von altera das Board Stratix II EP2S60F1020C4

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab vor kurzem mit dem selbem Problem gekämpft. Eine Sinustabelle 
kannst du ganz einfach durch den Kompiler erzeugen. Beispiel:
type VEKTOR is array (0 to 255) of integer;
signal SINUS: VEKTOR; 
signal COSINUS: VEKTOR;


     
build_tab: for k in 0 to 255 GENERATE
            CONSTANT x: REAL := SIN(real(2) * MATH_PI * real(k)* real(1)/real(255)) * real(255)*0.5 ;
             CONSTANT y: REAL := COS(real(2) * MATH_PI * real(k)* real(1)/real(255)) * real(255)*0.5 ;
            begin
                SINUS(k) <= integer(x);
                COSINUS(k) <= integer(y);
            end generate build_tab;

Eine Tabelle für 2^16 Bit Auflösung wird aber unwahrscheinlich groß und 
deine Entwicklungsumgebung braucht viiieeel Zeit um das alles zu 
erstellen.
Wenn es wirklich mit einer Tabelle gemacht werden soll, wäre es besser 
eine kleine Tabelle zu erstellen und dann zwischen den werte 
interpolieren.

Besser ist der Cordic algorithmus. Ich habe mich da auch erst vor 
gescheut weil es unheimlich kompliziert aussieht. Aber im eigentlich ist 
der Algorithmus ganz einfach und Logisch aufgebaut. Ich empfehle wir das 
Buch Digital Signal Processing with Field Programmable Gate Arrays. Da 
ist der Algorithmus sehr gut erklärt und sogar ein Beispiel Code dabei, 
ganz einfach zu verstehen!

Autor: Morin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> welche möglichkeiten gibt es denn noch.

Ein C-, Java-, oder sonstwie Programm, welches in einer Schleife die 
Sinuswerte errechnet und eine VHDL-Datei für ein ROM generiert. Schon 
zigmal gemacht, aber versuch es erstmal als Übung - es ist ganz 
nützlich, mit solchen Codegeneratoren Erfahrung zu haben.

Autor: xxx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@michi, danke für den tip

der war sehr nützlich, und da die tabelle ja beim compilieren erstellt 
wird, werd ich das wohl auch im projekt verwenden dürfen

die kompilierzeit beträgt bei mir 5min und speicher geht übrigens auch 
kaum verloren bin bei 6% also noch viel platz


auch der buchtip ist sehr nützlich weil ich auch noch nen digitalen 
filter realisieren soll und ich mir die nützlichen seiten auf google 
book anschauen kann

Autor: Uwe Bonnes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Xilinx Webpack kennt ein SinCosinux Modul in Coregen...

Autor: walchhofer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das ist aber auch nur eine tabelle!

Autor: Asic-Mann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann man als selbstidenten Algo fomrulieren in form eine Rekursion. Das 
reicht meistens zeitlich für einige 100kHz - ganz ohne Tabelle.

Autor: cl-saxony (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Michi,
was sollen die real(255)*0.5 in deinem Code:

build_tab: for k in 0 to 255 GENERATE
            CONSTANT x: REAL := SIN(real(2)  MATH_PI  real(k)* 
real(1)/real(255)) * real(255)*0.5 ;
             CONSTANT y: REAL := COS(real(2)  MATH_PI  real(k)* 
real(1)/real(255)) * real(255)*0.5 ;
            begin
                SINUS(k) <= integer(x);
                COSINUS(k) <= integer(y);
            end generate build_tab;

Erzeugt Sinus im Sinus, da mit halber Frequenz.

Wenn du einen reinen Sinus wünschst, einfach weglassen:
CONSTANT x: REAL := SIN(real(2)  MATH_PI  real(k)* real(1)/real(255));

Mfg

Autor: SagINet (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Äh what?

*255*0.5 würde ich glatt für ne Bereichsanpassung halten...
sin x -> [0°, 360°[
sin y -> [0 ... 1]

nach der Anpassung
sin x -> [0°, 360°[
sin y -> [0 ... 255/2]

*255 für Bytegröße, *0.5 wegen halber Amplitude (halber Bereich für 
positive Amp. und die andere Hälfte in den negativen Bereich)

wenn man mit Integergenauigkeit arbeitet muss man halt
* (2^32-1) * 0.5 rechnen, damit man die 32 Bit ausnutzt!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SagINet schrieb:
> 20.01.2011 10:41
>       Äh what?
Würde ich nach 1 1/2 Jahren auch fragen...

> *255 für Bytegröße, *0.5 wegen halber Amplitude
Richtig. Und daher ist der Kommentar falsch:
>> Erzeugt Sinus im Sinus, da mit halber Frequenz.
>> Wenn du einen reinen Sinus wünschst, einfach weglassen:
>> CONSTANT x: REAL := SIN(real(2)*MATH_PI*real(k)*real(1)/real(255));
Was da wegulassen wäre ist nämlich das real(2) im Sinus... :-o

SagINet schrieb:
> wenn man mit Integergenauigkeit arbeitet
Wird dort aber nirgends getan, die CONSTANT x ist REAL.
Allerdings wird dann durch das *0.5 dem Array SINUS() Werte im Bereich 
von -127 bis +127 zugewiesen...

Autor: Johann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also 4096 Werte a 16Bit sind 65536Bit. Dies sollte kein Problem 
darstellen die Daten in einem RAM abzulegen.

Ich mache es wie folgt (bei Xilinx):

1. Ich erstelle mit Excel die Sinustabelle dies ist schnell gemacht.
2. Speicher dann die Tabelle als txt-Datei ab.
3. Bei Xilinx gibt es ein Tool mit dem man BlockRams oder ROM mit Werten 
vorbelegen kann. Ich Öffne also das Programm lade das Text-File und 
erzeuge dann das File für die BlockRam vorbelegung.

4. Anschließen erzeuge ich mit dem IP-Core Wizard einen BlockRAM mit der 
richtigen größe. Beim Wizard kann man dann einstellen ob alle Zellen mit 
einer Konstanten vorbelegt sein sollen oder ob man ein 
Initialisierung-File verwenden möchte. Ich wähle natürlich das 
Initialisierungs-File aus und erzeuge somit den vorinitialisierten Block 
RAM.

5. Somit steht in der 0. BlockRam Adresse der 1. Sinuswert in der 2. 
Adresse der 2. Sinuswert usw.

Autor: Johann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dieser eben beschriebenen Methode kann man nicht nur ein Sinus oder 
Cosinus erzuegen sondern jedes beliebige Muster. Du kann so z.B. eigene 
Testsignale erzeugen

Autor: René D. (Firma: www.dossmatik.de) (dose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Asic-Mann schrieb:
> Kann man als selbstidenten Algo fomrulieren in form eine Rekursion. Das
> reicht meistens zeitlich für einige 100kHz - ganz ohne Tabelle.

Mit dem Cordic Algorithmus kommt man in höhere Frequenzen. Weit in die 
Megaherzen. Das ist ganz ohne Tabelle.

Autor: Sym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entweder mit der Sinusfunktion aus math_real eine Tabelle generieren 
oder eben CORDIC. Für kleine Sinustabellen (so 1 KB) würde ich eine 
Tabelle verwenden, darüber CORDIC.

Der Cordic Algorithmus läuft pipelined je nach Wortlänge mit über 200 
MHz am Stratix II C4. Selbst seriell sollten mit 15 Stufen solltest du 
noch etwa 10 Mio Sinusberechnungen/s durchführen können.

Autor: Jürgen S. (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Solange man nur den Wert selber braucht und mit dem pipelining leben 
kann, ist der CORDIC in der Tat besser. Es gibt aber Fälle, wo 
dynammisch moduliert werden muss/soll und da ist die DDS-Methode besser. 
Mit einer echten Tabelle kann man auch gut interpolieren, indem man die 
Tabelle mehrfach abtastet. (dy und auch dt).

Autor: Ranga Yogibaer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mit dem Cordic Algorithmus kommt man in höhere Frequenzen. Weit in die
>Megaherzen.
Rene, wieso kommt man mit Berechnung höher, als mit Ablesen aus dem Ram?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ranga Yogibaer schrieb:
> Rene, wieso kommt man mit Berechnung höher, als mit Ablesen aus dem Ram?
Das wurde nicht behauptet... ;-)
Ein vorberechnetes RAM auszulesen dürfte ungeschlagen dei schnellste 
Variante bleiben...

Autor: Hotte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie genau ist der Cordic-Algorithmus? Kann man sich das aussuchen?

Autor: D. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hotte schrieb:
> Kann man sich das aussuchen?

Je mehr bit Auflösung du nimmst desto genauer wird er

Autor: Ranga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ein vorberechnetes RAM auszulesen, dürfte ... die schnellste
> Variante bleiben...
Das wollte ich aber auch gesagt haben. Wobei: Grosse Tabellen belegen 
zuviel Blockram. Muss man raus ins DDR, wird es auch langsamer wegen der 
Latenz.

Autor: René D. (Firma: www.dossmatik.de) (dose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hotte schrieb:
> Wie genau ist der Cordic-Algorithmus? Kann man sich das aussuchen?

Der Cordic-Algorithmus ist ein Näherungeverfahren. Je mehr Stufen 
einbaut um so genauer wird er. Der Algorithmus konverigert sehr schnell. 
Bereits bei geringen Iterationanzahlen ist der Fehler sehr gering.


http://www.mathworks.com/help/toolbox/fixedpoint/r...


>Rene, wieso kommt man mit Berechnung höher, als mit Ablesen aus dem Ram?
Höher habe ich nicht gesagt doch die Ausgabe mit 100Msamples/s ist kein 
Problem. Es geht auch höher, doch das habe ich noch nicht gebraucht.

Autor: Alfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nach dieser Grafik von Mathworks beträgt der maximale absolute Fehler 
auch bei einer Iterationstiefe von 10 immerhin noch 0,005! Die Frage 
ist, wie dort der zugehörige Endwert aussieht. Selbst bei 1.0 wären das 
maximal 1:200, also nicht einmal 8 Bit Genauigkeit. Da braucht man aber 
keinen 12-bit Cordic.

Für eine Audiosignalerzeugung oder "analoge" IQ-Demodulation reicht das 
bei Weitem nicht.

Interessieren würden mich mal der Platzbedarf und der 
Rechenzeitbedarf(Latenz) für eine echtes Äquivalent einer Tabelle von: 
12 Bit Amplitude und 16 Bit Phase. Die bräuchte ich nämlich für eine 
DDS.

Autor: Hotte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der NCO in Quartus braucht bei Deinen Angaben 1402 LEs ud mit 1 Bit mehr 
1582 (32 Bit Phase, 17 Frequenzmodulation, 13 Bit Genauigkeit).
Er bringt bei 20kHz 80dB SNR laut Diagramm.

Autor: Gerhard Hoffmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe eine Sinus/Cosinus-Funktion unter

http://opencores.org/project,sincos

abgelegt. Sie benutzt ROMs, weil der Cordic für meine Zwecke (digitale
PLLs) zu viel Totzeit erzeugt. Die Anzahl der Pipelinestufen kann man 
frei
wählen (in 0...10). Für den rein kombinatorischen Fall erzeugt XST viele
kleine distributed RAMs und keine Blockrams, was die generierte Hardware
natürlich ziemlich aufbläht.

Es wird nur 1/4 Welle abgespeichert, der Rest wird gespiegelt.
Sinus & Cosinus gleichzeitig brauchen nicht mehr Speicher als Sinus 
allein.
Das ist praktisch für I/Q-Verarbeitung.

Geschwindigkeit ist 230 MHz in Spartan-6 ohne Klimmzüge mit hinreichend
vielen Pipelinestufen.

Reines, portables VHDL ohne Xilinx, Matlab oder sonstwelchen Bezug.


Gruß, Gerhard




Aus der description:
Sine and cosine table that can be synthesized. Pure VHDL, no other tools 
or
silicon vendor macros. Pipeline delay can be selected from combinatorial
to 10 stages at compile time via a generic.

Phase input and sin/cos output widths are automatically determined by 
the
connected bus. 16 bit phase/18 bit amplitude runs at 230 MHz in 
Spartan6-3
without any optimization efforts. (Just setting 250 MHz as the goal)

Also features a programmable pipeline register entity for most basic 
VHDL types.
Pipeline delay can be set from 0 to MAXINT clocks

Also a library for conversion between reals and integer/fractional 
signed and unsigned.

The test bed can log the generated sinewaves to a file for inspection 
with matlab.

Autor: Hotte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Status=Beta?

Autor: Gerhard Hoffmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Compiliert, synthetisiert und simuliert jedenfalls ok. Und Matlab hat an 
den erzeugten Sinuswellen auch nix auszusetzen. Für die Doku will ich 
das noch durch den Video-DAC des SP605-Boards jagen ("Hardware-proved"). 
Leider schon wieder ein neuer DAC-Typ.

Rückmeldungen bekommt man auch bei 350 Downloads nicht, weder pos. noch 
neg.

Gerhard

Autor: Hotte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na dann werde ich das mal erledigen. Wenn ich den Core freigeben habe, 
kannst du ja "approved by Horst" drunterstempeln :-)

Autor: FPGAler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist der nun approved?
(immer noch "Beta")

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerhard Hoffmann schrieb:
> Für die Doku will ich
> das noch durch den Video-DAC des SP605-Boards jagen ("Hardware-proved").
> Leider schon wieder ein neuer DAC-Typ.
Verstehe ich das richtig: Du willst einen (analogen) Farbkanal verwenden 
um Dein Signal auszugeben?

Um den Analogteil des Chrontel (SP605 u.ä.) zu aktivieren verwende ich 
folgende Initialisierung:
    // input data format (idf)
    // idf 0 - 24 bit color depht
    // dvi output / rgb bypass (vga output)
    // chrontel_address = 0x76; // 7 bit
    // dvi_address      = 0x50; // 7 bit -> display
    // apbvga delivers 640x480@60Hz
    // xclk with 1X pixel rate
    // reg  freq  <= 65 MHz   > 65 MHz
    // 0x33 tpcp    0x08        0x06
    // 0x34 tpd     0x16        0x26
    // 0x36 tpf     0x60        0xa0

    // adjust xclk and data
    chrontel_reg_write( 0x1d, 0x45); // input clock register, xcmd[3..0]=5
    
    // enable sync out and bypass
    chrontel_reg_write( 0x21, 0x09); // dac control register, sync, dacg[1..0], dacbp

    // values for lower 65 MHz according to table above
    chrontel_reg_write( 0x33, 0x08); // dvi pll charge pump control register,  dvid[2..0], dvii, tppsd[1..0], tcpcp
    chrontel_reg_write( 0x34, 0x16); // dvi pll divider register, tpffd[1..0], tpfbd[3..0]
    chrontel_reg_write( 0x36, 0x60); // dvi pll filter register, tplpf[3..0]
    
    // c0 = DVI, 00 = VGA only
    chrontel_reg_write( 0x49, 0xc0); // power management register, dvip, dvil, dacpd[2..0], fpd

Duke

Autor: Marian Kopecky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Het mal jemand einen Vergleich gemacht, wie sich CORDIC und Tabelle 
gegeneinander verhalten?

Also, welche CORDIC Auflösung entspricht welcher Tabellengröße?

Zumindest in der Softwareentwicklung kommt man schnell von Tabellen weg. 
Wie ist das bei FGPAs?

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo, bin da auch gerade dran...

Also, ein lummeliger Spartan3 schafft die CORDIC Umrechnung von Winkel 
nach Sinus/Cosinus nicht mit 100MHz (landet so ca. bei 75MHz, Winkel ist 
15bit, Sinus/Cosinus sind 16bit Werte). Ich habe das ganze mit 
Register-Balancing probiert (2 Clock cycle fuer die Berechnungen, hat 
nicht funktioniert) und bin dann auf 'multi-cycle' gegangen (da tut das 
ganze natuerlich, da effektiv mit 50MHz betrieben). Ist aber ziemlich 
'nasty'...

Eine LUT mit 1024x15bit plus angeschlossenem Multiplier (fuer die 
Verstaerkung) macht locker 100MHz (pipelined), ich kann also meinen 
Winkel mit einer Genauigkeit von 360Grad/1024 ~ 0,35Grad machen. Das 
reicht mir und deshalb nehme ich die LUT, zumal genuegend RAMs und 
Multiplier verfuegbar sind auf dem Chip.

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: Die LUT lasse ich mir uebrigens mit einem Perl-Script in der 
gewuenschten Aufloesung und Tiefe generieren. Bin ja nicht bescheuert 
und tippe das von Hand ein...

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ahh, edit: Die LUT speichert nur 90Grad ab, also ist die Aufloesung in 
etwa 0,35Grad/4 also damit <0,1Grad...

Autor: Andreas Fischer (chefdesigner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arbeitet der Cordic-Core eigentlich auch nur über 90 Grad und spiegelt?

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Fischer schrieb:
> Arbeitet der Cordic-Core eigentlich auch nur über 90 Grad und spiegelt?

ja

Autor: Weltbester FPGA-Pongo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Fischer schrieb:
> Arbeitet der Cordic-Core eigentlich auch nur über 90 Grad und spiegelt?

Ich denke, das machen alle Algorithmen so. Der Cordic liefert dazu noch 
Sinus und Cosinus parallel frei Haus.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.