Non ho ancora lavorato con i filtri IIR, ma se hai solo bisogno di calcolare l'equazione data
y[n] = y[n-1]*b1 + x[n]
una volta per ciclo della CPU, è possibile utilizzare il pipelining.
In un ciclo si esegue la moltiplicazione e in un ciclo è necessario eseguire la somma per ciascun campione di input. Ciò significa che il tuo FPGA deve essere in grado di eseguire la moltiplicazione in un ciclo quando è sincronizzato alla frequenza di campionamento indicata! Quindi dovrai solo eseguire la moltiplicazione del campione corrente E la somma del risultato della moltiplicazione dell'ultimo campione in parallelo. Ciò provoca un ritardo di elaborazione costante di 2 cicli.
Ok, diamo un'occhiata alla formula e progettiamo una pipeline:
y[n] = y[n-1]*b1 + x[n]
Il codice della pipeline potrebbe essere simile al seguente:
output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input
Nota che tutti e tre i comandi devono essere eseguiti in parallelo e che "output" nella seconda riga utilizza quindi l'output dell'ultimo ciclo di clock!
Non ho lavorato molto con Verilog, quindi la sintassi di questo codice è probabilmente errata (ad es. Larghezza di bit mancante dei segnali di input / output; sintassi di esecuzione per la moltiplicazione). Tuttavia dovresti avere l'idea:
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: Forse un programmatore esperto di Verilog potrebbe modificare questo codice e rimuovere questo commento e il commento sopra il codice in seguito. Grazie!
PPS: nel caso in cui il fattore "b1" sia una costante fissa, potresti essere in grado di ottimizzare il progetto implementando uno speciale moltiplicatore che accetta solo un input scalare e calcola solo "volte b1".
Risposta a: "Sfortunatamente, questo è effettivamente equivalente a y [n] = y [n-2] * b1 + x [n]. Ciò è dovuto allo stadio aggiuntivo della pipeline." come commento alla vecchia versione della risposta
Sì, quello era effettivamente giusto per la seguente vecchia versione (INCORRETTA !!!):
always @ (posedge clk or posedge reset)
if (reset) begin
t <= 0;
end else begin
y <= t + x;
t <= mult(y, b);
end
Spero di aver corretto questo errore ora ritardando anche i valori di input in un secondo registro:
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
Per assicurarci che funzioni correttamente questa volta diamo un'occhiata a ciò che accade nei primi cicli. Si noti che i primi 2 cicli producono più o meno immondizia (definita), poiché non sono disponibili valori di output precedenti (ad es. Y [-1] == ??). Il registro y è inizializzato con 0, che equivale ad assumere y [-1] == 0.
Primo ciclo (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
Secondo ciclo (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]
Terzo ciclo (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]
Quarto ciclo (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]
Possiamo vedere che a partire dal cilindro n = 2 otteniamo il seguente output:
y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]
che equivale a
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
Come accennato in precedenza, introduciamo un ritardo aggiuntivo di l = 1 cicli. Ciò significa che l'output y [n] è ritardato di ritardo l = 1. Ciò significa che i dati di output sono equivalenti ma sono ritardati di un "indice". Per essere più chiari: i dati di uscita ritardati di 2 cicli, poiché è necessario un ciclo di clock (normale) e 1 ciclo di clock aggiuntivo (ritardo l = 1) viene aggiunto per lo stadio intermedio.
Ecco uno schizzo per rappresentare graficamente il flusso dei dati:
PS: Grazie per aver esaminato da vicino il mio codice. Quindi ho imparato anche qualcosa! ;-) Fammi sapere se questa versione è corretta o se vedi altri problemi.