Forum: FPGA, VHDL & Co. Effizentes Moving Average Filter


von Patrick B. (p51d)


Lesenswert?

Hallo

Ich habe wiedereinmal eine kleine Knobelaufgabe von der Schule bekommen, 
bei der ich mir etwas weitere Gedanken gemacht habe:
Ein Moving Average Filter ist eigentlich relativ simpel. Man kann die 
klassische FIR Struktur nehmen, Koeffizienten auf 1 setzen (also 
Multiplikatoren weg) und schon hat man den MA Filter.

Wie wird das nun umgesetzt, wenn über grössere Datenpunkte (z.B. 50) 
gemittelt werden soll? Da werden 50 Addierer fällig, deren Busbreite 
sich jedesmal um 1 Bit erhöht und somit deren Latenz (Busbreite am 
Ausgang = x+49).
Ich habe dann in diesem Forum die einfache Beschreibung "Summe - 
ältester Wert + neuer Wert und ein FIFO" gefunden. Von mir aus gesehen 
funktioniert das doch nur, solange die Addierer maximal 1 Takt 
Verzögerung haben, und selbst dann nicht (Addierer und Subtrahierer je 1 
Takt Verzögerung ergibt was komplett schräges).

Und ein IIR Filter könnte beim Sprung von 0-1 das gleiche Verhalten 
aufzeigen, wie ein FIR. Aber bei 1 auf 0 ist es spiegelverkehrt...

Tja, Theorie und Praxis sind irgendwie nie das selbe

Gruss
Patrick

von Nobody (Gast)


Lesenswert?


von Couka R. (Gast)


Lesenswert?

Junge, junge... Was ist das denn für eine Schule? Da will ich auch hin 
:D

lg, couka

von Patrick B. (p51d)


Lesenswert?

Couka R. schrieb:
> Junge, junge... Was ist das denn für eine Schule? Da will ich auch hin
> :D

Mhm, das habe ich selber auch schon gemerkt. Irgendwie werden nur 
minimale Elemente vermittelt, aber nicht wirklich das nötige.

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


Lesenswert?

Patrick B. schrieb:
> Ich habe dann in diesem Forum die einfache Beschreibung "Summe -
> ältester Wert + neuer Wert und ein FIFO" gefunden. Von mir aus gesehen
> funktioniert das doch nur, solange die Addierer maximal 1 Takt
> Verzögerung haben, und selbst dann nicht
Ich denke, du hast das nicht zu Ende gedacht. Oder andersrum: eher 
werden 2 Addierer fertig als 49...

BTW: nimm als Speicherlänge eine Zweierpotenz. Das macht die Verwaltung 
einfacher.

: Bearbeitet durch Moderator
von Stefan K. (stefan64)


Lesenswert?

Patrick B. schrieb:
> Wie wird das nun umgesetzt, wenn über grössere Datenpunkte (z.B. 50)
> gemittelt werden soll? Da werden 50 Addierer fällig, deren Busbreite
> sich jedesmal um 1 Bit erhöht und somit deren Latenz (Busbreite am
> Ausgang = x+49).

Wie kommst Du darauf? Das Summenergebnis ist maximal 50* des maximalen 
Datenwerts, also muss die Addition mit max. 6 Bit mehr als die Bitbreite 
eines Datenworts gerechnet werden.

In de Praxis addierst Du den neuen Datenwert und subtrahierst den 
letzten, das wars.

Gruß, Stefan

von voltwide (Gast)


Lesenswert?

So isses!

von J. S. (engineer) Benutzerseite


Lesenswert?

Vielleicht sollte man noch den Tipp geben, dass man die Summe permanent 
neu bildet, indem man das Addieren sofort mit dem ersten Wert beginnt, 
das Abziehen des alten Wertes aber erst zeitrichtig nach einer Anzahl 
von Delays startet, sodass das Filter hochlaufen kann.

Siehe diese Grafik aus dem parallelen Thread zum Filtern (grüne Kurve).
Beitrag "Re: MEMS Ultraschallmikro mit PDM"

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


Lesenswert?

Patrick B. schrieb:
> Und ein IIR Filter könnte beim Sprung von 0-1 das gleiche Verhalten
> aufzeigen, wie ein FIR. Aber bei 1 auf 0 ist es spiegelverkehrt...
Und wo legst du da die Spiegelachse an?
Was ist an einem 0-1 Sprung verglichen mit einem 1-0 Sprung so 
grundlegend anders, dass sich ein Filter einmal gleich und einmal ganz 
anders verhält?

Jürgen S. schrieb:
> Vielleicht sollte man noch den Tipp geben, dass man die Summe permanent
> neu bildet, indem man das Addieren sofort mit dem ersten Wert beginnt,
> das Abziehen des alten Wertes aber erst zeitrichtig nach einer Anzahl
> von Delays startet, sodass das Filter hochlaufen kann.
Wenn der Speicher vorher mit dem "Neutralwert" (z.B. 0) initialisiert 
wird, muss hier keine Ausnahme gemacht werden. Denn wenn 50 Takte lang 0 
abgezogen wird, ist das gerade so, als ob man da ein Delay einbaut.
Wenn man natürlich den Speicher erst noch initialiseren müsste (nicht 
initialisierbares RAM), dann zählt man tatsächlich leichter mit, bis der 
Fifo durch ist.

von Patrick B. (p51d)


Lesenswert?

