Hallo Zusammen, ich interessiere mich zu Zeit für Audiokompression und arbeite deshalb gerade an einer Diskreten Cosinus Transformation auf einem FPGA System. Das Problem ist, dass die Transformation und Rücktransformation "eigentlich" funktioniert, nur dass bei einem Testsignal wie z.B einem Sinus die Nullstellen nach des rücktransformierten Signales gegen inf und -inf ausschlagen. Siehe Bild1. Was ich bereits überprüft habe und funktioniert: - Mein Design für die Kommunikation mit dem WM8731 - Das erzeugen der verschieden Cosinus Wellen in der DCT und iDCT - Die Übertragung der Transformationsdaten von der DCT zur iDCT Verwendet wird ein Altera DE2-115 FPGA Board. Die Hintransformation benutzt die DCT-II und die Rücktransformation die DCT-III. Die Audiodaten werden über den integrierten WM8731 Audiochip eingelesen und ausgegeben. Das Audiosignal wird mit 44.1kHz abgetastet mit einer Auflösung von 16 Bit. Die DCT verwendet N = 256 Elemente. Das Design ist komplett gepipelined und verwendet ein zwei Buffer System am Eingang der DCT, zwischen DCT und iDCT und am Ende der iDCT, sodass z.B eingehenden Audiodaten während der Berechnung der DCT nicht verloren gehen. Die Cosinus Funktion ist mit einer LUT implementiert. Um Komplexität zu vermeiden, bildet die LUT eine ganze Periode des Cosinus ab. die Länge der LUT ist 512 Elemente. Das Design verwendet Festkomma zur Darstellung Rationaler Zahlen. Die Bitbreite der Festkommasignale beträgt immer 18 Bit, da die DSP Multiplizierer im FPGA auf 18 Bit ausgelegt sind. Es werden immer die niederwertigsten Nachkommastellen abgeschnitten, um das 18 Bit Format beizubehalten. Der WM8731 benötigt einen Takt von 11.2896MHz und die DCT und iDCT wird mit einer Frequenz von 28MHz betrieben. Beide Clocks werden durch eine PLL erzeugt. Das beobachte verhalten tritt leider nicht in der Simulation auf. Das lässt, denke ich, eigentlich nur auf Timingprobleme schließen. Bild1: Die Abbildung zeigt die Rücktransformation eines Spektrums, dass mit einem Logic Analysier während des Betriebes vom FPGA gesammelt wurde und dann mit der Matlab idct() Funktion rücktransformiert wurde. Bild2: Das ist das Spektrum, welches während des Betriebes gesammelt wurde. Bild3: Die Abbildung zeigt das rücktransformierte Audiosignal mit einem Oszilloskop aufgenommen. Bild4: Auszug aus der Simulation. Die Ausschläge in Audio_out treten an den Grenzen des 256 Elemente Buffer der DCT auf und sind nicht das Problem, was ich versuche zu beheben. Die Werte in Bild1 und Bild2 sind nicht richtig Skaliert, weil diese Signale eigentlich im Festkommaformat sind, der Logic Analyser aber nur std_logic_vector kennt. Ich habe jetzt erst einmal noch nicht die VHDL Dateien angehangen. Falls es dazu Fragen oder Bedarf gibt, kann ich gerne Auszüge oder auch gleich die ganzen Dateien anbieten. Ich freue mich über jeden Impuls oder Tipp, was vielleicht die Ursache dieses Verhaltens sein könnte :) Viele Grüße und Danke im Voraus Anselm D.
Anselm D. schrieb: > ... Um Komplexität zu > vermeiden, bildet die LUT eine ganze Periode des Cosinus ab. die Länge > der LUT ist 512 Elemente. Skaliere deren Werte doch einmal. Nicht das die 1.0 da ueberlaeuft.
Anselm D. schrieb: > Ich habe jetzt erst einmal noch nicht die VHDL Dateien angehangen. Falls > es dazu Fragen oder Bedarf gibt, kann ich gerne Auszüge oder auch gleich > die ganzen Dateien anbieten. Her damit!
Anselm D. schrieb: > Die > Audiodaten werden über den integrierten WM8731 Audiochip eingelesen und > ausgegeben. Bist Du sicher, das das richtig funktioniert? Ich würde mal testweise einen Sägezahn bzw. ein Dreiecksignal ausgeben, um zu schauen, ob es dort an der 'Nullstelle' auch zu Problemen kommt. Außerdem würde ich empfehlen noch einen Debug-RAM anzuflanschen, um zu schauen ob die Daten der Berechnung plausibel sind.
Motopick schrieb: > Nicht das die 1.0 da ueberlaeuft. Die Werte der LUT und mein eingehendes Audiosignales speichere ich als sfixed(0 downto -17). Tatsächlich hatte ich das Problem, dass der synthetisierter rumgemeckert hat, weil er "1.0" nicht in diesem Format darstellen kann. Was ja auch Sinn macht wegen des asymmetrischen Zahlenraumes im 2er Komplement. Deshalb habe ich die "1.0" in der LUT durch "0.9999..." ersetzt. Analog dazu kann die "-1.0" ja in diesem Zahlenraum abgebildet werden und deshalb habe ich diese nicht mit "-0.9999..." angenähert.
Gustl B. schrieb: > Her damit! Hier einmal das archivierte Quartus Projekt und einmal die VHDL Dateien als ZIP. die Top Level Entity ist Audio_Visualizer_lite. Ein paar Anmerkungen zu dem Projekt: - Die Quartusversion ist 23.1std.0 Build 991 11/28/2023 Patches 0.02std SC Lite Edition. In der Version gab es einen Bug mit der Erzeugung von PLLs. Den Patch dazu hatte ich installiert. - Da ich nicht die Pro Version von Quartus habe, ist das ieee Fixpoint package nicht verfügbar. Deshalb verwende ich den Workaround dieses git Repositorys : https://github.com/LockBall/floatfixlib_VHDL1993 - Ich verwende zum speichern der Eingangsdaten, der Transformation und der Rücktransformation keine Signal Arrays sondern einen Double Buffer Dual Port RAM, da ich große Probleme mit langen Synthetisierzeiten hatte und da mir langsam der Platz auf dem FPGA ausgegangen ist. Diese Sachen konnte ich damit beheben. - der Dual Port RAM ist ein IP Core und verwendet kein Register am Ausgang und hat separate Clocks für Lesen und Schreiben. - Das Design beruht auf der Annahme, dass die Berechnung der DCT und iDCT sehr viel schneller ist, als das 256 neue Eingangsdaten gesammelt werden. Sobald die DCT oder iDCT mit der Berechnung fertig ist, warten diese darauf, dass der vorangehende Double Buffer RAM getauscht wird. Dieser wird immer getauscht, sobald 256 neue Daten geschrieben wurden. Außer der Double Buffer RAM am Ende der iDCT. Der wird immer getauscht, sobald 256 Daten gelesen wurden. - Die Anzahl der Bit vor und nach dem Komma jedes Signales der DCT und iDCT ist in dem Package "Custom_types.vhd" hinterlegt. Die Anzahl der Bit vor dem Komma ist genannt N und nach dem Komma ist genannt M. Vor den Konstanten ist der Rechenweg für dieses Signal beschrieben und wie ich auf die Anzahl der Bit vor dem Komma komme. - Durch die Pipeline sind die ganzen Rechenschritte etwas schleierhaft in der DCT oder iDCT. Falls das nicht verständlich ist, kann ich da gerne auch noch detailliert drauf eingehen.
Rick D. schrieb: > Ich würde mal testweise einen Sägezahn bzw. ein Dreiecksignal ausgeben, > um zu schauen, ob es dort an der 'Nullstelle' auch zu Problemen kommt. Hier sind einmal Aufnahmen mit Rechteck, Sägezahn, Dreieck und noch einmal Sinus als Eingangssignal. Was mir dabei auffällt ist, dass je nachdem ob das Signal gerade steigt oder fällt, diese Ausschläge in die selbe Richtung gehen. Also wenn das Signal gerade fällt, ist der Ausschlag ins Negative und wenn das Signal steigt, ist der Ausschlag ins Positive. Ich weiß noch nicht wie ein Debug Ram funktioniert aber ich werde mir das einmal anschauen :D
Ohne das ich jetzt in das Projekt hineingesehen haette, koenntest du dein Werk mit Signaltap an den kritischen Stellen "instrumentieren". Dazu muss man nicht die gesamte Signalbreite nehmen. In der Regel reichen die oberen 5 - 8 Bit aus, um Fehler in den Algorithmen zu erkennen. Und auch wenn der Synthesizer bei den "0.999..." nicht mehr mault, den in der LUT hinterlegten Wert noch einmal pruefen. Oder ihn gleich als Bitvektor hinschreiben. Es waere ja zu einfach gewesen, wenn das der Fehler gewesen waere. :) Viel Erfolg!
Anselm D. schrieb: > Deshalb habe ich die "1.0" in der LUT durch "0.9999..." ersetzt. Wie viele Neunen nach dem Komma genau? Eine Dezimalstelle entspricht gut 3,3 Bit. Setze doch einfach diese eine Zahl binär auf alles Eins bis auf das Vorzeichen (Name'left => '0', others => '1').
Da sind noch mehr "Grausamkeiten" drin, bspw. der Sinus wechselt schon mal die Richtung bevor er die Wendestellen erreicht. (siehe Anhang, aus Bild1.png durch Skalierung und Farbreduktion) Kan natürlich auch ein Problem der graphischen Darstellung sein, check mal die Roh-Werte. Eventuell dem Integer mehr Genauigkeit spendieren. Das Zahlenformat mal dahingehend überprüfen wie das Vorzeichenhandling bei der Null ist. Da scheint es eine Code für "+0" und einen für "-0" zu geben, es sollte aber nur einen geben. (kann aber auch ein Problem der graphischen Darstellung sein, welche Rohwerte stehen dort). Der Simulations-Auszug(?) (bild4.png) zeigt auch üble Artefakte nicht nur an den Nullstellen, vielleicht eher Runden statt abschneiden bei der Bitlängenreduktion ? also 001 -> 0 ... 001 -> 0 ; 010 -> 1 011 -> 1 ? BTW: Was ist der Unterschied zwischen den beiden Graphen in Bild4.png? Der obere sieht OK aus, der untere ist "grausam".
:
Bearbeitet durch User
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.