Hallo Ich beschäftige mich gerade etwas mit Signalverarbeitung in einem FPGA. Aktuell habe ich ein MA-Filter für FFT-Samples, welches über die Zeit die Werte etwas glätten soll. Die FFT hat die Ordnung 1024. Damit ich jetzt am Ausgang weiss, wann die korrekten Datan anliegen muss ich das eingehende Valid-Signal entsprechend der MA-Ordnung verzögern. Mittle ich schon nur über 4 Werte entspricht das einer Verzögerung von 4096 Takten. Zuerst dachte ich, ich verwende eine simple FF-Kette (oder einfach einen std_logic_vector der Länge 4096). Das ist aber nicht gerade platzsparend sowie ressourcensparend. Bei der Synthese lief ich immer in Timingprobleme. Der nächste Ansatz war eine SLR16 Implementiertung, welche ja in einer einzelnen LUT umgesetzt wird. Dies würde dann aber immer noch 256 LUTs beanspruchen. Was gibt es sonst noch für Möglichkeiten? Ich dachte da an einen Timer, der einfach auf 4096 hochzählt, aber so könnte ich nicht alle Informationen des eingehenden Valid-Signals ausgeben. Könnte man mit einer RLE etwas optimieren? Oder wie macht ihr das normalerweise? Gruss Patrick
du könntest z.B. jeweils 8 (oder 9) aufeinanderfolgende Valid-Flags zusammenfassen und das über ein Block-RAM FIFO verzögern. 4kbit passen da gut rein. Aber offen gesagt kapiere ich nicht, wieso dein MA-Filter (steht ja wohl für moving average, oder?) zu einer solchen Verzögerung führen soll. Ein Moving average filter besteht doch darin, dass bei jedem neuen Eingangswert dieses zur bisherigen Gesamtsumme addiert wird, und ein verzögertes Sample von der Gesamtsumme abgezogen wird. Die (skalierte) Gesamtsumme entspricht dem aktuellen MA-Wert. Mit jedem neuem Wert, das du in den MA-Filter reinschiebst, kommt also gleich (oder mit 1-2 Zyklen Latenz für Addition und Subtraktion) ein neuer Wert am Ausgang des Filters raus. Das valid-Flag am Filter-Eingang könnte also direkt (oder mit 1-2 Zyklen Latenz) als valid-Flag für den Filterausgang genutzt werden.
Das Filter mittelt nicht über die Frequenzbins sondern über die Zeit. Es werden also Sample 0 mit Sample 1024 mit Sample 2048... addiert. So verzögert sich die korrekte Ausgabe halt, bis Anzahl Mittelungen * NFFT durchgelaufen sind.
sorry, ich verstehs immer noch nicht. Nach meinem Verständis eines einfachen (gleichgewichteten) Moving Avergage Filter fällt immer dann hinten ein neuer Wert raus, sobald vorne ein neuer Wert reingeschoben wird (egal wie viele Takte Abstand zwischen dem Reinschieben der Werte vergeht). Bei jedem neuen Sample werden genau eine Addition und eine Subtraktion fällig (egal über wie viele Werte die Mittelung läuft). Aber wahrscheinlich kapier ich einfach nicht, wie bei dir der Datenfluss aussieht (bzw. die Implementierung deines Filters).
Ich habs mal versucht aufzuzeichnen. Mir leuchtet auch ein, dass mit jedem neuen hineingeschobenen Wert ein neuer rauskommt. Mein Problem besteht darin, die ersten paar Werte (die durch die Division/Schieben alle zu klein sind) zu verwerfen. Falls die Mittelung über 4 Frames geht, dann ist der erste korrekte Wert ja erst nach 4*NFFT am Ausgang (es wird ja jeweils 1/4 aufsummiert). Oder hast du einen komplett anderen Algorithmus?
Patrick B. schrieb: > Mir leuchtet auch ein, dass mit jedem neuen hineingeschobenen Wert ein > neuer rauskommt. Mein Problem besteht darin, die ersten paar Werte (die > durch die Division/Schieben alle zu klein sind) zu verwerfen. Ok, du willst also nur den "Einschwingvorgang" des Filters ausblenden? Reicht dafür nicht ein Zähler, der mitzählt, wie viele Werte du schon ins Filter reingeschoben hast? Und erst nach dem vollständige Auffüllen des Filters die Ausgabewerte weitergibt? Der Zähler darf nur hochzählen, wenn wirklich neue Werte ins Filter reinkommen, alsw wenn data_in_valid aktiv ist. Und eigentlich hast du diesen Zähler mit data_in_index doch wahrscheinlich bereits - am Schreibindex sollte sich doch der "Füllstand" des Filters ablesen lassen.
Solche Schieberegisterfreunde, die massenhaft LUTs verbraten, nur weil sie nicht in der Lage sind, zu zählen, werden in Fachkreisen üblicherweise ausgepeitscht! Im Ernst: Für sowas gibt es Zähler, die als pipeline-Marker agieren und von der Synthese passend zusammengefasst und vereinfacht werden können.
VHDL-Polizei schrieb im Beitrag #4576584: > Im Ernst: Für sowas gibt es Zähler, die als pipeline-Marker agieren und > von der Synthese passend zusammengefasst und vereinfacht werden können. Was soll da die Synhhese zusammenfassen resp. Vereinfachen können?
VHDL-Polizei schrieb im Beitrag #4576584: > Solche Schieberegisterfreunde, die massenhaft LUTs verbraten, nur weil > sie nicht in der Lage sind, zu zählen, werden in Fachkreisen > üblicherweise ausgepeitscht! > > Im Ernst: Für sowas gibt es Zähler, die als pipeline-Marker agieren und > von der Synthese passend zusammengefasst und vereinfacht werden können. Das mag ja stimmen, aber so wird nur das Startsignal verzögert. Falls aus irgend einem Grund nun das Valid-Signal zwischendurch für 2-3 Takte von 1 auf 0 wechselt und wieder zurück, kannst du das mit einem Zähler nie am Ausgang abbilden, oder wie sollte ich das lösen?
Patrick B. schrieb: > VHDL-Polizei schrieb im Beitrag #4576584: >> Solche Schieberegisterfreunde, die massenhaft LUTs verbraten, nur weil >> sie nicht in der Lage sind, zu zählen, werden in Fachkreisen >> üblicherweise ausgepeitscht! >> >> Im Ernst: Für sowas gibt es Zähler, die als pipeline-Marker agieren und >> von der Synthese passend zusammengefasst und vereinfacht werden können. > > Das mag ja stimmen, aber so wird nur das Startsignal verzögert. Falls > aus irgend einem Grund nun das Valid-Signal zwischendurch für 2-3 Takte > von 1 auf 0 wechselt und wieder zurück, kannst du das mit einem Zähler > nie am Ausgang abbilden, oder wie sollte ich das lösen? Mit einem Zähler wird das eigehende Signal nicht verzögert sondern neu generiert. Genaugenommen wird nicht das Signal neugeneriert sondern die jeweilige Flanke. Das kann in Abhängigkeit von der Verzögerungsdauer und anzahl der einlaufenden Flanken innerhalb der Verzögerung einiges an aktiver Hardware erfordern. Beispielsweise realisiert als Event-FF *taktcounter *adder *Fifo *comperator *OUT-FF Bei jedem bitwechsel am Eingang wird der wert des taktcounter plus der gewünschten Verzögerung und der Wert des Eingangbits in die FIFO geschrieben. ein Komperator vergleicht den FIFO -ausgang mit dem aktuellen wert des taktcounters und schaltet entsprechend das out-FF. Das braucht schon einiges an FF wenn man wirklich alle events weiterleiten will. Vorteile bringt das nur wenn man wenige events nachgeneriern muss und man muss mit dem nicht behabbaren fehler leben das die FIFO bei zu hoher event-last vollläuft und event verliert. Eine simple Schieberegister-kette dagegen verliert nie events, weil sie das Signal nicht nachgeneriert sondern 1:1 verzögert durchreicht. Ein unschätzbarer Vorteil für den es sich lohnen könnte einige der zehntausen Slices zu verbraten. bei externen events ist meist noch ein deglitcher dazwischen. dann baut man natürlich das verzögerte Signal mit einer delay-chainan den entsprechend geteilten Takt nach. das reduziert die Anzahl der FF auch gerne um den Faktor 1000. MfG,
Fpga K. schrieb: > Eine simple Schieberegister-kette dagegen verliert nie events, weil sie > das Signal nicht nachgeneriert sondern 1:1 verzögert durchreicht. Ein > unschätzbarer Vorteil für den es sich lohnen könnte einige der > zehntausen Slices zu verbraten. wenn es für die Anwendung nötig wäre, würde ich die Slices ja auch spendieren (bzw. ein paar wenige Slices plus ein Blockram, wodurch sich einfach eine 4k-Verzögerung mit geringem Resourcenverbrauch implementieren lässt). Aber der TO ist ja inzwischen selbst soweit, dass er nicht eine beliebige Eventfolge verzögern möchte, sondern nur ein einzelnes Event: nämlich wann der erste gültige Wert am Ausgang erscheint. Patrick B. schrieb: > Mir leuchtet auch ein, dass mit jedem neuen hineingeschobenen Wert ein > neuer rauskommt. Mein Problem besteht darin, die ersten paar Werte (die > durch die Division/Schieben alle zu klein sind) zu verwerfen. das geht leicht mit einem Zähler.
Fpga K. schrieb: > Mit einem Zähler wird das eigehende Signal nicht verzögert sondern neu > generiert. Richtig! Die Information wird im Zähler gespeichert, womit ständig alle FFs benutzt werden, statt immer nur 1 von n wie bei dieser "one hot" Geschichte. > Das kann in Abhängigkeit von der Verzögerungsdauer und > anzahl der einlaufenden Flanken innerhalb der Verzögerung einiges an > aktiver Hardware erfordern. ja, aber er schreibt: Patrick B. schrieb: > Der nächste Ansatz war eine SLR16 Implementiertung, welche ja in einer > einzelnen LUT umgesetzt wird. Dies würde dann aber immer noch 256 LUTs > beanspruchen. Damit ist ein lumpiger Zähler, der mit ein paar LUTs und Akku gebaut wird sicher erheblich kleiner. Der lohnt sich schon bei den typischen Verzögerungen, die eine Signalrechenkette mit z.B. CORDIC (Wurzel, Loga) hat. Die einzelnen Zähler der hintereinandergeschalteten Stufen werden dann in der Simulation schön aufgezeigt, purzeln aber bei der Synhese zu einem zusammen.
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.