Saya belum bekerja dengan filter IIR, tetapi jika Anda hanya perlu menghitung persamaan yang diberikan
y[n] = y[n-1]*b1 + x[n]
sekali per siklus CPU, Anda bisa menggunakan pipelining.
Dalam satu siklus Anda melakukan perkalian dan dalam satu siklus Anda perlu melakukan penjumlahan untuk setiap sampel input. Itu berarti FPGA Anda harus dapat melakukan perkalian dalam satu siklus ketika clock pada laju sampel yang diberikan! Maka Anda hanya perlu melakukan penggandaan sampel saat ini DAN penjumlahan hasil perkalian sampel terakhir secara paralel. Ini akan menyebabkan kelambatan pemrosesan konstan 2 siklus.
Ok, mari kita lihat rumus dan desain pipa:
y[n] = y[n-1]*b1 + x[n]
Kode pipa Anda bisa terlihat seperti ini:
output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input
Perhatikan bahwa ketiga perintah harus dijalankan secara paralel dan "output" pada baris kedua karenanya menggunakan output dari siklus clock terakhir!
Saya tidak bekerja terlalu banyak dengan Verilog, jadi sintaksis kode ini kemungkinan besar salah (mis. Sinyal input / output bit lebar yang hilang; sintaksis eksekusi untuk perkalian). Namun Anda harus mendapatkan ide:
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: Mungkin beberapa programmer Verilog yang berpengalaman bisa mengedit kode ini dan menghapus komentar ini dan komentar di atas kode sesudahnya. Terima kasih!
PPS: Jika faktor "b1" Anda adalah konstanta tetap, Anda mungkin dapat mengoptimalkan desain dengan menerapkan pengganda khusus yang hanya membutuhkan satu input skalar dan hanya menghitung "kali b1".
Tanggapan untuk: "Sayangnya, ini sebenarnya setara dengan y [n] = y [n-2] * b1 + x [n]. Ini karena tahap pipa tambahan." sebagai komentar untuk versi jawaban lama
Ya, itu sebenarnya tepat untuk versi lama (INCORRECT !!!) berikut:
always @ (posedge clk or posedge reset)
if (reset) begin
t <= 0;
end else begin
y <= t + x;
t <= mult(y, b);
end
Mudah-mudahan saya memperbaiki bug ini sekarang dengan menunda nilai input, juga di register kedua:
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
Untuk memastikan itu berfungsi dengan benar kali ini mari kita lihat apa yang terjadi pada beberapa siklus pertama. Perhatikan bahwa 2 siklus pertama menghasilkan lebih banyak atau lebih sedikit (didefinisikan) sampah, karena tidak ada nilai output sebelumnya (misalnya y [-1] == ??) tersedia. Register y diinisialisasi dengan 0, yang setara dengan asumsi y [-1] == 0.
Siklus Pertama (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
Siklus Kedua (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]
Siklus Ketiga (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]
Siklus Keempat (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]
Kita dapat melihat, bahwa diawali dengan silinder n = 2 kita mendapatkan output berikut:
y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]
yang setara dengan
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
Seperti disebutkan di atas kami memperkenalkan jeda tambahan l = 1 siklus. Itu berarti bahwa output Anda y [n] tertunda oleh lag l = 1. Itu berarti data output setara tetapi tertunda oleh satu "indeks". Agar lebih jelas: Data output tertunda menjadi 2 siklus, karena satu siklus clock (normal) diperlukan dan 1 siklus clock tambahan (lag l = 1) ditambahkan untuk tahap perantara.
Berikut ini adalah sketsa untuk menggambarkan secara grafis bagaimana data mengalir:
PS: Terima kasih sudah memperhatikan kode saya. Jadi saya belajar sesuatu juga! ;-) Beritahu saya jika versi ini benar atau jika Anda melihat ada masalah lagi.