Henüz IIR filtreleri ile çalışmadım, ancak sadece verilen denklemi hesaplamanız gerekiyorsa
y[n] = y[n-1]*b1 + x[n]
CPU döngüsü başına bir kez boru hattını kullanabilirsiniz.
Bir döngüde çarpma işlemini ve bir döngüde her girdi örneği için toplamı yapmanız gerekir. Bu, FPGA'nızın verilen örnek hızında saatlendiğinde çarpımı bir döngüde yapabilmesi gerektiği anlamına gelir! O zaman sadece geçerli örneğin çarpımını VE son örneğin çarpım sonucunun toplamını paralel olarak yapmanız gerekir. Bu, 2 döngüden oluşan sabit bir işleme gecikmesine neden olacaktır.
Tamam, formüle bir göz atalım ve bir boru hattı tasarlayalım:
y[n] = y[n-1]*b1 + x[n]
Boru hattı kodunuz şöyle görünebilir:
output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input
Her üç komutun da paralel yürütülmesi gerektiğini ve bu nedenle ikinci satırdaki "çıktı" nın son saat döngüsünün çıktısını kullandığını unutmayın!
Verilog ile fazla çalışmadım, bu yüzden bu kodun sözdizimi büyük olasılıkla yanlıştır (örneğin, giriş / çıkış sinyallerinin bit genişliği eksik; çarpma için yürütme sözdizimi). Ancak şu fikri edinmelisiniz:
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
Not: Belki bazı deneyimli Verilog programcısı bu kodu düzenleyebilir ve daha sonra bu yorumu ve kodun üstündeki yorumu kaldırabilir. Teşekkürler!
PPS: "b1" çarpanınızın sabit bir sabit olması durumunda, yalnızca bir skaler girdi alan ve yalnızca "b1 çarpı" değerini hesaplayan özel bir çarpan uygulayarak tasarımı optimize edebilirsiniz.
Yanıt: "Ne yazık ki, bu aslında y [n] = y [n-2] * b1 + x [n] ile eşdeğerdir. Bunun nedeni fazladan boru hattı aşamasıdır." cevabın eski versiyonuna yorum olarak
Evet, bu aslında aşağıdaki eski (INCORRECT !!!) sürüm için doğruydu:
always @ (posedge clk or posedge reset)
if (reset) begin
t <= 0;
end else begin
y <= t + x;
t <= mult(y, b);
end
Umarım şimdi ikinci bir kayıtta da giriş değerlerini geciktirerek bu hatayı düzelttim:
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
Bu sefer düzgün çalıştığından emin olmak için ilk birkaç döngüde neler olduğuna bakalım. Önceki çıktı değerlerinin (ör. Y [-1] == ??) mevcut olmadığından, ilk 2 döngünün az çok (tanımlanmış) çöp ürettiğine dikkat edin. Y kaydı, y [-1] == 0 varsayılmasına eşdeğer olan 0 ile başlatılır.
Birinci Düzey (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
İkinci Düzey (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]
Üçüncü Çevrim (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]
Dördüncü Döngü (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]
Gördüğümüz gibi, n = 2 silindirinden başlayarak aşağıdaki çıktıyı elde ediyoruz:
y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]
eşdeğer
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
Yukarıda belirtildiği gibi ek bir l = 1 devir gecikmesi sunuyoruz. Bu, y [n] çıkışınızın l = 1 gecikmesi ile geciktiği anlamına gelir. Bu, çıktı verilerinin eşdeğer olduğu ancak bir "indeks" tarafından geciktiği anlamına gelir. Daha açık olmak gerekirse: Bir (normal) saat çevrimi gerektiğinden ve ara aşama için 1 ek (gecikme l = 1) saat çevrimi eklendiğinden, çıkış verileri 2 döngü gecikmelidir.
Verilerin nasıl aktığını grafik olarak gösteren bir çizim:
Not: Koduma yakından baktığınız için teşekkür ederim. Ben de bir şey öğrendim! ;-) Bu sürümün doğru olup olmadığını veya daha fazla sorun görürseniz bana bildirin.