Fehler in DDS?

Gast #1272114
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;
Angehängte Dateien:
Gast #1272335
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
Gast #1273577
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
Gast #1274328
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren