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


von Max (Gast)


Angehängte Dateien:

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:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity DDS is
6
    port (
7
        RST      : in    std_logic;
8
        DDS_ON   : in    std_logic;
9
        ADDR_OUT : out   std_logic_vector(10 downto 0);
10
        LUT_IN   : in    std_logic_vector(8 downto 0);
11
        DDS_OUT  : out   std_logic_vector(8 downto 0);
12
        CLK      : in    std_logic
13
    );
14
end DDS;
15
16
architecture BEHAVE of DDS is
17
18
19
signal phaseaccu : unsigned(16-1 downto 0);
20
signal Delay_1: std_logic_vector(1 downto 0) := "00";
21
signal Delay_2: std_logic_vector(1 downto 0) := "00";
22
23
begin
24
25
     INCREMENT: process (CLK, RST)
26
     begin
27
          if RST = '1' then
28
             phaseaccu <= (others => '0');
29
             Delay_1 <= (others => '0');
30
             Delay_2 <= (others => '0');
31
          elsif CLK'event and CLK = '1' then
32
             if DDS_ON = '1' then phaseaccu <= phaseaccu+16000; end if;
33
             if (phaseaccu(16-1 downto 16-2) = "00") or (phaseaccu(16-1 downto 16-2) = "10") then
34
                ADDR_OUT <= std_logic_vector(phaseaccu(16-3 downto 16-2-10));
35
             else
36
                ADDR_OUT <= std_logic_vector(not phaseaccu(16-3 downto 16-2-10));
37
             end if;
38
             Delay_1 <= std_logic_vector (phaseaccu(16-1 downto 16-2));
39
             Delay_2 <= Delay_1;
40
          end if;
41
     end process INCREMENT;
42
43
44
     ADDRESSING: process (LUT_IN, Delay_2)
45
     begin
46
       case Delay_2 is
47
          when "00" => DDS_OUT <= LUT_IN;
48
          when "01" => DDS_OUT <= LUT_IN;
49
          when "10" => DDS_OUT <= std_logic_vector(2**10 - unsigned (LUT_IN));
50
          when "11" => DDS_OUT <= std_logic_vector(2**10 - unsigned (LUT_IN));
51
          when others => null;
52
       end case;
53
     end process ADDRESSING;
54
55
end;

von name (Gast)


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?

von Achim S (Gast)


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

von Max (Gast)


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

von Eddy C. (chrisi)


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_documentation/dds_ds558.pdf

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

von Duke Scarring (Gast)


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

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.