Je n'ai pas encore travaillé avec les filtres IIR, mais si vous avez seulement besoin de calculer l'équation donnée
y[n] = y[n-1]*b1 + x[n]
une fois par cycle CPU, vous pouvez utiliser le pipelining.
Dans un cycle, vous effectuez la multiplication et dans un cycle, vous devez faire la sommation pour chaque échantillon d'entrée. Cela signifie que votre FPGA doit être capable de faire la multiplication en un cycle lorsqu'il est cadencé à la fréquence d'échantillonnage donnée! Ensuite, vous aurez seulement besoin de faire la multiplication de l'échantillon actuel ET la somme du résultat de multiplication du dernier échantillon en parallèle. Cela entraînera un décalage de traitement constant de 2 cycles.
Ok, regardons la formule et concevons un pipeline:
y[n] = y[n-1]*b1 + x[n]
Votre code de pipeline pourrait ressembler à ceci:
output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input
Notez que les trois commandes doivent être exécutées en parallèle et que la "sortie" sur la deuxième ligne utilise donc la sortie du dernier cycle d'horloge!
Je n'ai pas beaucoup travaillé avec Verilog, donc la syntaxe de ce code est très probablement erronée (par exemple, largeur de bit manquante des signaux d'entrée / sortie; syntaxe d'exécution pour la multiplication). Cependant, vous devriez avoir l'idée:
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: Peut-être qu'un programmeur Verilog expérimenté pourrait modifier ce code et supprimer ce commentaire et le commentaire au-dessus du code par la suite. Merci!
PPS: dans le cas où votre facteur "b1" est une constante fixe, vous pourriez être en mesure d'optimiser la conception en implémentant un multiplicateur spécial qui ne prend qu'une seule entrée scalaire et calcule les "temps b1" uniquement.
Réponse à: "Malheureusement, cela équivaut en fait à y [n] = y [n-2] * b1 + x [n]. Cela est dû à l'étape supplémentaire du pipeline." comme commentaire à l'ancienne version de la réponse
Oui, c'était en fait correct pour l'ancienne version (INCORRECTE !!!) suivante:
always @ (posedge clk or posedge reset)
if (reset) begin
t <= 0;
end else begin
y <= t + x;
t <= mult(y, b);
end
J'espère avoir corrigé ce bug maintenant en retardant les valeurs d'entrée, également dans un deuxième registre:
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
Pour nous assurer que cela fonctionne correctement cette fois, regardons ce qui se passe lors des premiers cycles. Notez que les 2 premiers cycles produisent plus ou moins de déchets (définis), car aucune valeur de sortie précédente (par exemple y [-1] == ??) n'est disponible. Le registre y est initialisé à 0, ce qui revient à supposer que y [-1] == 0.
Premier cycle (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
Deuxième cycle (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]
Troisième cycle (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]
Quatrième cycle (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]
Nous pouvons voir qu'à partir de cylce n = 2, nous obtenons la sortie suivante:
y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]
ce qui équivaut à
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
Comme mentionné ci-dessus, nous introduisons un décalage supplémentaire de l = 1 cycle. Cela signifie que votre sortie y [n] est retardée de retard l = 1. Cela signifie que les données de sortie sont équivalentes mais sont retardées d'un "index". Pour être plus clair: les données de sortie retardées sont de 2 cycles, car un cycle d'horloge (normal) est nécessaire et 1 cycle d'horloge supplémentaire (décalage l = 1) est ajouté pour l'étage intermédiaire.
Voici un croquis pour décrire graphiquement comment les données circulent:
PS: Merci d'avoir regardé de près mon code. J'ai donc aussi appris quelque chose! ;-) Faites-moi savoir si cette version est correcte ou si vous voyez d'autres problèmes.