Ich habe noch nicht mit IIR-Filtern gearbeitet, aber wenn Sie nur die angegebene Gleichung berechnen müssen
y[n] = y[n-1]*b1 + x[n]
Einmal pro CPU-Zyklus können Sie Pipelining verwenden.
In einem Zyklus führen Sie die Multiplikation durch und in einem Zyklus müssen Sie die Summierung für jede Eingangsabtastung durchführen. Das bedeutet, dass Ihr FPGA in der Lage sein muss, die Multiplikation in einem Zyklus durchzuführen, wenn es mit der angegebenen Abtastrate getaktet wird! Dann müssen Sie nur noch die Multiplikation des aktuellen Samples UND die Summierung des Multiplikationsergebnisses des letzten Samples parallel durchführen. Dies führt zu einer konstanten Verarbeitungsverzögerung von 2 Zyklen.
Ok, schauen wir uns die Formel an und entwerfen eine Pipeline:
y[n] = y[n-1]*b1 + x[n]
Ihr Pipeline-Code könnte folgendermaßen aussehen:
output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input
Beachten Sie, dass alle drei Befehle parallel ausgeführt werden müssen und dass "Ausgabe" in der zweiten Zeile daher die Ausgabe aus dem letzten Taktzyklus verwendet!
Ich habe nicht viel mit Verilog gearbeitet, daher ist die Syntax dieses Codes höchstwahrscheinlich falsch (z. B. fehlende Bitbreite der Eingangs- / Ausgangssignale; Ausführungssyntax für die Multiplikation). Sie sollten jedoch auf die Idee kommen:
module IIRFilter( clk, reset, x, b, y );
input clk, reset, x, b;
output y;
reg y, t, t2;
wire clk, reset, x, b;
always @ (posedge clk or posedge reset)
if (reset) begin
y <= 0;
t <= 0;
t2 <= 0;
end else begin
y <= t + t2;
t <= mult(y, b);
t2 <= x
end
endmodule
PS: Vielleicht könnte ein erfahrener Verilog-Programmierer diesen Code bearbeiten und diesen Kommentar und den Kommentar über dem Code anschließend entfernen. Vielen Dank!
PPS: Wenn Ihr Faktor "b1" eine feste Konstante ist, können Sie das Design möglicherweise optimieren, indem Sie einen speziellen Multiplikator implementieren, der nur eine Skalareingabe verwendet und nur "Zeiten b1" berechnet.
Antwort auf: "Leider entspricht dies tatsächlich y [n] = y [n-2] * b1 + x [n]. Dies liegt an der zusätzlichen Pipeline-Stufe." als Kommentar zur alten Version der Antwort
Ja, das war eigentlich richtig für die folgende alte (INCORRECT !!!) Version:
always @ (posedge clk or posedge reset)
if (reset) begin
t <= 0;
end else begin
y <= t + x;
t <= mult(y, b);
end
Ich habe diesen Fehler jetzt hoffentlich behoben, indem ich auch die Eingabewerte in einem zweiten Register verzögert habe:
always @ (posedge clk or posedge reset)
if (reset) begin
y <= 0;
t <= 0;
t2 <= 0;
end else begin
y <= t + t2;
t <= mult(y, b);
t2 <= x
end
Um sicherzustellen, dass es diesmal richtig funktioniert, schauen wir uns an, was in den ersten Zyklen passiert. Beachten Sie, dass die ersten beiden Zyklen mehr oder weniger (definierten) Müll produzieren, da keine vorherigen Ausgabewerte (z. B. y [-1] == ??) verfügbar sind. Das Register y wird mit 0 initialisiert, was der Annahme von y [-1] == 0 entspricht.
Erster Zyklus (n = 0):
BEFORE: INPUT (x=x[0], b); REGISTERS (t=0, t2=0, y=0)
y <= t + t2; == 0
t <= mult(y, b); == y[-1] * b = 0
t2 <= x == x[0]
AFTERWARDS: REGISTERS (t=0, t2=x[0], y=0), OUTPUT: y[0]=0
Zweiter Zyklus (n = 1):
BEFORE: INPUT (x=x[1], b); REGISTERS (t=0, t2=x[0], y=y[0])
y <= t + t2; == 0 + x[0]
t <= mult(y, b); == y[0] * b
t2 <= x == x[1]
AFTERWARDS: REGISTERS (t=y[0]*b, t2=x[1], y=x[0]), OUTPUT: y[1]=x[0]
Dritter Zyklus (n = 2):
BEFORE: INPUT (x=x[2], b); REGISTERS (t=y[0]*b, t2=x[1], y=y[1])
y <= t + t2; == y[0]*b + x[1]
t <= mult(y, b); == y[1] * b
t2 <= x == x[2]
AFTERWARDS: REGISTERS (t=y[1]*b, t2=x[2], y=y[0]*b+x[1]), OUTPUT: y[2]=y[0]*b+x[1]
Vierter Zyklus (n = 3):
BEFORE: INPUT (x=x[3], b); REGISTERS (t=y[1]*b, t2=x[2], y=y[2])
y <= t + t2; == y[1]*b + x[2]
t <= mult(y, b); == y[2] * b
t2 <= x == x[3]
AFTERWARDS: REGISTERS (t=y[2]*b, t2=x[3], y=y[1]*b+x[2]), OUTPUT: y[3]=y[1]*b+x[2]
Wir können sehen, dass wir beginnend mit cylce n = 2 die folgende Ausgabe erhalten:
y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]
das ist äquivalent zu
y[n]=y[n-2]*b + x[n-1]
y[n]=y[n-1-l]*b1 + x[n-l], where l = 1
y[n+l]=y[n-1]*b1 + x[n], where l = 1
Wie oben erwähnt, führen wir eine zusätzliche Verzögerung von l = 1 Zyklen ein. Das bedeutet, dass Ihre Ausgabe y [n] um die Verzögerung l = 1 verzögert ist. Das heißt, die Ausgabedaten sind äquivalent, werden jedoch um einen "Index" verzögert. Um es klarer zu machen: Die Ausgangsdaten verzögern sich um 2 Zyklen, da ein (normaler) Taktzyklus benötigt wird und 1 zusätzlicher (Verzögerung l = 1) Taktzyklus für die Zwischenstufe hinzugefügt wird.
Hier ist eine Skizze, um grafisch darzustellen, wie die Daten fließen:
PS: Danke, dass Sie sich meinen Code genau angesehen haben. Also habe ich auch etwas gelernt! ;-) Lass mich wissen, ob diese Version korrekt ist oder ob du weitere Probleme siehst.