mikrocontroller.net

Forum: FPGA, VHDL & Co. DDS Compiler und Phase Increment


Autor: Hans-Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Kurt Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Hans-Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Kurt Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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).

Autor: Hans-Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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

Autor: Kurt Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
component dds_test1
   port ( ce      : IN  std_logic;
          clk     : IN  std_logic;
          rdy     : OUT std_logic;
          sine    : OUT std_logic_vector(11 downto 0));
end component;

   dds_block: dds_test1
      port map(
      ce => sample_clk,
      clk => system_clk,
      rdy => da_new_data_trig,
      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.

Autor: Hans-Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ?

Autor: Hans-Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kurt,

meintes du es vielleicht so ?

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


entity adc_out is
  port (
      clock     : in std_logic;   -- 50 MHz Clock
      SPI_SCK    : out std_logic;
      SPI_MOSI   : out std_logic;
      DAC_CLR    : out std_logic;
      DAC_CS      : out std_logic;
      led         : out std_logic_vector(7 downto 0)
      );
end entity adc_out;

architecture rtl of adc_out is
  
  -- Der Core soll einen Sinus mit 1 MHz erzeugen
  component Sinuscore
  port 
  (
        ce: IN std_logic;
        clk: IN std_logic;
        rdy: OUT std_logic;
        sine: OUT std_logic_vector(11 downto 0)
  );
  end component;
    
  type dacStateType is (idle, sendBit, clockHigh, csHigh);
  signal dacState   : dacStateType;
  signal clock_enable     : std_logic;
  signal ready : std_logic;
  
  signal sine_out  : std_logic_vector(11 downto 0);
  -- 24 Bit Format
  signal dacCounter : integer range 0 to 23;
  signal DAC_OUT    : std_logic_vector(23 downto 0);
  
  constant teiler : positive := 1;
  signal zaehler : integer range 0 to teiler := 0;
  type states is (one, two);
  signal state : states;
   signal takt : std_logic;
begin

  sine_wave_label : Sinuscore
  port map
  (
    ce => takt,
    clk => clock,   -- 50 MHz Clock
    rdy => ready,
    sine => sine_out
  );
  
  ----------------------------------------------------------------------------------------
  
  leds : process (clock)
  begin
    if rising_edge(clock)
    then  
      led(7 downto 2) <= "000000";  
      led(1) <= clock_enable;
      led(0) <= ready;    
    end if;
  end process;
  
  ----------------------------------------------------------------------------------------
  
  -- Bei 1 MHz sollte ein Sampletakt von 50 MHz möglich sein
    -- Hier 50 Mhz des Boards durch 2
   Sampletakt : process (clock)
   begin
    if rising_edge(clock)
    then
      case state is
        when one =>    if zaehler < teiler
                  then 
                    takt <= '0';
                    zaehler <= zaehler + 1;
                  else
                    state <= two;
                  end if;
        when two =>     takt <= '1';
                  zaehler <= 0;
                  state <= one;
                
      end case;
      end if;
    end process;
   
   
  process(clock, ready)
   begin
     if rising_edge(clock) 
    then
        -- Daten an den ADC senden
        case dacState is
           when idle =>
                   if ready = '1'
                then
                  DAC_CS <= '0';
                  SPI_SCK <= '0';              
                  -- dacCounter <= 31;
                  dacCounter <= 23;
                  -- 32 Bit Format 
                  -- 8Bit Dont care & Command & Address & Output & 4Bit Dont care                        
                  -- DAC_OUT <= "00000000" & "0010" & "1111" & output & "0000";
                  -- 24 Bit Format
                  -- Sinus auf DAC Channel A
                  DAC_OUT <= "0011" & "0000" & sine_out & "0000";                
                  dacState <= sendBit;
                end if;
           when sendBit =>
               
              SPI_SCK <= '0';
              -- SPI_MOSI <= DAC_OUT(31);
              SPI_MOSI <= DAC_OUT(23);
              -- DAC_OUT <= DAC_OUT(30 downto 0) & "0";
              DAC_OUT <= DAC_OUT(22 downto 0) & "0";
              dacState <= clockHigh;
           when clockHigh =>
              SPI_SCK <= '1';
              if dacCounter = 0 
              then
                dacState <= csHigh;
              else
                dacCounter <= dacCounter - 1;
                dacState <= sendBit;
              end if;
           when csHigh =>
              -- Digital-Analog-Wandlung
              DAC_CS <= '1';          
              dacState <= idle;             
        end case;
      
    end if; -- if rising_edge
  end process;
    
  DAC_CLR <= '1';
  
end architecture rtl;

Autor: Kurt Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

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.