Hallo, ich verwende gerne Pyfda https://github.com/chipmuenk/pyfda zum Entwurf von Filtern. Aber ich habe ein Problem das ich nicht verstehe: Die Amplitude im Passband ist nicht gleich der Eingangsamplitude sondern oft deutlich niedriger, teilweise nur die Hälfte. Und das obwohl das Filter so entworfen wurde, dass das Signal dort nicht gedämpft wird. Mir ist klar, dass es im Passband oft Ripple gibt, aber eine Dämpfung im gesamten Passband finde ich seltsam. Aber vielleicht ist ja auch einer meiner Schritte falsch: Ich entwerfe das Filter wie im ersten Bildchen Filter_1. Dann stelle ich ein, dass die Koeffizienten Integers mit maximal 16 Bits sind. Also signed wie im Bildchen Filter_2. Seltsam ist, dass trotz der 16 Bits der maximale Wert der Koeffizienten hier bei nur 8192 liegt. Das ist 2**13 und etwas wenig. Der maximale positive Wert bei 16 Bit signed ist ja 2**15-1. Die Koeffizienten kopiere ich dann in das FIR Filter und bekomme eben als Ergebnis ein gefiltertes Signal mit deutlich reduzierter Amplitude im Passband. Wenn ich aber alle Koeffizienten so skaliere, dass sie die vollen 16 Bits ausnutzen ändert das nix an der Amplitude. Ist ja auch verständlich, denn es werden ja positive und negative Koeffizienten skaliert. Die gewichtete Summe bleibt also gleich. Aber wo kommt das her und wie schaffe ich es die Amplitude zu erhöhen? Klar könnte ich das Ergebnis, also das gefilterte Signal multiplizieren, aber dazu sehe ich keinen Grund wenn das Filter das ebenfalls können müsste.
Gustl B. schrieb: > Wenn ich aber alle Koeffizienten so skaliere, dass sie die vollen 16 > Bits ausnutzen ändert das nix an der Amplitude. Ist ja auch > verständlich, denn es werden ja positive und negative Koeffizienten > skaliert. Nein. Wenn Du die Koeffizienten skalierst muss die Amplitude mitgehen. Du hast wahrscheinlich Overflows bei den Zwischenwerten. Cheers Detlef
Nun, ich verwende das Filter von Xilinx. Da erwarte ich schon, dass das richtig funktioniert. Seltsam ist auch, dass das unterschiedlich aussieht wenn ich das in Pyfda oder im Xilinx Tool angucke. Bei dem Xilinx Tool verstehe ich die Achsenbeschriftung nicht. Also wo die den Nullpunkt der y-Achse hingelegt haben. Die Koeffizienten: 0,0,0,0,-2,-4,-5,0,15,32,34,0,-72,-143,-139,0,249,463,427,0,-713,-1306,- 1211,0,2290,5054,7318,8192,7318,5054,2290,0,-1211,-1306,-713,0,427,463,2 49,0,-139,-143,-72,0,34,32,15,0,-5,-4,-2,0,0,0,0 Es stimmt, doch, dass ich die Nullen am Anfang und am Ende weglassen kann oder? Detlef _. schrieb: > Nein. Wenn Du die Koeffizienten skalierst muss die Amplitude mitgehen. Das stimmt natürlich. Ich hatte nur den Fall betrachtet wenn die Summe der Koeffizienten Null ist. Dann ändert sich DC nicht wenn man die Koeffizienten skaliert. Aber für höhere Frequenzen ändert sich dann schon die Amplitude, das hatte ich nicht bedacht.
:
Bearbeitet durch User
Moin, Gustl B. schrieb: > Bei dem > Xilinx Tool verstehe ich die Achsenbeschriftung nicht. Also wo die den > Nullpunkt der y-Achse hingelegt haben. Summier' alle Koeffizienten mal auf, das ist ja dann das, was aus dem Filter rauskommt, wenn man es mit einem Einheitssprung, also sowas wie Gleichspannung, anregt. Das ist dann also die Zahl, die aus dem Filter mit jedem Takt rauskommt. Und wenn du diese Zahl logarithmierst und das dann x20 nimmst... Die Unterschiede im Sperrverhalten in den Diagrammen sehen so aus, als ob Xilinx mit den auf Bitaufloesung gerundeten Koeffizienten arbeitet und Pyfda mit Floatingpoint. Gruss WK
Dergute W. schrieb: > Summier' alle Koeffizienten mal auf 32766 Das ist also fast 2**15. Dergute W. schrieb: > Und wenn du diese Zahl logarithmierst 4.515423 Dergute W. schrieb: > und das dann x20 nimmst... 90.30846 Ja, fein. Das passt zu dem was mir das Xilinx Tool anzeigt. Aber wie ändere ich die Amplitude? Ich habe auch schon alle Koeffizienten mit 1,5 multipliziert. 0, 0, 0, 0, -3, -6, -7, 0, 22, 48, 51, 0, -108, -214, -208, 0, 373, 694, 640, 0, -1069, -1959, -1816, 0, 3435, 7581, 10977, 12288, 10977, 7581, 3435, 0, -1816, -1959, -1069, 0, 640, 694, 373, 0, -208, -214, -108, 0, 51, 48, 22, 0, -7, -6, -3, 0, 0, 0, 0 Dann sagt mir das Xilinx Tool und die selbe Rechnung wie oben 93.83. Aber die Amplitude in der Simulation ändert sich genau nicht.
Moin, Gustl B. schrieb: > Dann sagt mir das Xilinx Tool und die selbe Rechnung wie oben 93.83. > Aber die Amplitude in der Simulation ändert sich genau nicht. Die 93.83 passen ja zum Faktor 1.5. Warum das bei der Simulation nix aendert? keinen Blassen... Gruss WK
Gustl B. schrieb: > Nun, ich verwende das Filter von Xilinx. Da erwarte ich schon, dass das > richtig funktioniert. Sicher funktioniert das. Aber Du hast bei der Bedienung irgendeinen Fehler gemacht oder was mißverstanden. Jetzt gibs zwei Möglichkeiten: entweder fummelst Du Dich in die Xilinx tools rein und findest den Fehler oder Du bastelst selber nen FIR in Verilog oder VHDL zusammen. Mach Letzteres, weil dann hast Du nicht lediglich die tools verstanden sondern kannst FIR, egal in welcher Implementationssprache. So hab ich das gemacht, und FIR kann ich :))) Cheers Detlef
Detlef _. schrieb: > oder Du bastelst selber nen FIR in Verilog oder VHDL zusammen. Das hatte ich schon gemacht. Und zwar in mehreren Formen je nachdem was man will, wenig DSPs oder höhere Samplerate. Siehe Beitrag "FIR parallel und seriell braucht zu viele LUTs." Aber der Xilinx FIR Compiler IP der optimiert halt doch besser. Den würde ich gerne verwenden. Klar, kann ich machen und am Ende das Ergebnis passend skalieren, aber das sollte doch auch ohne so eine Skalierung funktionieren.
Hallo Gustl, bin gerade zufällig über diesen Thread hier gestolpert (nein, ich habe kein Ego-Googling gemacht ;-)). Ich bin der Hauptentwickler von pyFDA und wollte mich demnächst mit der Skalierung der Koeffizienten beschäftigen. Das ist noch verbesserungswürdig und daher wäre ich an Feedback interessiert. Ich habe mal eine kurze Fixpointsimulation mit dem Default-Equiripplefilter und 16 bit Koeffizienten gemacht. Bei der Sprungantwort ("Step") musste ich die Amplitude auf 0.9 reduzieren um Überläufe zu verhindern. Schick mir doch die Filterdaten wenn Du magst, dann kann ich mir das mal anschauen. Viele Grüße, Christian
Christian M. schrieb: > bin gerade zufällig über diesen Thread hier gestolpert Juhu wie fein! Deine Videoreihe habe ich mir vor einiger Zeit mal auf Youtube angeguckt, vielen Dank! Naja, eigentlich möchte ich mal FIR zu Fuß machen und das dann auch verstanden haben. Meine aktuelles Verständnis ist, dass das so geht: Ich habe ein Array mit Abtastwerten (ungefiltert), ich habe ein kürzeres Array mit Koeffizienten (koeffizienten). Jetzt schiebe ich schrittweise die Koeffizienten an den Abtastwerten entlang. Immer wenn ich die um einen Schritt geschoben habe, dann mache ich:
1 | gefiltert = [] |
2 | schieberegister = [0]*len(koeffizienten) |
3 | for i in range(0,len(ungefiltert)): |
4 | schieberegister.pop(0) |
5 | schieberegister.append(ungefiltert[i]) |
6 | summe = 0 |
7 | for j in range(0,len(koeffizienten)): |
8 | summe += koeffizienten[j] * schieberegister[j] |
9 | gefiltert.append(summe/len(koeffizienten)) |
Und meine Annahme ist, dass wenn das Filter im Durchlassbereich eine Dämpfung von 0 dB hat, dann bleibt die Amplitude so wie beim ungefilterten Eingangssignal. Jedoch sehe ich das nicht so wenn ich das zu Fuß hinschreibe. Koeffizienten (Bandpass, DEC, Integer, W=16) sind z. B.: koeffizienten = [0,-1,0,0,-2,-1,7,16,10,-13,-29,-20,3,7,-9,-5,38,75,43,-49,-106,-66,10,2 2,-25,-14,104,199,110,-120,-255,-157,23,50,-55,-31,227,431,236,-255,-537 ,-329,50,106,-115,-64,480,917,507,-554,-1189,-742,116,253,-285,-165,1325 ,2720,1654,-2040,-5186,-4153,988,5848,5848,988,-4153,-5186,-2040,1654,27 20,1325,-165,-285,253,116,-742,-1189,-554,507,917,480,-64,-115,106,50,-3 29,-537,-255,236,431,227,-31,-55,50,23,-157,-255,-120,110,199,104,-14,-2 5,22,10,-66,-106,-49,43,75,38,-5,-9,7,3,-20,-29,-13,10,16,7,-1,-2,0,0,-1 ,0] Was ich gerne sehen würde wäre ein sehr einfacher Code ohne eine fertige Bibliothek wie eben mein Code oben der einen FIR zu Fuß rechnet. Ich habe FIRs auch schon in VHDL geschrieben sowohl seriell als auch als Pipeline ( Beitrag "Re: zu blöd für 25 tap FIR auf FPGA" ) aber ich musste bisher das Ergebnis immer skalieren. Es reichte nicht die Summe durch die Anzahl der Koeffizienten zu teilen.
Moin, Gustl B. schrieb: > Was ich gerne sehen würde wäre ein sehr einfacher Code ohne eine fertige > Bibliothek wie eben mein Code oben der einen FIR zu Fuß rechnet. Sowas?
1 | /* compile with:
|
2 | gcc -Wall -O2 bla.c -lm
|
3 | */
|
4 | #include <stdio.h> |
5 | #include <stdlib.h> |
6 | #include <math.h> |
7 | |
8 | double sinc(double s) { |
9 | if (s) return sin(s)/s; |
10 | return 1.0; |
11 | }
|
12 | int fir(int n, double w, double * coeff) { |
13 | int i; |
14 | double x; |
15 | for (i=0; i<=n; i++) { |
16 | /* here happens the filter magic: */
|
17 | x = i-n/2.0; |
18 | x *= M_PI * w; |
19 | coeff[i] = sinc(x); |
20 | }
|
21 | return 0; |
22 | }
|
23 | int main(int argc, char* argv[]) { |
24 | int n = 6; |
25 | double w=0.5; |
26 | double * coeff; |
27 | double sum = 0.0; |
28 | int i; |
29 | if (argc < 3) printf("usage: %s n w\n using order n=%d, normalized cutoff freq. w=%g as default\n", argv[0],n,w); |
30 | if (argv[1]) { |
31 | n = atoi(argv[1]); |
32 | if (argv[2]) { |
33 | w = strtod(argv[2], NULL); |
34 | }
|
35 | }
|
36 | coeff = calloc((n+1),sizeof(double)); |
37 | if (!coeff) { |
38 | printf("phuc!\n"); |
39 | return -1; |
40 | }
|
41 | fir(n, w, coeff); |
42 | /* normalize + print coefficients */
|
43 | for (i=0;i<=n;i++) { |
44 | sum += coeff[i]; |
45 | }
|
46 | for (i=0;i<=n;i++) { |
47 | printf("%g\n",coeff[i]/sum); |
48 | }
|
49 | free(coeff); |
50 | return 0; |
51 | }
|
Gruss WK
Ne, nicht sowas. Das berechnet doch die Koeffizienten wenn ich das richtig verstanden habe und zwar als Double? Ich suche einen FIR Filter, also eine Funktion die eine unendliche Folge aus Abtastwerten nacheinander an festen Koeffizienten vorbeischiebt, multipliziert, summiert und je Schritt einen Ausgangswert ausgibt. Aber: - Mit ganzzahligen Koeffizienten und - die Amplitunde sollte stimmen. Mir ist mittlerweile klar, dass mein Problem durch die Verwendung von Integerkoeffizienten herkommt. Das möchte ich nicht ändern sondern weiterhin Integer verwenden. Ich will aber herausfinden wie ich einen Faktor berechne mit dem ich die Amplitude korrekt hinbekomme. Nach den Multiplikationen bilde ich die Summe. Und diese will ich mit einem Faktor skalieren damit die korrekte Amplitude herauskommt.
Moin, Axo. Die Funktion, die du suchst, heisst Faltung(convolution). Danach brauchst du noch eine Skalierung. Bei Tiefpaessen kriegst du den Faktor ueber die Summe der Koeffizienten. Bei anderen -paessen wirds etwas unangenehmer. Wahrscheinlich musst du dann die Koeffizienten noch mit einem cos() Signal mit 0/Mittenfrequenz/halben Abtastfrequenz multiplizieren, danach aufsummmieren fuer die Skalierung auf 1 bei 0/Mittenfrequenz/halbe Abtastfrequenz. Da emfehl' ich mal ein Grundlagenbuch fuer Signalverarbeitung, wo Faltung, Impulsantwort, etc. durchgekaut wird. Gruss WK
Dergute W. schrieb: > Die Funktion, die du suchst, heisst Faltung(convolution). Ja das ist die Multiplikation und Summenbildung. Das habe ich schon. Dergute W. schrieb: > Danach brauchst du noch eine Skalierung. Bei Tiefpaessen kriegst du den > Faktor ueber die Summe der Koeffizienten. Bei anderen -paessen wirds > etwas unangenehmer. Exakt darum geht es mir. Bisher mache ich das durch Probiererei. Ich würde das aber gerne rechnen. Dergute W. schrieb: > Da emfehl' ich mal ein Grundlagenbuch fuer Signalverarbeitung, wo > Faltung, Impulsantwort, etc. durchgekaut wird. Hm ... na gut, werde ich machen wenn ich Zeit habe. Ausprobieren ist bisher ein guter Kompromiss.
Eine große Schwierigkeit bei Fixpointfiltern ist immer die Skalierung: Bei einem Floating Point Tiefpass-FIR Filter sind die Koeffizienten normalerweise so ausgelegt, dass ein Gleichsignal (lauter "Einser") auch zu lauter "Einsern" am Ausgang führt (Verstärkung 1 bei DC). Beispiel: Moving Average Filter mit 4 Taps: Jeder Koeffizient ist b_i = 0.25, bei einem Gleichsignal erhält man am Ausgang 4 x 0.25 = 1. (Ja, in der Praxis skaliert man eher einmal am Ein- oder Ausgang mit 0.25 ...) Beim gleichen Filter in Fixpoint-Implementierung mit 8 Bit breiten Ein- und Ausgangssignalen muss ich zunächst mal ein Datenformat festlegen. Ich wähle Q0.7 mit einem Vorzeichenbit, 0 Vorkommabits und 7 Nachkommabits. Meine Koeffizienten wären dann z.B. b_i = 0.010_000_0, mein Eingangs-Gleichsignal z.B. eine Sequenz von 0.100_000_0 (entspricht 1/2). Ein Eingangswert 1.000_000_0 entspricht nicht +1 sondern -1 und wäre daher schon zu groß, mein Wertebereich ist -1 ... 1 - 1/128 (1.000_000_0 ... 0.111_111_1). Bei der Multiplikation wächst die Wortlänge (genau wie bei einer dezimalen Multiplikation) sowohl bei Vor- als auch bei Nachkommastellen: 23,45 x 67,89 = 1592,0205 Falls ich nur 4 Dezimalstellen zur Verfügung habe, muss ich Stellen nach der Multiplikation wegwerfen (mache ich das vorher, leidet die Genauigkeit). Da ich die Vorkommastellen ausgenutzt habe (keine Reserve), muss ich die Nachkommastellen fallen lassen bzw. runden. Genau das Gleiche muss ich auch bei meinem Fixpointfilter tun. Nach der Multiplikation habe ich 4 Teilprodukte mit jeweils 0.001_000_000_000 (entspricht 1/8) im Format Q0.14 (15 Bit) oder wenn ich ganz genau bin im Format Q1.14, da das Produkt -1 x -1 = +1 eine Extra-Vorkommastelle bräuchte. Addiere ich meine 4 Teilprodukte auf (dafür brauche ich in unserem Fall Addierer mit 14 Nachkommabit und 1 Vorkommabit, bei anderen Koeffizienten u.U. auch mehr Vorkommabits. Da ich am Ausgang nur 8 Bits zur Verfügung haben, muss ich wieder im Dezimalbeispiel Bits wegwerfen, wieder im Nachkommabereich. @Gustl B.: Wenn Du Dich jetzt fragst, was das mit Deinem Problem zu tun hat: Digitale Rechenwerke kennen kein Komma, für ein FPGA ist 0.111_111_1 das Gleiche wie 0111_111_1, das Komma ist nur in Deinem Kopf! Du musst in einem Fixpoint-Filter darauf achten, die Daten richtig zu kürzen und anzuordnen und ggf. zu verlängern (Sign Extension). Mein Kollege entwirft seine Digitalfilter lieber im Integerformat, ich komme besser mit dem Fractional Fixpoint Format klar. Auf dem FPGA sind die Filter aber gleich. Mehr Info: * http://www.digitalsignallabs.com/fir.pdf * https://github.com/chipmuenk/dsp/blob/main/notebooks/07_FIX/FIX_intro.ipynb (Jupyter Notebook) * https://github.com/chipmuenk/dsp/blob/main/docs/DSV_FPGA_Muenker_Skript.pdf (Kap. 6 zu Fixpointformaten und -filtern) Viel Spaß damit :->
Vielen Dank für die ausführliche Erklärung! Christian M. schrieb: > @Gustl B.: Wenn Du Dich jetzt fragst, was das mit Deinem Problem zu tun > hat: Digitale Rechenwerke kennen kein Komma, für ein FPGA ist > 0.111_111_1 das Gleiche wie 0111_111_1, das Komma ist nur in Deinem > Kopf! Das ist mir schon bekannt. Ich habe nur noch nicht verstanden wie ich ich darauf komme wie viele LSBs ich verwerfe. Wenn ich als Beispiel Abtastwerte mit 16 Bit habe und ein FIR Filter mit 64 Koeffizienten die ebenfalls 16 Bits haben, dann bekomme ich für die Summe: 16+16+6 = 38 Bits Damit ich wieder Ausgangswerte mit 16 Bit habe könnte ich einfach die 22 LSBs wegwerfen. Aber dann passt eben die Amplitude vom Filter nicht. Auch wenn ich das nicht von Hand schreibe sondern mit dem Xilinx FIR Wizard bauen lasse, dann stimmt die Amplitude nicht. Sie ist nicht irre weit daneben, aber doch etwas. Ich habe das jetzt mal mit dem Xilinx FIR in den Anhang gesteckt. Die Koeffizienten: koeffizienten = [-1,0,0,-2,-1,7,16,10,-13,-29,-20,3,7,-9,-5,38,75,43,-49,-106,-66,10,2 2,-25,-14,104,199,110,-120,-255,-157,23,50,-55,-31,227,431,236,-255,-537 ,-329,50,106,-115,-64,480,917,507,-554,-1189,-742,116,253,-285,-165,1325 ,2720,1654,-2040,-5186,-4153,988,5848,5848,988,-4153,-5186,-2040,1654,27 20,1325,-165,-285,253,116,-742,-1189,-554,507,917,480,-64,-115,106,50,-3 29,-537,-255,236,431,227,-31,-55,50,23,-157,-255,-120,110,199,104,-14,-2 5,22,10,-66,-106,-49,43,75,38,-5,-9,7,3,-20,-29,-13,10,16,7,-1,-2,0,0,-1 ] Vielen Dank für die Links! Die werde ich mir mal merken für ruhigere Zeiten.
Sorry, da hatte ich Deine Frage missverstanden. Leider kann man aus der Xilinx - Simulation nicht den Faktor ablesen, der Dir an der Ausgangsamplitude fehlt. Ich habe Dein Filter nachgebaut und ähnlich simuliert wie Du (seit Version 0.4 gibt es Chirp-Stimuli in pyfda). Du siehst kaum einen Unterschied zwischen Floating Point und Fixpoint Simulation (ich habe die Wortbreiten drastisch reduziert, damit man überhaupt etwas sieht). Das letzte Bild zeigt das Filter mit 13 Bit Wortbreite am Eingang, 8 Bit Wortbreite der Koeffizienten und 16 Bit am Ausgang (bis auf die Wortbreite am Ausgang alles ziemlich beliebig gewählt), hier sind alle Signale als "Integer Scale" dargestellt, die Amplitude am Ausgang ist ganz knapp noch innerhalb des Wertebereichs. Das Eingangssignal habe ich begrenzt ("sat"). Wenn Dein Ausgangssignal deutlich kleiner ist, ist wohl noch irgendwas mit Deiner Skalierung im Argen. Mit diesem Teil des Codes habe ich aber auch lange gekämpft, vielleicht hilft er Dir ja weiter: https://github.com/chipmuenk/pyfda/blob/7c8d90e6503d1c3169a09575f4b058133f15cf15/pyfda/fixpoint_widgets/fixpoint_helpers.py#L29 Viel Erfolg!
Christian M. schrieb: > Sorry, da hatte ich Deine Frage missverstanden. Leider kann man aus der > Xilinx - Simulation nicht den Faktor ablesen, der Dir an der > Ausgangsamplitude fehlt. Kein Problem. Was der Faktor ist habe ich auch nicht ausgerechnet. In dem Bildchen sind aber ungefiltert und gefiltert identisch skaliert. von -2**15 bis +2**15-1. Christian M. schrieb: > Ich habe Dein Filter nachgebaut und ähnlich > simuliert wie Du (seit Version 0.4 gibt es Chirp-Stimuli in pyfda). Du > siehst kaum einen Unterschied zwischen Floating Point und Fixpoint > Simulation (ich habe die Wortbreiten drastisch reduziert, damit man > überhaupt etwas sieht). Das letzte Bild zeigt das Filter mit 13 Bit > Wortbreite am Eingang, 8 Bit Wortbreite der Koeffizienten und 16 Bit am > Ausgang (bis auf die Wortbreite am Ausgang alles ziemlich beliebig > gewählt), hier sind alle Signale als "Integer Scale" dargestellt, die > Amplitude am Ausgang ist ganz knapp noch innerhalb des Wertebereichs. > Das Eingangssignal habe ich begrenzt ("sat"). Das sieht gut aus, war aber auch zu erwarten. Die Koeffizienten wurden mit pyfda berechnet und zeigen mir ja auch eine Dämpfung im Durchlassbereich von 0 dB an. Christian M. schrieb: > Wenn Dein Ausgangssignal > deutlich kleiner ist, ist wohl noch irgendwas mit Deiner Skalierung im > Argen. Der Witz ist, ich habe da nix skaliert. Ich habe im letzten Post den FIR Compiler von Xilinx verwendet und dort nur die Koeffizienten (Integer, W=16) aus pyfda hineinkopiert. Dann habe ich noch eingestellt, dass das Ausgangssignal 16 Bits signed seien soll und die LSBs verworfen werden. In der Testbench erzeuge ich einen 16 Bit signed full-scale Sinus Sweep. Und da kann ich jetzt beobachten, dass die Amplitude geringer ist als ich es erwarten würde. Klar könnte ich mir da jetzt den Faktor ausrechnen und das selber skalieren, mich würde aber mehr interessieren wieso die Amplitude nicht passt. Ist das ein Fehler von dem Xilinx FIR Compiler? Christian M. schrieb: > Mit diesem Teil des Codes habe ich aber auch lange gekämpft, vielleicht > hilft er Dir ja weiter: Werde ich mir mal angucken.
Es wäre schon interessant, um welchen Faktor die Antwort in Xilinx zu klein ist. Ich weiß nicht, was der FIR-Compiler macht, aber da die Multiplizierer je nach Xilinx FPGA 18x18 oder 18x25 Bits verarbeiten, könntest Du mal versuchen Deine Koeffizienten als 18 bit signed zu erzeugen. Ich habe lange nicht mehr mit dem FIR-Compiler gearbeitet (nach meinem letzten frustrierenden Projekt zusammen mit Studis habe ich Vivado vom Rechner geworfen und schaue mir gerade den Lattice Flow an), aber da gibt es bestimmt Optionen für die Skalierung.
Hm, ja ... jetzt habe ich in die Testbench mal das TextIO eingebaut und mir die gefilterten Werte schreiben lassen. Das Maximum hat den Wert 8434. Das ist also grob 1/4, aber etwas mehr als 1/4. Dann habe ich mir das mal in Python geschrieben und plotten lassen, da passt der Faktor 1/2**15 sehr gut. Für mich bleibt als Fazit, dass ich nicht verstehe was Xilinx da macht. Ich kann damit leben, muss die Ausgangsdaten aber eben manuell skalieren.
Faktor 4 würde gut zu meiner Idee passen, dass die Koeffizienten um 2 Bit zu kurz sind. Versuch doch mal, die Koeffizienten mit 18 Bit Wortlänge zu Xilinx zu exportieren.
Gemacht. Das Maximum liegt jetzt bei 66679. Ich habe Abtastwerte als 18 Bit erzeugt, Koeffizienten in 18 Bit und die gefilterten Daten als 18 Bit. Es bleibt also fast 2 als Faktor. 2 wäre aber zu viel, dann würde es clippen.
Das Kapitel "Coefficient Quantization" (S. 59 ff.) in https://www.xilinx.com/support/documentation/ip_documentation/fir_compiler/v7_2/pg149-fir-compiler.pdf schildert sehr ausführlich, was Xilinx mit den Koeffizienten anstellt. Ich wusste z.B. nicht, dass man inzwischen Koeffizienten auch fraktional angeben kann. Vielleicht ist die Option "Maximize Dynamic Range" was Du suchst. Und da Du schon so gut in dem ganzen Thema drinsteckst :-> - hast Du nicht Lust mich ein bisschen bei der pyFDA-Entwicklung zu unterstützen (oder jemand anders hier aus dem Forum)? Ich würde gerne als nächstes Fixpointsimulation und -synthese auf nMigen umstellen und auslagern nach https://github.com/chipmuenk/pyfixp und https://github.com/chipmuenk/dsp_nmigen . Da die Filter und Fixpointroutinen auch ohne pyfda einsetzbar sein sollen, muss man sich in diesen beiden Repos nicht mit der Komplexität (= gewachsenes Chaos) von pyfda herumschlagen. Auch Testen von z.B. generiertem Verilog-Code und Exportformaten für FIR-Koeffizienten würde mir (und der Community ;-) ) weiterhelfen.
Danke! Christian M. schrieb: > Ich wusste z.B. nicht, dass man inzwischen Koeffizienten auch fraktional > angeben kann. Das werde ich noch ausprobieren. Christian M. schrieb: > Vielleicht ist die Option "Maximize Dynamic Range" was Du > suchst. Habe ich schon probiert, ändert nichts. Christian M. schrieb: > Und da Du schon so gut in dem ganzen Thema drinsteckst :-> Vielen Dank, aber ich habe da leider nicht wirklich viel Wissen. Ich kann VHDL schreiben und habe so auch schon FIR Filter gebaut, sonst bin ich da ziemlicher Laie. Ich nutze aber sehr gerne pyfda und finde das ein wunderbar schön zu bedienendes nützliches Werkzeug. Danke dafür!
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.