Pertanyaan ini adalah tentang menerapkan filter IIR dalam FPGA dengan irisan DSP, dengan kriteria yang sangat spesifik.
Katakanlah Anda membuat filter tanpa ketukan ke depan dan hanya 1 ketuk terbalik, dengan persamaan ini:
(lihat gambar)
Ambil irisan DSP48A1 dari Xilinx sebagai contoh - sebagian besar irisan IP DSP serupa.
Katakanlah Anda memiliki data analog yang masuk pada 1 sampel per jam. Saya ingin merancang filter IIR yang berjalan secara sinkron pada jam sampel.
Masalahnya adalah bahwa untuk menjalankan slice DSP pada tingkat maksimum, Anda tidak dapat melipatgandakan DAN menambahkan pada siklus yang sama. Anda harus memiliki register pipa antara komponen-komponen ini.
Jadi, jika Anda memiliki 1 sampel baru setiap jam, Anda harus menghasilkan 1 output per jam. Namun, Anda memerlukan jam 2 keluaran sebelumnya sebelum Anda dapat menghasilkan yang baru dalam desain ini.
Solusi yang jelas adalah baik memproses data pada laju jam ganda, atau menonaktifkan register pipa sehingga Anda dapat mengalikan dan menambahkan dalam siklus yang sama.
Sayangnya, jika Anda mengambil sampel pada kecepatan clock maksimum dari slice DSP yang sepenuhnya disalurkan melalui pipa, tidak satu pun dari solusi itu yang mungkin. Apakah ada cara lain untuk membangun ini?
(Poin bonus jika Anda dapat merancang filter IIR yang beroperasi pada setengah dari laju sampel, menggunakan sejumlah irisan DSP)
Tujuannya adalah menjalankan filter kompensasi untuk 1 GSPS ADC dalam Xilinx Artix FPGA. Irisan DSP mereka dapat berjalan lebih dari 500 MHz saat disalin sepenuhnya. Jika ada solusi untuk 1 sampel per jam, saya ingin mencoba dan skala solusi untuk 2 sampel per jam. Ini semua sangat mudah dengan filter FIR.
Jawaban:
Saya belum bekerja dengan filter IIR, tetapi jika Anda hanya perlu menghitung persamaan yang diberikan
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:
Kode pipa Anda bisa terlihat seperti ini:
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:
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:
Mudah-mudahan saya memperbaiki bug ini sekarang dengan menunda nilai input, juga di register kedua:
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):
Siklus Kedua (n = 1):
Siklus Ketiga (n = 2):
Siklus Keempat (n = 3):
Kita dapat melihat, bahwa diawali dengan silinder n = 2 kita mendapatkan output berikut:
yang setara dengan
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.
sumber
y[n+l] = y[n-1] * b + x[n]
dengan nilai tetap untuk lagl
yang dapat ditulis ulang key[n] = y[n-1-l] * b + x[n-l]
dan untuk l = 1 iniy[n] = y[n-2] * b + x[n-1]
.y[n+l] = x[n] * b0 + x[n-1] * b1 - y[n-1] * a1 - y[n-2] * a2
=>y[n] = x[n-l]*b0 + x[n-1-l] * b1 - y[n-1-l] * a1 - y[n-2-l]*a2
. Dengan asumsi Anda dapat melakukan semua tiga perkalian secara paralel (1. tahap / 1 siklus) dan perlu melakukan untuk menambahkan produk bersama-sama Anda membutuhkan 2 siklus (1 siklus: menambah / sub pertama dua hasil produk, 1 siklus: menambah / sub hasil dari kedua add / subs), Anda akan membutuhkan 2 siklus tambahan. Jadi l = (3-1) = 2 memberi Anday[n]=x[n-2]*b0+x[n-1-2]*b1-y[n-1-2]*a1-y[n-2-2]*a2
=>y[n]=x[n-2]*b0+x[n-3]*b1-y[n-3]*a1-y[n-4]*a2
Ya, Anda dapat clock pada frekuensi sampel.
Solusi untuk masalah ini adalah memanipulasi ekspresi asli sehingga register pipa dapat dimasukkan, sambil mempertahankan urutan output yang diinginkan.
Diberikan: y [n] = y [n-1] * b1 + x [n];
ini dapat dimanipulasi menjadi: y [n] = y [n-2] * b1 * b1 + x [n-1] * b1 + x [n].
Untuk memverifikasi ini adalah urutan yang sama mempertimbangkan apa yang terjadi pada beberapa sampel pertama x [0], x [1], x [2] dll, di mana sebelumnya x [0] semua x, sampel y adalah nol.
Untuk ekspresi asli urutannya adalah:
Jelas bahwa perlu b1 <1, kalau tidak ini akan tumbuh tanpa terikat.
Sekarang perhatikan ungkapan yang dimanipulasi:
Ini urutan yang sama.
Solusi perangkat keras dalam pustaka Xilinx akan membutuhkan dua DSP48E dalam cascade. Lihat gambar 1-1 di UG193 v3.6 untuk port dan daftarkan nama di bawah. Primitif pertama mengalikan dengan b1 dan menambahkan satu jam kemudian; yang kedua adalah mengalikan dengan b1 * b1 dan menambahkan satu jam kemudian. Ada latensi pipa 4 jam untuk logika ini.
- DSP48E # 1
a_port1: = b1; - koefisien konstan, atur AREG = 1
b_port1: = x; - atur atribut BREG = 1
c_port1: = x; - atur CREG = 1
- internal ke DSP48E # 1
reg_a1 <= a_port1;
reg_b1 <= b_port1;
reg_c1 <= c_port1;
reg_m1 <= reg_a1 * reg_b1;
reg_p1 <= reg_m1 + reg_c1; - output 1 DSP48E
- akhir DSP48E # 1
- DSP48E # 2
a_port2: = reg_p2; - atur atribut AREG = 0
b_port2: = b1 * b1; - konstan, atur BREG = 1
c_port2: = reg_p1; - atur CREG = 1
- internal ke DSP48E # 2
reg_b2 <= b_port2;
reg_c2 <= c_port2;
reg_m2 <= a_port2 * reg_b2;
reg_p2 <= reg_m2 + reg_c2;
- akhir DSP48E # 2
Urutan di reg_p1:
x [0],
x [1] + x [0] * b1,
x [2] + x [1] * b1,
x [3] + x [2] * b1,
dll.
Urutan di reg_p2 adalah hasil yang diinginkan. Di dalam DSP48E ke-2, register reg_m2 memiliki urutan:
x [0] * b1 * b1,
x [1] * b1 * b1 + x [0] * b1 * b1 * b1,
x [2] * b1 * b1 + x [1] * b1 * b1 * b1 + x [0] * b1 * b1 * b1 * b1 * b1
Ada keanggunan yang bagus untuk hasil ini. Jelas DSP48E tidak menggandakan dan menambahkan dalam jam yang sama, namun itulah yang dibutuhkan persamaan perbedaan. Persamaan perbedaan yang dimanipulasi memungkinkan kita untuk mentolerir register M dan P dalam DSP48E dan clock dengan kecepatan penuh.
sumber