Ich habe mittels des Core Generators von Xilinx ISE 10.1 einen DDS Core erzeugt. Mit folgenden Einstellungen: Frequency Resolution 10 kHz, Spurious Suppression 72dB bzw. 12bit Ausgangsbreite, Clock 300 MHz, Phase Increment Fixed, Phase Offset None. Die 300 MHz sollen auf dem Spartan 3 AN Starter Kit mittels eines DCM Cores erzeugt werden. Maximal sind 330 MHz möglich. Wie bestimmt sich der Wert für den Phasen Increment bei der Festlegung Fixed ? Im Menü des DDS Compilers wird der Wert 8000 Hex angegeben. Die automatisch erzeugt vdl-Datei (Wrapper) beinhaltet auch diesen Wert. Die Festlegung des Phasen Increments muß anscheinend durch nachträgliche Änderung in der Wrapper-Datei erfolgen. Für eine Ausgabefrequenz von 1 MHz ergibt sich ein Phasen Increment von 13,653. Lässt sich dieses nur ganzzahlig festlegen also 13 oder 14 ? Wenn ja, ergäbe sich eine grosse Abweichung gegenüber der gewünschten Frequenz. In der Beschreibung des DDS Cores findet sich folgender Satz: "Based on the Core customization parameters, the DDS core will automatically employ quarter-wave symmetry when appropriate1." Unter welchen Umständen wird die Symmetrie ausgenutzt ? Auch die Programmierung des Phase Increments und des Phase Offsets ist mir noch nicht klar. Werde die Beschreibung weiter durchforsten.
Der D/A-Wandler läuft? Dann hast du sicherlich einen Sample-Takt von 1 bis 2 MHz. Folgende DDS-Konfiguration wird fürs erste funktionieren: System Clock 1 MHz (bzw. dein Sample-Takt) SFDR 70 dB --> 12 Bit Frq. Resolution 0.4 Hz Phase Inkrement fixed Phase Offset none Output Frequency Ch 1 0.1 MHz Auf Seite 4 brauchst du ein Clock Enable und das RDY Das wars. Nun hast du zwei Eingänge CLK und CE. An CLK legst du 50 MHz oder 100 MHz oder was du auch immer für einen Systemtakt hast (300 MHz sind nicht sinnvoll). An CE legst du den Sampletakt (s.o.), der aber immer nur für eine einzige Systemtaktperiode aktiv sein darf. Als Ausgang bekommst du 12 Bit die zur State-Machine des D/A-Wandlers als Daten hingehen. Das RDY benutzt du, um den Zustandsautomaten zu triggern, damit ein neuer Ausgabezyklus beginnt, es ist auch immer nur für eine Systemtaktperiode aktiv. Wenn alles klappt, bekommst du dann einen 100 kHz Sinus aus dem D/A-Wandler. Viel Erfolg!
Hallo Kurt, vielen Dank für die schnelle Antwort. >> System Clock 1 MHz (bzw. dein Sample-Takt) Warum 1 Mhz ? Hatte gedacht das je schneller die Clockfrequenz, desto höher die Ausgangsfrequenz. Je schneller, desto besser. >> Frq. Resolution 0.4 Hz Warum das ? Ist glaube ist der niedrigste Wert den man angeben kann. >> Phase Inkrement fixed Programmierbar wäre doch schöner. Laut Beschreibung A MSB = 0 für Phasen Increment und A MSB = 1 für Phasen Offset. Und die niedrigsten vier Bit für den Kanal. Wert über Data.
>Warum 1 Mhz ? Die 1 MHz deswegen, weil du nicht mehr Werte erzeugen musst, als du ausgeben kannst, ich spiele auf deinen D/A-Wandler an. Die Frequenzauflösung bestimmt die Bitbreite des Phasenakkumulators. Angenommen du hättest ein FTW von 0x66666, dann würde 0x66667 eine um nicht mehr als 0,4 Hz höhere Frequenz erzeugen, also fein aufgelöst. Bei 10 kHz Auflösung kannst du die Frequenz nur sehr grob einstellen. >Programmierbar wäre doch schöner. Das wäre die nächste Baustelle auf der anderen Seite des DDS-Cores, dazu brauchst du etwas, das dir die Frequenztuningworte generiert bzw. ausrechnet (Mikrocontroller).
>Warum 1 Mhz ? Die 1 MHz deswegen, weil du nicht mehr Werte erzeugen musst, als du ausgeben kannst, ich spiele auf deinen D/A-Wandler an. Ich denke der DA-Wandler kann, laut Datenblatt, 50 MHz verkraften. Soweit verstanden bezieht sich das auf die einzelnen Bits des 24 Bit bzw. 32 Bit Datenwortes an den DA-Wandler. Wie schnell jeweils die 24 Bits mit dem 12 Bit DA-Wert angelegt werden können, habe ich noch nicht herausgefunden. >Programmierbar wäre doch schöner. Das wäre die nächste Baustelle auf der anderen Seite des DDS-Cores, dazu brauchst du etwas, das dir die Frequenztuningworte generiert bzw. ausrechnet (Mikrocontroller). Also allein mit dem FPGA kann ich nur einen fixen Phasen Offset und ein fixes Phasen Increment angeben ? Das lässt sich nicht mittels VHDL verändern ? Das bedeutet ich bin an eine feste Ausgangsfrequenz gebunden. Was muß dann da gerechnet werden ? Beispielsweise a*b/c ? Die Frequenzauflösung bestimmt die Bitbreite des Phasenakkumulators. Angenommen du hättest ein FTW von 0x66666, dann würde 0x66667 eine um nicht mehr als 0,4 Hz höhere Frequenz erzeugen, also fein aufgelöst. FTW ??? Bei 10 kHz Auflösung kannst du die Frequenz nur sehr grob einstellen. Die Frequenz ergibt sich doch aus dem Phasen Increment. Wie du zuvor erklärt hast lässt das Phasen Increment nicht verändern, also wie kann ich diese dann einstellen ? Ich verstehe das als Widerspruch oder was ist hier mit "einstellen" gemeint ? Und zu guter letzt. Wie verwende ich jetzt die vom Core Generator erzeugte Sinuscore.vhd Datei für die Synthese ? Simulieren funktioniert. VHDL Text in eine eigene Datei kopieren oder irgendwie anders einbinden ? Der Wrapper wird unter Implementation nicht angezeigt. Beim Versuch die Datei zum Projekt hinzuzufügen erhalte ich die Fehlermeldung das diese schon im Projekt enthalten ist. Da die Datei nicht aufgeführt wird, kann ich doch auch nicht die Synthese durchführen. Schon mal im voraus: Vielen Dank für Deine Hilfe
Hans-Werner, der Grundgedanke meines Vorschlags war, den DDS-Core und den D/A-Wandler erstmal in einfachster Konfiguration und mit wenigen, überschaubaren Problemen (mit einer festen Frequenz) zum laufen zu bringen. Das Verständnis für die Funktion und wie man das dann erweitert, kommt dann fast von selbst. >Wie schnell jeweils die 24 Bits mit dem 12 Bit DA-Wert angelegt >werden können, habe ich noch nicht herausgefunden. Das ist der springende Punkt: 50 MHz / 24 ist rund 2 MHz. >Also allein mit dem FPGA kann ich nur einen fixen Phasen Offset und ein >fixes Phasen Increment angeben ? Das lässt sich nicht mittels VHDL >verändern ? Das bedeutet ich bin an eine feste Ausgangsfrequenz >gebunden. Was muß dann da gerechnet werden ? Beispielsweise a*b/c ? Da musst du nochmal lesen, wie DDS geht, aber s.o. >FTW ??? FTW heisst Frequency Tuning Word, ich glaube nur ein anderer Ausdruck für das Phasen-Inkrement. >Die Frequenz ergibt sich doch aus dem Phasen Increment. Wie du zuvor >erklärt hast lässt das Phasen Increment nicht verändern, also wie kann >ich diese dann einstellen ? Ich verstehe das als Widerspruch oder was >ist hier mit "einstellen" gemeint ? Einstellen vorerst mit dem Core-Generator durch Angabe der festen Frequenz. >Und zu guter letzt. Wie verwende ich jetzt die vom Core Generator >erzeugte Sinuscore.vhd Datei für die Synthese ? Gar nicht. Nimm die XCO-Datei. Rechte Maustaste in dein Projekt, "Add Source" und die vom Core-Generator erzeugte XCO-Datei wählen. Deine oberste VHD-Datei sollte folgendes in ähnlicher Form enthalten, schau dir dazu auch die VHO-Datei an:
1 | component dds_test1 |
2 | port ( ce : IN std_logic; |
3 | clk : IN std_logic; |
4 | rdy : OUT std_logic; |
5 | sine : OUT std_logic_vector(11 downto 0)); |
6 | end component; |
7 | |
8 | dds_block: dds_test1 |
9 | port map( |
10 | ce => sample_clk, |
11 | clk => system_clk, |
12 | rdy => da_new_data_trig, |
13 | sine => da_data); |
Vorschlag für den nächsten Schritt: Erzeuge einen Takt von 1 MHz und gib mit diesem Takt abwechselnd 000h und fffh an den Zustandsautomaten des D/A-Wandlers aus. Erst wenn das klappt, ist die Einbindung des DDS-Cores sinnvoll.
Als Ausgang bekommst du 12 Bit die zur State-Machine des D/A-Wandlers als Daten hingehen. Das RDY benutzt du, um den Zustandsautomaten zu triggern, damit ein neuer Ausgabezyklus beginnt, es ist auch immer nur für eine Systemtaktperiode aktiv. Wenn alles klappt, bekommst du dann einen 100 kHz Sinus aus dem D/A-Wandler. Ein etwas verschliffener Rechteck lässt sich erzeugen. Also das RDY in die Sensitivitätsliste des Prozesses mit dem Zustandsautomaten für die DA-Konvertierung ? An CE legst du den Sampletakt (s.o.), der aber immer nur für eine einzige Systemtaktperiode aktiv sein darf. Also einen eigenen Prozess für den Sampletakt parallel zum Zustandsautomaten der DA-Konvertierung ? Der Sampletakt kann also unabhängig von dem Takt des Zustandsautomaten gewählt werden ?
Hallo Kurt, meintes du es vielleicht so ?
1 | library ieee; |
2 | use ieee.std_logic_1164.all; |
3 | use ieee.numeric_std.all; |
4 | |
5 | |
6 | entity adc_out is |
7 | port ( |
8 | clock : in std_logic; -- 50 MHz Clock |
9 | SPI_SCK : out std_logic; |
10 | SPI_MOSI : out std_logic; |
11 | DAC_CLR : out std_logic; |
12 | DAC_CS : out std_logic; |
13 | led : out std_logic_vector(7 downto 0) |
14 | );
|
15 | end entity adc_out; |
16 | |
17 | architecture rtl of adc_out is |
18 | |
19 | -- Der Core soll einen Sinus mit 1 MHz erzeugen
|
20 | component Sinuscore |
21 | port
|
22 | (
|
23 | ce: IN std_logic; |
24 | clk: IN std_logic; |
25 | rdy: OUT std_logic; |
26 | sine: OUT std_logic_vector(11 downto 0) |
27 | );
|
28 | end component; |
29 | |
30 | type dacStateType is (idle, sendBit, clockHigh, csHigh); |
31 | signal dacState : dacStateType; |
32 | signal clock_enable : std_logic; |
33 | signal ready : std_logic; |
34 | |
35 | signal sine_out : std_logic_vector(11 downto 0); |
36 | -- 24 Bit Format
|
37 | signal dacCounter : integer range 0 to 23; |
38 | signal DAC_OUT : std_logic_vector(23 downto 0); |
39 | |
40 | constant teiler : positive := 1; |
41 | signal zaehler : integer range 0 to teiler := 0; |
42 | type states is (one, two); |
43 | signal state : states; |
44 | signal takt : std_logic; |
45 | begin
|
46 | |
47 | sine_wave_label : Sinuscore |
48 | port map |
49 | (
|
50 | ce => takt, |
51 | clk => clock, -- 50 MHz Clock |
52 | rdy => ready, |
53 | sine => sine_out |
54 | );
|
55 | |
56 | ----------------------------------------------------------------------------------------
|
57 | |
58 | leds : process (clock) |
59 | begin
|
60 | if rising_edge(clock) |
61 | then
|
62 | led(7 downto 2) <= "000000"; |
63 | led(1) <= clock_enable; |
64 | led(0) <= ready; |
65 | end if; |
66 | end process; |
67 | |
68 | ----------------------------------------------------------------------------------------
|
69 | |
70 | -- Bei 1 MHz sollte ein Sampletakt von 50 MHz möglich sein
|
71 | -- Hier 50 Mhz des Boards durch 2
|
72 | Sampletakt : process (clock) |
73 | begin
|
74 | if rising_edge(clock) |
75 | then
|
76 | case state is |
77 | when one => if zaehler < teiler |
78 | then
|
79 | takt <= '0'; |
80 | zaehler <= zaehler + 1; |
81 | else
|
82 | state <= two; |
83 | end if; |
84 | when two => takt <= '1'; |
85 | zaehler <= 0; |
86 | state <= one; |
87 | |
88 | end case; |
89 | end if; |
90 | end process; |
91 | |
92 | |
93 | process(clock, ready) |
94 | begin
|
95 | if rising_edge(clock) |
96 | then
|
97 | -- Daten an den ADC senden
|
98 | case dacState is |
99 | when idle => |
100 | if ready = '1' |
101 | then
|
102 | DAC_CS <= '0'; |
103 | SPI_SCK <= '0'; |
104 | -- dacCounter <= 31;
|
105 | dacCounter <= 23; |
106 | -- 32 Bit Format
|
107 | -- 8Bit Dont care & Command & Address & Output & 4Bit Dont care
|
108 | -- DAC_OUT <= "00000000" & "0010" & "1111" & output & "0000";
|
109 | -- 24 Bit Format
|
110 | -- Sinus auf DAC Channel A
|
111 | DAC_OUT <= "0011" & "0000" & sine_out & "0000"; |
112 | dacState <= sendBit; |
113 | end if; |
114 | when sendBit => |
115 | |
116 | SPI_SCK <= '0'; |
117 | -- SPI_MOSI <= DAC_OUT(31);
|
118 | SPI_MOSI <= DAC_OUT(23); |
119 | -- DAC_OUT <= DAC_OUT(30 downto 0) & "0";
|
120 | DAC_OUT <= DAC_OUT(22 downto 0) & "0"; |
121 | dacState <= clockHigh; |
122 | when clockHigh => |
123 | SPI_SCK <= '1'; |
124 | if dacCounter = 0 |
125 | then
|
126 | dacState <= csHigh; |
127 | else
|
128 | dacCounter <= dacCounter - 1; |
129 | dacState <= sendBit; |
130 | end if; |
131 | when csHigh => |
132 | -- Digital-Analog-Wandlung
|
133 | DAC_CS <= '1'; |
134 | dacState <= idle; |
135 | end case; |
136 | |
137 | end if; -- if rising_edge |
138 | end process; |
139 | |
140 | DAC_CLR <= '1'; |
141 | |
142 | end architecture rtl; |
Setze teiler vorerst auf 50 und generiere den DDS-Core für eine Frequenz von nicht mehr als 100 kHz mit Sampletakt von 1 MHz. Nähere dich der maximal möglichen Frequenz von unten und nicht von oben, das ist übersichtlicher. Das ready gehört m.E. nicht in die Sensitivitätsliste (getakteter Prozess). Experimentiere etwas mit dem Wert für teiler, der Wert 50 setzt voraus, der Zustandsautomat für den D/A-Wandler in 50 Takten abgelaufen ist.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.