Forum: FPGA, VHDL & Co. DDS mit DE0-Nano Board nur niedrige Frequenzen?


von Atmega-Verleger (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich möchte auf Basis einer DDS mit meinem FPGA_Board (Tersic DE0-Nano)
zunächst ein Sinussignal von einigen 10kHz ausgeben. Später dann auch 
eine AM durchführen.
OK also ich nutze als DAC den PCM5142 siehe folgenden Beitrag:
Beitrag "SPI mit Atmega8 zu PCM5142 klappt nicht!"
die Kommunikation zum DAC läuft also und der läuft mit einer Abtastrate 
von
384kHz!
Die Audio-Daten werden auf dem FPGA-Board generiert.
- Bit-Clock (BCK), Left-Right-Clock (LRCK) generiere ich schon mal am 
FPGA board.
der Systemclock (SCK) 49,152MHz wird von einem diskreten Quarzoszillator 
in der Nähe des DAC generiert und dient auch für mein FPGA-Board als 
Eingangs-Takt (CLK).

Zur Generierung der Audiodaten verwende ich (im Angefügten VHD-Dokument) 
eine LUT mit 1920 Werten!
Ich kann somit theoretisch mit einer Schrittweite von 200Hz Frequenz 
unterhalb von fs/2 also 192kHz generieren.
delta_f= (fs/N), wobei N die Länge der zugrundeliegenden Sinustabelle 
ist!
Die besagte Sinustabelle lasse ich mir über ein eigenes, kleines 
MatLab-Script generierten und kopiere die Tabelle dann zunächst zu 
meinem VHDL-Code!

Zu den Prozessen:

"BCKGEN" : generiert den BCK für den PCM5142, sind 24,576MHz

"LRCKGEN" : generiert den LRCK für den PCM5142, sind 384kHz

"SEND": generiert die Audiodaten, d.h. es werden hier seriell Daten 
ausgegeben und nach einer gewissen Zeit (Anzahl von Bits) ein neuer Wert 
aus der Sinus LUT gelesen!

Anmerkung: Ich habe ursprünglich mit einer Variablen gearbeitet! Da ich 
von Timing-Problemen ausgegangen bin, habe ich das nun auf "nur" Signale 
umgestellt.

Die Schrittweite ("SINE_INDEX") ist hier gerade bei 12, d.h. die 
generierte Frequenz sollte doch bei 2,4kHz liegen?

ich konnte es auch am Oszi messen sind in der Tat 2,4kHz allerdings kann 
ich das Signal nicht "ordentlich" triggern! Es scheinen Phasensprünge 
aufzutreten!
Bei näherer Betrachtung des generierten Sinussignals kann man erkennen, 
dass zwischen 2 Werten des Sinus manchmal eine überlagernde 
"Dreieckspannung mit "steigender Flanke" zu sehen ist und manchmal mit 
fallender Flanke!
Werde sonst nachher mal die Oszillogramme hier posten!

Kann es sein, dass ich "nur ein Timing-Problem" bzgl. des Routings in 
der Quartus 2 Software habe oder ist da noch grundsätlich was falsch?
Habe schon mal verschiedene Sinus LUT verwendet, d.h. einmal auch mit 
halber, maximaler Amplitude--> ohne Erfolg?

von Atmega-Verleger (Gast)



Lesenswert?

Hier nun dazu ein paar Oszillogramme!
Die letzten beiden sollten eigentlich 3,2kHz sein.
Die davor alle 200Hz!

von Thomas R. (Firma: abaxor engineering) (abaxor)


Lesenswert?

Atmega-Verleger schrieb:
> Ich kann somit theoretisch mit einer Schrittweite von 200Hz Frequenz
> unterhalb von fs/2 also 192kHz generieren.

Was willst du uns damit sagen?

> Kann es sein, dass ich "nur ein Timing-Problem" bzgl. des Routings in
> der Quartus 2 Software habe
Wenn du Timing-Probleme hast, sagt das dir Quartus.

> oder ist da noch grundsätlich was falsch?
Das sagt dir die Simulation. Hast du dein Design simuliert?





Tom

von Atmega-Verleger (Gast)


Lesenswert?

Thomas Reinemann schrieb:
> Wenn du Timing-Probleme hast, sagt das dir Quartus.

Ja, weiss aber nicht wie ich die beheben kann?
Meldung:
Critical Warning (332148): Timing requirements not met
Wo kann ich da denn überhaupt rumspielen, um das zu beheben?

Thomas Reinemann schrieb:
> Das sagt dir die Simulation. Hast du dein Design simuliert?

Ja Modelsim lief drüber und habe meine Ausgangsdaten für mehrere 
"Schrittweiten" überprüft -> z.B. keine Phasensprünge am Ende des 
Tabellendurchlaufs!


Thomas Reinemann schrieb:
>> Ich kann somit theoretisch mit einer Schrittweite von 200Hz Frequenz
>> unterhalb von fs/2 also 192kHz generieren.
>
> Was willst du uns damit sagen?

Was meine Intention ist! mehr nicht!


Viele Grüße
AV

von Lattice User (Gast)


Lesenswert?

Was soll die -12 in dieser Zeile?
Wenn SINE_INDEX_OLD kleiner 12 ist, wird nicht korrekt auf die Tabelle 
zugefriefen.
1
           DIN(31 downto 0) <= sine_LUT(SINE_INDEX_OLD-12);

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Atmega-Verleger schrieb:
> Die besagte Sinustabelle lasse ich mir über ein eigenes, kleines
> MatLab-Script generierten und kopiere die Tabelle dann zunächst zu
> meinem VHDL-Code!
Hört sich umständlich an. VHDL kann auch rechnen. Siehe dort in der 
Mitte:
http://www.lothar-miller.de/s9y/archives/37-DDFS-mit-BROM.html

>>> Ich kann somit theoretisch mit einer Schrittweite von 200Hz Frequenz
>>> unterhalb von fs/2 also 192kHz generieren.
>> Was willst du uns damit sagen?
> Was meine Intention ist! mehr nicht!
So berechnet man die Frequenz des Ausgangssignals:
http://www.lothar-miller.de/s9y/archives/87-DDFS-Frequenz.html

Das gilt natürlich nicht mehr, wenn man sowas macht:
>   SINE_INDEX <= SINE_INDEX_OLD + 12;
Warum machst du so eine lange Tabelle und donnerst dann in 12er 
Schritten quer durch?


BTW: Warum schreibst du deine Kommentare auf "Englisch" in den Code?
>> -- changes needs some more signal... use of variables is futile!
Ich musste erst mal nachsehen, was futile bedeutet. Und dann kam raus: 
nutzlos, sinnlos, vergeblich, zwecklos, nichtig...
Aber: diese Adjektive treffen auf Variablen nicht zu!
Am ehesten würde noch mostly superfluous passen...  ;-)

