www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Fehler in DDS?


Autor: Max (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Freunde,

ich sitze nach wie vor an einer DDS, an der ich im Moment verzweifle und 
wäre für jede Hilfe echt dankbar.

Am Adressausgang (ADDR_OUT) des DDS-Moduls hängt die Lookup Table, in 
der eine viertel Sinusperiode gespeichert ist. Sie gibt nach einem Takt 
den entsprechenden Wert an den LUT_IN Eingang zurück (Werte von 512 bis 
1024) und wird dann über den kombinatorischen Prozess in der zweiten 
Hälfte der Periode subtrahiert, um Werte von 0 bis 1023 an den DAC zu 
geben.

Bei niedrigen Frequenzen und entsprechend niedrigen Phaseninkrementen 
funktioniert die Sache wunderbar. Bei höheren Frequenzen aber verschiebt 
sich die Adressierung zum Phasenregisterüberlauf so, dass im worst case 
die Amplitude des Signals kleiner wird. Das Resultat ist dann eine Art 
Amplitudenmodulation, die ich auch so im Spektrum sehe.

Es ist mein erstes "größeres" VHDL Projekt und langsam drängt die Zeit 
und ich finde meinen Fehler in meinem Vorgehen nicht. Wie gesagt, ich 
freue mich über jede Idee.

Viele Grüße, Max

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity DDS is
    port (
        RST      : in    std_logic;
        DDS_ON   : in    std_logic;
        ADDR_OUT : out   std_logic_vector(10 downto 0);
        LUT_IN   : in    std_logic_vector(8 downto 0);
        DDS_OUT  : out   std_logic_vector(8 downto 0);
        CLK      : in    std_logic
    );
end DDS;

architecture BEHAVE of DDS is


signal phaseaccu : unsigned(16-1 downto 0);
signal Delay_1: std_logic_vector(1 downto 0) := "00";
signal Delay_2: std_logic_vector(1 downto 0) := "00";

begin

     INCREMENT: process (CLK, RST)
     begin
          if RST = '1' then
             phaseaccu <= (others => '0');
             Delay_1 <= (others => '0');
             Delay_2 <= (others => '0');
          elsif CLK'event and CLK = '1' then
             if DDS_ON = '1' then phaseaccu <= phaseaccu+16000; end if;
             if (phaseaccu(16-1 downto 16-2) = "00") or (phaseaccu(16-1 downto 16-2) = "10") then
                ADDR_OUT <= std_logic_vector(phaseaccu(16-3 downto 16-2-10));
             else
                ADDR_OUT <= std_logic_vector(not phaseaccu(16-3 downto 16-2-10));
             end if;
             Delay_1 <= std_logic_vector (phaseaccu(16-1 downto 16-2));
             Delay_2 <= Delay_1;
          end if;
     end process INCREMENT;


     ADDRESSING: process (LUT_IN, Delay_2)
     begin
       case Delay_2 is
          when "00" => DDS_OUT <= LUT_IN;
          when "01" => DDS_OUT <= LUT_IN;
          when "10" => DDS_OUT <= std_logic_vector(2**10 - unsigned (LUT_IN));
          when "11" => DDS_OUT <= std_logic_vector(2**10 - unsigned (LUT_IN));
          when others => null;
       end case;
     end process ADDRESSING;

end;


Autor: name (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne jetzt deinen VHDL Code genau durch zu sehen, werfe ich mal das 
Stichwort Abtasttheorem in den Raum.
Vlt. ist die Anzhal der Werte im LUT zu gering?

Autor: Achim S (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

mein Vorredner hat völlig recht: du hast gerade mal noch vier 
Abtastwerte pro voller Sinusperiode. Da kann das Ausgangssignal nicht 
schöner aussehen, als das DDS_Out in deiner Simulation.

Ein analoger Tiefpass mit genau passender Grenzfrequenz könnte dir in 
der realen Schaltung vielleicht ein bisschen helfen. Aber wenn du einen 
"schönen" Sinus brauchst, wird dir nichts anderes übrigbleiben, als CLK 
deutlich schneller und dein Phaseninkrement dementsprechend deutlich 
kleiner zu machen.

schöne Grüße

Achim

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Achim und Name,

vielen Dank für eure Antwort und sorry das ich selbst erst so spät 
antworte, ich konnte nicht in I-Net (unangenehm).

Mich "stört" nicht, dass der Sinus bei hohen Phaseninkrementen so fies 
aussieht - damit rechne ich ja. Ich habe nur noch nie davon 
gehört/gelesen, dass bei anderen DDS Systemen (z.B. Analog Devices) eine 
kleine Anzahl an Abtastwerten zu einer >periodischen< Änderung der 
Amplitude und damit zu einer Amplitudenmodulation führen!

Ich könnte jetzt bspw. mit egal welchem TP Filter kein sauberes 60kHz 
Signal bei einer CLK Frequenz von 480kHz erzeugen. Eigentlich sollte das 
kein Problem sein, aber diese periodische Amplitudenmodulation führt zu 
Spektrallinien bei 60kHz +/- ca. 5 kHz! Vor allem die bei 55kHz kann ich 
nicht filtern.

Die Abtastwerte im LUT sollten mehr als genug sein. Falls Ihr noch eine 
Idee habt oder vielleicht sogar mal ein ähnliches oder gleiches Problem 
freue ich mich über jede Info.

Vielen Dank und ein schönen Sonntag,

Max

Autor: Eddy Current (chrisi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lies Dir mal ein Datenblatt eines DDS-Bausteins von Analog Devices 
durch. Oder schau Dir die Beschreibung hier an:

http://www.xilinx.com/support/documentation/ip_doc...

Letztlich erkennt man, dass genau Deine Beobachtungen der Grund dafür 
sind, warum die DDS eben auch nicht für alle Situationen geeignet ist.

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> dass bei anderen DDS Systemen (z.B. Analog Devices) eine
> kleine Anzahl an Abtastwerten zu einer >periodischen< Änderung der
> Amplitude und damit zu einer Amplitudenmodulation führen!

Doch. Genau deswegen wird da auf die letzten Bits der LUT-Adresse noch 
ein Rauschen addiert. Stichwort: Phase Dithered DDS

Vielleicht kannst Du Dir auch folgendes Paper besorgen: Spur-Reduced 
Digital Sinusoid Generation Using Higher-Order Phase Dithering 
[Flanagan/ Zimmerman]

Duke

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.