Forum: FPGA, VHDL & Co. Grosse Verzögerung von Valid-Signalen


von Patrick B. (p51d)


Lesenswert?

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

von Achim S. (Gast)


Lesenswert?

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.

von Patrick B. (p51d)


Lesenswert?

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.

von Achim S. (Gast)


Lesenswert?

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).

von Patrick B. (p51d)


Angehängte Dateien:

Lesenswert?

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?

von Achim S. (Gast)


Lesenswert?

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.

von VHDL-Polizei (Gast)


Lesenswert?

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.

von Bitwurschtler (Gast)


Lesenswert?

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?

von Patrick B. (p51d)


Lesenswert?

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?

von Gerald M. (gerald_m17)


Lesenswert?

Zähler nur inkrementieren wenn ein valid Signal anliegt?

von Fpgakuechle K. (Gast)


Lesenswert?

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,

von Achim S. (Gast)


Lesenswert?

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.

von FPGA-Polizei (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.