von Thomas R. (Firma: abaxor engineering) (abaxor)


Lesenswert?

Atmega-Verleger schrieb:
> Thomas Reinemann schrieb:
>> Wenn du Timing-Probleme hast, sagt das dir Quartus.
>
> Ja, weiss aber nicht wie ich die beheben kann?
> Meldung:
> Critical Warning (332148): Timing requirements not met
> Wo kann ich da denn überhaupt rumspielen, um das zu beheben?
Dann musst du im Timing-Report nachsehen, welche Signale das Timing 
verletzten und bei diesen Pipeline-Stufen einbauen.

Aber wahrscheinlich wird dir diese Zeile Probleme bereiten:

DIN(31 downto 0) <= sine_LUT(SINE_INDEX_OLD-12);

Innerhalb eines Taktes muss ein Übertrag über 11 Bit laufen und dann 
müssen die elf Bit dekodiert werden, um den LUT-Eintrag zu lesen.

Teile es in zwei Zeilen innerhalb eines Prozesses auf, z.B:

s_lut_addr <= SINE_INDEX_OLD-12;
DIN(31 downto 0) <= sine_LUT(s_lut_addr);

Dann kommt dein Sinus-Wert zwar ein Takt später, aber bei deinen 
Frequenzen im Analogbereich, dürfte das kein Problem sein.


> Thomas Reinemann schrieb:
>> Das sagt dir die Simulation. Hast du dein Design simuliert?
>
> Ja Modelsim lief drüber und habe meine Ausgangsdaten für mehrere
> "Schrittweiten" überprüft -> z.B. keine Phasensprünge am Ende des
> Tabellendurchlaufs!
Das deutet auf ein Timing-Problem.


> Thomas Reinemann schrieb:
>>> Ich kann somit theoretisch mit einer Schrittweite von 200Hz Frequenz
>>> unterhalb von fs/2 also 192kHz generieren.
>>
>> Was willst du uns damit sagen?
>Was meine Intention ist! mehr nicht!
Ich habe aus dem Kauderwelsch deine Intention nicht verstanden, darum 
die Frage.