Lothar M. schrieb:
> Und wo legst du da die Spiegelachse an?
> Was ist an einem 0-1 Sprung verglichen mit einem 1-0 Sprung so
> grundlegend anders, dass sich ein Filter einmal gleich und einmal ganz
> anders verhält?

Wenn am Eingang ein Rechteckimpuls ankommt, bilded das IIR Filter am 
Ausgang eine "Welle" (ähnlich Kondensatorladekurve), währenddessend das 
FIR einen Dreieck generiert (wie bei der Faltung, da die Koeffizienten 
ja alle 1/n sind). Das Filter kann sich ja nie gleich verhalten... 
Vieleicht habe ich mich hier unklar ausgedrückt.


Das CIC Filter ist ziemlich interessant und funktioniert bei meiner 
Simulink-Simulation auch bestens. Jetzt kommt aber die grosse 
Preisfrage: Wenn nun der Addierer beim Integrator mehr Takte benötigt 
(z.B. 5), wird doch die Summe nicht mehr korrekt gebildet. Und somit 
funktioniert das CIC Filter nicht mehr wie gewünscht. Als ich in einem 
Buch etwas über das Filter nachgelesen habe, wurde das Feedback-Register 
durch eine Pipelinestufe im Integrator-Differentiator Pfad ersetzt (ist 
auch so nachvollziebar), aber was ist wenn die Daten breiter als 48 Bit 
für DSP Slices werden?

Beim Differentiator (Subtraktion) sehe ich keine Probleme, da hier keine 
Rekursion passiert.

: Bearbeitet durch User
von Achim S. (Gast)


Lesenswert?

Patrick B. schrieb:
> aber was ist wenn die Daten breiter als 48 Bit
> für DSP Slices werden?

eine Eigenschaft des CIC ist, dass ein Überlauf des Integrators 
überhaupt nichts ausmacht - das Endergebnis ist immer noch richtig. Das 
lässt sich aber nicht so ganz einfach sehen - man muss sich tief in die 
Literatur einlesen, oder es einfach glauben.

Es geht dir immer noch um die Mittelung bei deiner FFT, mit der du schon 
seit einigen Wochen beschäftigt bist, richtig? Ich fürchte, du gehst die 
Sache immer noch komplizierter an als nötig.

Du bekommst die Daten in Paketen von 1024 Samples (hast also sogzusagen 
1024 "Kanäle", die du filtern willst). Und du möchtest für jeden Kanal 
einen Moving Average über jeweils 4 Samples.

Dann brauchst du insgesamt nicht mehr als:
- einen Speicher für die aktuellen Summen: 1024 Adressen mit Bitbreite 
(n+2) (n ist die Bitbreite deiner Samples, die zwei Zusatzbits brauchst 
du wegen der Addition über 4 Werte). Dieser Speicher kann als Blockram 
oder über Register implementiert werden, je nachdem, was für die weitere 
Verwendung der Daten sinnvoller ist.
- einen Speicher für die "verzögerten" Samples, die du von der jeweils 
aktuellen Summe wieder abziehst. Dieser Speicher braucht 1024*4=4069 
Adressen und eine Bitbreite von n. Der Einsatz eines oder zweier 
BlockRAMs bietet sich an. Eventuell macht eine Ausführung als dual 
ported RAM dir die Sache einfacher, im selben Takt an einem Port das 
neue Sample einzuspeichern (um es zu verzögern) und am anderen Port das 
verzögerte Sample auszulesen (um es von der aktuellen Summe abzuziehen.
- eventuell brauchst du noch einen Speicher, um den Datenstrom von 
deiner Quelle zu deinem Filter anzugleichen. Aber wenn die Datenquelle 
die FFT ist, brauchst du das nicht: aus der FFT purzeln die einzelnen 
Werte ja der Reihe nach raus und können mit minimaler Latenz in dein 
Filter reingeschoben werden.
- wenn nicht in jedem Takt valide Samples ankommen, dann brauchst du 
noch ein kurzes Schieberegister, das das data-valid von der Datenquelle 
entsprechend der Latenz des Filters verzögert. Aber da geht es nicht um 
tausende von Takte (wie du in einem früheren Beitrag vermutet hast) 
sondern lediglich um eine Handvoll Takte. (Denn jedes mal wenn du ein 
neues Sample ins Filte reinschiebst kommt nach wenigen Takte ein neues 
valides Ergebnis aus dem Filter raus)

Also: dein Moving Average sollte mit einigen Blockrams, einer 
Additonsstufe und einer Subtraktionsstufe erschlagen sein.

von Patrick B. (p51d)


Lesenswert?

Achim S. schrieb:
> Es geht dir immer noch um die Mittelung bei deiner FFT, mit der du schon
> seit einigen Wochen beschäftigt bist, richtig?

Fast, damals wollte ich über die Frames mitteln. Jetzt soll der Einfluss 
des Rauschens in normaler Richtung (also über die Frequenzbins) 
vermindert werden. Hier gestaltet sich das Filter viel einfacher, da 
keine Verzögerung um NFFT notwendig ist.

von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Sollte man bei dieser Anzahl von beitragenden Elementen (50!) nicht 
vielleicht doch darüber nachdenken, einen ordnetliches FIR zu machen?

von Achim S. (Gast)


Lesenswert?

Patrick B. schrieb:
> Fast, damals wollte ich über die Frames mitteln. Jetzt soll der Einfluss
> des Rauschens in normaler Richtung

Ups, dann entschuldige, dass ich nicht richtig gelesen habe bevor ich 
meinen Senf dazugegeben habe ;-)

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.