Tom

von Atmega-Verleger (Gast)


Lesenswert?

Lothar Miller schrieb:
> Hört sich umständlich an. VHDL kann auch rechnen. Siehe dort in der
> Mitte:
> http://www.lothar-miller.de/s9y/archives/37-DDFS-m...

so ich bin nun halbwegs dahinter gestiegen, wie Du Dir das mit deiner 
DDFS gedacht hast. Ein pi/2 Sinus zu verwenden ist ja schon mal gut 
aber, das mit dem Signal "Accum" ist mir nicht ganz klar:
Warum ist das genau 21Bit lang? Wie erhöhe ich dort denn die 
Schrittweite, also den Index aus der Sinustabelle "Rom64x8"?
Es wird dort ja nur mit
Accum <= Accum + unsigned(Freq_Data)
der hintere (LSB) Teil von Accum um Freq_Data erhöht, später jedoch
werden mit
z.B.
Accum(Accum'high-2 downto Accum'high-7) ... die Bits 18 bis 13 in 
"Address'" kopiert/zugewiesen! ?
Accum hat also lange Zeit bis diese Bit überhaupt von Freq_Data erhöht 
werden den Wert "0"!?
Den Bit 18 bis 13 bleiben ja durch das Accum <= Accum + 
unsigned(Freq_Data) lange Zeit unbeeinflusst?

von Lattice User (Gast)


Lesenswert?

Tutorial zur DDS:

http://www.analog.com/static/imported-files/tutorials/450968421DDS_Tutorial_rev12-2-99.pdf

Wird zwar immer wieder bezug auf (ältere) Analog Devices Bauteile 
genommen, ist aber trotzdem allgemein genug.

von Atmega-Verleger (Gast)


Lesenswert?

Atmega-Verleger schrieb:
> Accum(Accum'high-2 downto Accum'high-7) ... die Bits 18 bis 13 in
> "Address'" kopiert/zugewiesen! ?

Ok kann mein Problem nun besser umschreiben und habe es in Modelsim 
simuliert!
Das Signal "Accum" müsste also nur 8Bit lang sein ! So wird die 
Schrittweite, mit der der Viertelsinus durchlaufen wird um Freq_Data 
erhöht. Der maximale Wert (ohne Alias) wäre dann bei 31!
Die genierte Frequenz wäre dann (also in diesem Fall bei einer 64 
Elemente langen Liste!) bei (Freq_Data/64)*fs , wobei fs die 
Abtastfrequenz der Datenausgabe ist!
klingt das halbwegs plausibel?
Oder sehe ich da etwas noch nicht?


Änderung:

signal Accum : unsigned (20 downto 0) := (others=> '0');"
zu
signal Accum : unsigned (7 downto 0) := (others=> '0');"

von Atmega-Verleger (Gast)


Lesenswert?

Atmega-Verleger schrieb:
> Die genierte Frequenz wäre dann (also in diesem Fall bei einer 64
> Elemente langen Liste!) bei (Freq_Data/64)*fs , wobei fs die
> Abtastfrequenz der Datenausgabe ist!

Da wir ja von nem Viertelsinus ausgehen, müsste dann ja die Frequenz 
doch so berechnet werden:
(Freq_Data/(64*4))*fs
Die generierte Frequenz hängt ja von den Werten des "gedachten" vollen 
Sinuses ab! ?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Zeichne es einfach mal auf. Du kommst schon noch drauf. Es ist keine 
Raketentechnik. Als Anhaltspunkt: meine Formel stimmt.

Dabei ist es letzlich egal, ob ein Viertel oder Halbsinus oder ein 
ganzer Sinus betrachtet wird. Denn letzlich ist das nur eine andere 
Verwendung der beiden führenden Bits des Akkus (MSB=pos/neg, 
MSB-1=Tabellenzugriff "von vorn"/"von hinten"). Du solltest/kannst also 
für deine Betrachtungen von einem kompletten Sinus in der Tabelle 
ausgehen.

Ein kompletter Zyklus ist nach einmaligem Durchlaufen des kompletten 
Akkus erledigt. Die "unnötigen" Bits im Akku "vor" dem Tabellenindex 
sind einfach Vorteilerbits...

von Atmega-Verleger (Gast)


Lesenswert?

Lothar Miller schrieb:
> Dabei ist es letzlich egal, ob ein Viertel oder Halbsinus oder ein
> ganzer Sinus betrachtet wird. Denn letzlich ist das nur eine andere
> Verwendung der beiden führenden Bits des Akkus (MSB=pos/neg,
> MSB-1=Tabellenzugriff "von vorn"/"von hinten"). Du solltest/kannst also
> für deine Betrachtungen von einem kompletten Sinus in der Tabelle
> ausgehen.

Ja das stimmt schon und ist mir auch klar!

Also du hast aber einen ACCUM wie folgt:

x"0  0  0  0| 0  0  0  0| 0  0  0  0 |0 0 0 0|0 0 0 0| 0" 21 Bits
 20  19 18 17 16 15 14 13 12 11 10 9  8 7 6 5 4 3 2 1  0 Bitnummern
dann Freq_Data->x"0000|000|0"
Freq_Data wird zu ACCUM addiert also zu den Bits 7 bis 0!
in Address werden aber Bit 18 13 gespeichert!
Bit 19 ist in der Tat für die Unterscheidung, von welcher Seite die 
Tabelle
gelesen werden soll und Bit20 ist das eigentliche Vorzeichen-Bit!

Ich kann aber mit meiner Tabelle nur Frequenzen generieren, die wie 
folgt  berechnet werden (1/4*Tabellenlänge)*fs--> kleinste generierbare 
Frequenz! also jeder Wert einer Sinustabelle wird ausgegeben! bei der 
Viertelsinustabelle wird dann jeder Wert pro Ausgabesinus 4mal ausgegen 
(natürlich mit entsprechender Vorzeichen und Quadrantenanpassung) !!!!
So mein Gedanke!!!

Accum ist also zu lang! muss nur 8 Bit lang sein!

von Atmega-Verleger (Gast)


Lesenswert?

Lothar Miller schrieb:
> Ein kompletter Zyklus ist nach einmaligem Durchlaufen des kompletten
> Akkus erledigt. Die "unnötigen" Bits im Akku "vor" dem Tabellenindex
> sind einfach Vorteilerbits...

wozu so viele "vorteiler" bits?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Atmega-Verleger schrieb:
> wozu so viele "vorteiler" bits?
Damit man auch mit einer hohen Taktfrequenz (z.B. 50MHz) auf niedrige 
Ausgabefrequenzen (z.B. 2Hz) kommt. Und so auch auf kleine 
Frequenzschritte, wenn das Signal Freq_Data um 1 incrementiert wird...

von Atmega-Verleger (Gast)


Lesenswert?

Lothar Miller schrieb:
> Damit man auch mit einer hohen Taktfrequenz (z.B. 50MHz) auf niedrige
> Ausgabefrequenzen (z.B. 2Hz) kommt. Und so auch auf kleine
> Frequenzschritte, wenn das Signal Freq_Data um 1 incrementiert wird...

Dann (also Freq_Data = 1) dann würde auch immer ein "beträchtlicher" 
Anteil der Frequenz (1/(4*Tabellenlänge)*fs im Ausgangssignal vorhanden 
sein?
Entsprechendes Interpolationsfilter notwendig?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Atmega-Verleger schrieb:
> dann würde auch immer ein "beträchtlicher" Anteil der Frequenz
> (1/(4*Tabellenlänge)*fs im Ausgangssignal vorhanden sein?
"Störfrequenzen" kommen bei der DDFS von den "Stufen" des 
Digitalsignals. Du musst also nur die Schritte klein genug machen (und 
damit für die selbe Ausgangsfrequenz viel schneller durch die Tabelle 
laufen), dann verschwinden diese Frequenzen immmer weiter.
Aber bei einer 8 Bit ist dieser Störpegel schon 8*6dB = 48dB vom 
Nutzpegel entfernt. Und zudem ist die Störfrequenz um den Faktor 
"Tabellenlänge" (*1,*2 oder *4) höher als die Nutzfrequenz...

von Atmega-Verleger (Gast)


Lesenswert?

Lothar Miller schrieb:
> "Störfrequenzen" kommen bei der DDFS von den "Stufen" des
> Digitalsignals. Du musst also nur die Schritte klein genug machen (und
> damit für die selbe Ausgangsfrequenz viel schneller durch die Tabelle
> laufen), dann verschwinden diese Frequenzen immmer weiter.
> Aber bei einer 8 Bit ist dieser Störpegel schon 8*6dB = 48dB vom
> Nutzpegel entfernt. Und zudem ist die Störfrequenz um den Faktor
> "Tabellenlänge" (*1,*2 oder *4) höher als die Nutzfrequenz...

Ich hab mir mal das ganze umgemodelt auf 32 Bit und werde sollte ich
niedrigere Frequenzen ausgeben wollen eine längere Tabelle verwenden!
Zumindest als nächsten Schritt!

von Atmega-Verleger (Gast)


Angehängte Dateien:

Lesenswert?

Ok hab jetzt alles umgebaut und in Quartus 2 synthetisiert (vorher mit 
Modelsim simuliert)
irgendwie sehen die ausgegebenen Signale noch immer so aus!

Gibt es eine Möglichkeit, die Modelsim-Daten also die 32Bit-Werte in 
eine Datei zu leiten, um die dann grafisch darzustellen?
Ansonsten etwa doch Timing-Probleme zumindest sagt das die Quartus 2 
Software genauso wie beim vorherigen Versuch?

Mit Glück kann ich nächste Woche das mal auf 'nen Xilinx Spartan3 
testen!

von Atmega-Verleger (Gast)



Lesenswert?

Hallo,
hier nochmal die Oszillogramme zu meinen Versuchen, 3kHz bzw. 6kHz 
auszugeben!
Da stellt sich mir nun zwingend die Frage nach dem Datenexport bei 
Modelsim?

von Uli (Gast)


Lesenswert?

ja, gibt es: filereader funktion.

von Atmega-Verleger (Gast)


Lesenswert?

Uli schrieb:
> ja, gibt es: filereader funktion.

mal ausprobieren... morgen oder Montag!

von Atmega-Verleger (Gast)


Angehängte Dateien:

Lesenswert?

Atmega-Verleger schrieb:
> mal ausprobieren... morgen oder Montag!

So ich hab es jetzt mal ausprobiert (gestern + heute), also die 
Simulationsergebnisse aus dem Modelsim-List-File gelesen, in MatLab 
eingelesen und grafisch dargestellt!

Die Schrittweite (FREQ_DATA/FREQ_INC) ist in diesem Fall x"02"!
Somit ist das Modul "funktional" korrekt! ah, mir gehen die Optionen 
aus!
Als nächstes auf'm Spartan ausprobieren... sinnvoll?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Atmega-Verleger schrieb:
> Als nächstes auf'm Spartan ausprobieren... sinnvoll?
Wenn die Simulation sagt: "Alles ok", dann kannst du auf die Hardware 
gehen...

von Klaus (Gast)


Lesenswert?

Lothar Miller schrieb:
> Atmega-Verleger schrieb:
>> Als nächstes auf'm Spartan ausprobieren... sinnvoll?
> Wenn die Simulation sagt: "Alles ok", dann kannst du auf die Hardware
> gehen...

Und dann zuallererst das hier beheben, sonst kommt potentiell eh nur 
Mist raus:

Atmega-Verleger schrieb:
> Critical Warning (332148): Timing requirements not met

von Ale (Gast)


Lesenswert?

Witz:
Lothar's LUTs können 1920 Werte Speichern :)

von Atmega-Verleger (Gast)


Lesenswert?

Klaus schrieb:
> Und dann zuallererst das hier beheben, sonst kommt potentiell eh nur
> Mist raus:
>
> Atmega-Verleger schrieb:
>> Critical Warning (332148): Timing requirements not met

OK hab jetzt mal den TImeQuestTimingAnalyzer von Quartus 2 verwendet und 
dort meine Clocks angegeben d.h. CLK, BCK_OUT und LRCK_OUT mit der 
jeweiligen
Frequenz definiert und siehe da: nur noch eine "Critical Warning" aber 
eine böse!
1
Critical Warning (308042): (High) Rule C105: 
2
  Clock signal should be a gobal signal. (Value defined:25). 
3
  Found 1 node(s) related to this rule.
4
Critical Warning (308012): Node "CLK"

also ich soll das CLK auf "global" setzen weiss aber nicht wie..... 
angeblich
unter "Assignments -> Assignments Editor" ??

von Atmega-Verleger (Gast)


Lesenswert?

Atmega-Verleger schrieb:
> also ich soll das CLK auf "global" setzen weiss aber nicht wie.....
> angeblich
> unter "Assignments -> Assignments Editor" ??

Ok konnte meinen CLK nun als global festlegen---> keine kritischen 
Warnungen mehr!
Das allein hat nichts gebracht! Daher habe ich den Oszillator, der in 
der Nähe vom DAC platziert war direkt am FPGA Board angebaut, generiere 
den Takt dort direkt für das FPGA-Board..... der DAC bekommt dann sein 
CLK von nem anderen Ausgang des FPGA-Board "CLK_OUT".
Dachte, so könnte ich ein wenige gegen Verzögerungen zwischen den 
einzelnen CLKs wirken!
Leider ist das DAC Ausgangssignal immer noch "bescheiden"!!!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Atmega-Verleger schrieb:
> Leider ist das DAC Ausgangssignal immer noch "bescheiden"!!!
Lass einfach mal einen Zähler zählen und sieh dir dessen Bits an. 
Jittern die auch?

von ich (Gast)


Lesenswert?

Läuft dein Eingangstakt über eine PLL im FPGA?

von Atmega-Verleger (Gast)


Lesenswert?

Lothar Miller schrieb:
>> Leider ist das DAC Ausgangssignal immer noch "bescheiden"!!!
> Lass einfach mal einen Zähler zählen und sieh dir dessen Bits an.
> Jittern die auch?

Hab das größte Problem endlich gefunden!

Es lag am DAC "PCM5142"
Der hat intern Interpolationsfilter 8x und 16x
Einstellbar über Register 34 page 0.
Ich habe den Auf 16x gehabt!!! Nun mal auf 8x ausprobiert und nun läufts 
kann
nun auch Frequenzen im gewünschten Kilohertzbereich generieren!

Beste Grüße an dieser Stelle auch
and "Alfred Banause"

von Atmega-Verleger (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ich hab da nun mal ein Problem bzgl. des DDS(DDFS) Modulus von 
Lothar Miller!

Ich wollte das DDS Modul so anpassen, dass ich nicht nur "Listen" mit 
einer Länge einer Zweierpotenz anlegen muss!
Also ich wollte Listen mit einem Vielfachen der Abtastrate von 384kHz 
anlegen
also hier z.B.
7680 Werte daraus folgt dann eine pi/4-Liste mit 1920 Werten!

das folgende habe ich dann im Modul ergänzt/geändert:

   process begin
     wait until rising_edge(CLK);
     if BCK = '1' then
     ACCUM_TMP <= ACCUM;  -- Wert von ACCUM einen Takt lang speichern
     if (DIN_CNT = DIN_CNT_MAX-1) then
        QUADRANT <= "00";
        SIGN <= '0';
        if (ACCUM >=1920) then
          QUADRANT <= "01";
          SIGN <= '0';
        end if;
        if (ACCUM >= 3840) then
          QUADRANT <= "10";
          SIGN <= '1';
        end if;
        if (ACCUM >= 5760) then
          QUADRANT <= "11";
          SIGN <= '1';
        end if;
      end if;
    end if;
   end process;


   --QUADRANT <= ACCUM(ACCUM'left-1);
  process begin
   wait until rising_edge(CLK);
    case QUADRANT is
        when   "00" => ADDRESS <= ACCUM_TMP;  -- erster Quadrant
        when   "01" => ADDRESS <= 3840-ACCUM_TMP; -- zweiter Quadrant
        when   "10" => ADDRESS <= ACCUM_TMP-3840; -- dritter Quadrant
        when   "11" => ADDRESS <= 7680-ACCUM_TMP; -- vierter Quadrant
        when others => ADDRESS <= 0;
    end case;
  end process;

leider rechnet der nicht richtig!
ich laufe immer aus dem Indexbereich von 0... 1919 raus?
nutze hier nur noch integer!
Die Ausgabe also ob positiv oder negativ ist wie im original DDFS.vhd!

von J. S. (engineer) Benutzerseite


Lesenswert?

Nun ja, er tut, was Du hingeschrieben hast:

Die erste Bedingung (als default) ist ja auch immer erfüllt (1920). In C 
auf dem ARM wird das dann auch nicht anders laufen.

Entweder, Du schiebst sie nach hinten in die umgekehrte Reihenfolge oder 
formulierst alle Bedingungen so, dass sie vollständig exklusiv, also 
ohne logische Überlappung stehen, was ich ja immer empfehle:

    if (accu > a) and (accu <= b) then
elseif (accu > b) and (accu <= c) then
...

else
    -> habe_was_falsch_gemacht <= '1';

Sieh Dir mal meinen VGA_CORE hier in den Artikeln an. Da ist so eine Art 
DDS drin.

Was wird das eigentlich für eine APP: die 384kHz sehen mir sehr 
verdächtig aus :-)

von Atmega-Verleger (Gast)


Lesenswert?

Hmmh ich hab das jetzt wie unten angefügt aufgebaut!
Aber der läuft immer noch in den Index 2000! erreicht also den Fall für 
den zweiten Quadranten nicht rechtzeitig? ob wohl doch
"QUADRANT" und "ACCUM_TMP" zusammengehörig sein sollten, also beide 
Signale passen zum selben Takt?


  process begin
     wait until rising_edge(CLK);
     if BCK = '1' then
     ACCUM_TMP <= ACCUM;  -- Wert von ACCUM einen Takt lang speichern
     if (DIN_CNT = DIN_CNT_MAX-1) then
        if ((ACCUM >= 5760) and (ACCUM < 7680)) then
          QUADRANT <= "11";
          SIGN <= '1';
        elsif ((ACCUM >= 3840) and (ACCUM < 5760)) then
          QUADRANT <= "10";
          SIGN <= '1';
        elsif ((ACCUM >=1920) and (ACCUM < 3840)) then
          QUADRANT <= "01";
          SIGN <= '0';
        elsif ((ACCUM >= 0) and (ACCUM < 1920)) then
          QUADRANT <= "00";
          SIGN <= '0';
        else
          QUADRANT <= "01";
          SIGN <= '1';
        end if;
      end if;
    end if;
   end process;


   --QUADRANT <= ACCUM(ACCUM'left-1);
  process begin
   wait until rising_edge(CLK);
    case QUADRANT is
        when   "00" => ADDRESS <= ACCUM_TMP;  -- erster Quadrant
        when   "01" => ADDRESS <= 3840-ACCUM_TMP; -- zweiter Quadrant
        when   "10" => ADDRESS <= ACCUM_TMP-3840; -- dritter Quadrant
        when   "11" => ADDRESS <= 7680-ACCUM_TMP; -- vierter Quadrant
        when others => ADDRESS <= 0;
    end case;
  end process;

von Oli (Gast)


Lesenswert?

Wie gross ist denn das Inkrement? Ist das nur einen Takt zu spät, oder 
mehrere?

Zeige mal eine Simulation

von Atmega-Verleger (Gast)


Lesenswert?

Oli schrieb:
> Wie gross ist denn das Inkrement? Ist das nur einen Takt zu spät, oder
> mehrere?

Das Inkrement liegt bei "200"! un er sagt mir bei der Simu, dass 2000 
nicht im Bereich von 0 bis 1919 liegt! Eine wahre Aussage!
Das heißt aber auch, dass der nicht rechtzeitig in den "Fall" für den 
zweiten
Quadranten wechselt?

Oli schrieb:
> Zeige mal eine Simulation

Kann ich jetzt gerade nicht, sitze leider vor nem anderen Rechner... 
morgen!

von J. S. (engineer) Benutzerseite


Lesenswert?

Ohne vollständigen Code und Sim ist da herzlich wenig zu sagen, fürchte 
ich. Gfs liegt es an der "DIN_CNT = DIN_CNT_MAX-1" die die Bedingung in 
den Abfragen überspringt.

von Atmega-Verleger (Gast)


Lesenswert?

Jürgen S. schrieb:
> Ohne vollständigen Code und Sim ist da herzlich wenig zu sagen, fürchte
> ich. Gfs liegt es an der "DIN_CNT = DIN_CNT_MAX-1" die die Bedingung in
> den Abfragen überspringt.

Ah die Abfrage von QUADRANT mache ich ja in nem getakten Prozess mit 
CLK!
und QUADRANT bekommt zu der Bedingung DIN_CNT = DIN_CNT_MAX-1 neue Werte 
zugewiesen.
Hmmhh dann könnte das Problem ja auch daran liegen, dass ich auc die 
Abfrage
von QUADRANT zu der Bedingung "DIN_CNT = DIN_CNT_MAX" machen muss? oder
ich takte den Prozess zum Abfragen von QUADRANT gar nicht und packe 
QUADRANT in die Sensitivitätsliste?
Mal sehen heute abend mal ausprobieren und ggfs. poste ich mal mehr 
Code!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Atmega-Verleger schrieb:
> das folgende habe ich dann im Modul ergänzt/geändert:
Packe deine VHDL Beschreibungen zwischen die Token [ vhdl] und [ /vhdl] 
(ohne Leerzeichen, so wie im Screenshot mit den C-Quelltexten). Dann 
funktioniert das auch mit dem Syntax-Highlighting...

Atmega-Verleger schrieb:
> oder ich takte den Prozess zum Abfragen von QUADRANT gar nicht
> und packe QUADRANT in die Sensitivitätsliste?
Du fischst im Trüben...
Aber es ist tatsächlich so, dass deine unnötig getakteten Prozesse 
jeweils einen Takt Latency ins Spiel bringen.

Aber m.E. liegt das Problem etwa hier:
1
        if ((ACCUM >= 5760) and (ACCUM < 7680)) then
2
          QUADRANT <= "11";
3
          SIGN <= '1';
4
        elsif ((ACCUM >= 3840) and (ACCUM < 5760)) then
5
          QUADRANT <= "10";
6
          SIGN <= '1';
Eine DDFS sollte vorteilhafterweise so an den Binärgrenzen angelegt 
werden, dass ein solches Herumgewürge nicht nötig wäre...
Insbesondere, wenn du soweiso mit RIESENSCHRITTEN quer durchs RAM 
rennst:
> Das Inkrement liegt bei "200"!
Wozu hast du denn 1920 Stützstellen im Viertelkreis, wenn du nur 0,5% 
davon verwendest?

Atmega-Verleger schrieb:
> Mal sehen heute abend mal ausprobieren und ggfs. poste ich mal mehr
> Code!
Am besten den Ganzen...

von Atmega-Verleger (Gast)


Lesenswert?

Lothar Miller schrieb:
>> Das Inkrement liegt bei "200"!
> Wozu hast du denn 1920 Stützstellen im Viertelkreis, wenn du nur 0,5%
> davon verwendest?

Ich habe jetzt ein Inkrement von 200 will aber das Modul auch für andere 
Frequenzen verwenden, dafür muss das Inkrement dann aber höher bzw. 
niedriger sein!

Lothar Miller schrieb:
> Aber m.E. liegt das Problem etwa hier:
1
      if ((ACCUM >= 5760) and (ACCUM < 7680)) then
2
>           QUADRANT <= "11";
3
>           SIGN <= '1';
4
>         elsif ((ACCUM >= 3840) and (ACCUM < 5760)) then
5
>           QUADRANT <= "10";
6
>           SIGN <= '1';
> Eine DDFS sollte vorteilhafterweise so an den Binärgrenzen angelegt
> werden, dass ein solches Herumgewürge nicht nötig wäre...
> Insbesondere, wenn du soweiso mit RIESENSCHRITTEN quer durchs RAM
> rennst:

Und ja mir ist klar, dass es sonst besser wäre sich an Zweierpotenzen zu 
halten. Ich wollte aber Vielfache von 384 haben. Das ist die Abtastrate 
und so sind "ganzzahlige" Frequenzschritte möglich!

von Atmega-Verleger (Gast)


Lesenswert?

Ok zumindest hätte ich hier andere Grenzen setzen müssen:
1
  process begin
2
   wait until rising_edge(CLK);
3
    case QUADRANT is
4
        when   "00" => ADDRESS <= ACCUM_TMP;  -- erster Quadrant
5
        when   "01" => ADDRESS <= 3839-ACCUM_TMP; -- zweiter Quadrant
6
        when   "10" => ADDRESS <= ACCUM_TMP-3840; -- dritter Quadrant
7
        when   "11" => ADDRESS <= 7679-ACCUM_TMP; -- vierter Quadrant
8
        when others => ADDRESS <= 0;
9
    end case;
10
  end process;

also in Fall "01" 3839 statt 3840 und in
Fall "11" 7679 statt 7680

aber da das tatsächlich nur Probleme gibt werde ich doch wieder auf
ein System mit Zweierpotenzen wechseln. Die "kleine" Ungenauigkeit ist 
dann auch noch gut in Kauf zu nehmen!

von Mike (Gast)


Lesenswert?

Irgendwie ist mir nicht klar, wie Du mit 200er Schritten die Grenzen 
erreichen willst und wozu es dann einer 386er Teilung braucht.

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.