क्या एक FPGA में IIR फ़िल्टर बनाना संभव है जो नमूना आवृत्ति पर देखा जाता है?


9

यह प्रश्न डीएसपी स्लाइस के साथ एक एफपीजीए में IIR फ़िल्टर लागू करने के बारे में है, जिसमें बहुत ही विशिष्ट मानदंड हैं।

कहते हैं कि आप इस समीकरण के साथ आगे के नल और केवल 1 रिवर्स टैप के साथ एक फिल्टर बना रहे हैं:

y[n]=y[n1]b1+x[n]

(चित्र देखें)

उदाहरण के रूप में Xilinx से DSP48A1 स्लाइस लें - अधिकांश हार्ड IP DSP स्लाइस समान हैं।

कहते हैं कि आपके पास प्रति घड़ी 1 नमूने पर आने वाला एनालॉग डेटा है। मैं एक आईआईआर फ़िल्टर डिजाइन करना चाहता हूं जो नमूना घड़ी में समान रूप से चलता है।

समस्या यह है कि अधिकतम दर पर डीएसपी स्लाइस को चलाने के लिए, आप एक ही चक्र पर गुणा और जोड़ नहीं सकते हैं। आपको इन घटकों के बीच एक पाइपलाइन रजिस्टर करना होगा।

इसलिए, यदि आपके पास हर घड़ी 1 नया नमूना है, तो आपको प्रति घड़ी 1 आउटपुट का उत्पादन करने की आवश्यकता होगी। हालाँकि, इस डिज़ाइन में एक नया उत्पादन करने से पहले आपको पिछले आउटपुट 2 घड़ियों की आवश्यकता होगी।

स्पष्ट समाधान या तो डेटा को डबल क्लॉक रेट पर संसाधित करना है, या पाइपलाइन रजिस्टर को अक्षम करना है ताकि आप एक ही चक्र में गुणा और जोड़ सकें।

दुर्भाग्य से, यदि आप कहते हैं कि आप पूरी तरह से पाइपलाइज्ड डीएसपी स्लाइस की अधिकतम घड़ी दर का नमूना ले रहे हैं, तो उनमें से कोई भी समाधान संभव नहीं है। क्या इसे बनाने का कोई और तरीका है?

(बोनस अंक यदि आप एक IIR फ़िल्टर डिज़ाइन कर सकते हैं जो नमूना दर के आधे हिस्से में संचालित होता है, किसी भी डीएसपी स्लाइस का उपयोग करके)

लक्ष्य Xilinx Artix FPGA में 1 GSPS ADC के लिए क्षतिपूर्ति फ़िल्टर चलाना होगा। उनके DSP स्लाइस पूरी तरह से पाइपलाइज होने पर सिर्फ 500 MHz से अधिक चल सकते हैं। यदि प्रति घड़ी 1 नमूने के लिए एक समाधान है, तो मैं कोशिश करूँगा और प्रति घड़ी 2 नमूनों के समाधान का पैमाना बनाऊंगा। एफआईआर फिल्टर के साथ यह सब बहुत आसान है।

एकल प्रतिक्रिया IIR फ़िल्टर उदाहरण


1
बस स्पष्ट करने के लिए, कोई कारण नहीं है कि आपके पास पाइपलाइन पद्धति के साथ प्रति घड़ी चक्र में एक आउटपुट नहीं होगा, है ना? आप दो के बजाय एक घड़ी चक्र के लिए विलंबता को कम करने की कोशिश कर रहे हैं, है ना? आपकी स्थिति के आधार पर, यदि आप b1 के लिए पूर्णांक का उपयोग कर रहे हैं, तो आप गुणा को x [n] सहित एक विशाल ऐड में बदल सकते हैं।
हॉर्टा

सही - चूंकि प्रति घड़ी एक इनपुट होता है, इसलिए प्रति घड़ी एक आउटपुट होना आवश्यक है। विलंबता कोई समस्या नहीं है। डीएसपी स्लाइस में केवल 2 इनपुट योजक होते हैं, और नल आमतौर पर बहुत बड़ी संख्या में होते हैं, इसलिए आप 1 घड़ी चक्र में बी 1 बार नहीं जोड़ सकते। मुख्य सीमा यह है कि आउटपुट को 1 घड़ी में वापस फीड करने की आवश्यकता होती है, लेकिन उत्पादन के लिए 2 घड़ियों का समय लगता है।
Marcus10110

1
मुझे लगता है कि आप अभी भी गलत समझ रहे हैं कि पाइप लाइन कैसे काम करती है। एक पाइपलाइन संभावित रूप से विलंबता को बढ़ाता है, लेकिन आपको प्रत्येक घड़ी चक्र में प्रत्येक इनपुट के लिए 1 आउटपुट प्राप्त करने की अनुमति देता है। यह सिर्फ इतना है कि परिणाम अब आदर्श 1 घड़ी के बजाय 2 घड़ियों के बाद है। इनपुट इस तरह अनुक्रम होगा: x [0], x [1], x [2], x [3], x [4] जबकि आउटपुट उसी समय अंतराल y [-2], y होगा [-1], वाई [0], वाई [1], वाई [2]। आप कोई नमूना नहीं खो रहे हैं। इसके अलावा, आप FPGA पर हैं, इसलिए यदि आप DSP पाइपलाइनों के लिए डिज़ाइन किए गए काम से अधिक काम लेना चाहते हैं, तो कार्यभार को समानांतर करने के लिए fpga का उपयोग करें।
हॉर्टा

कि डीएसपी एक चक्र में एक संचित गुणा करने में सक्षम है। हालांकि यह मेरे लिए स्पष्ट नहीं है कि अगर किसी DSP स्लाइस का आउटपुट एक ही चक्र में फीडबैक के साथ अपने इनपुट से जुड़ा हो सकता है।
जर्बलो

हॉर्टा - आप सामान्य रूप से पाइपलाइनिंग के बारे में सही हैं, लेकिन समस्या यह है कि इस मामले में टैब बी 1 में प्रतिक्रिया है - जिसका अर्थ है कि पाइप लाइन में एक चरण पिछले मूल्य के आउटपुट पर निर्भर करता है। अगर यह हमेशा पिछले आउटपुट से अगले आउटपुट का उत्पादन करने के लिए 2 घड़ियां लेता है, तो प्रति घड़ी 1 आउटपुट का उत्पादन करने का कोई तरीका नहीं है, भले ही आपने कितना विलंबता जोड़ा हो। jbarlow - आप सही हैं, DSP स्लाइस में 1 चक्र फ्यूज्ड विकल्प है। हालाँकि यह इस मामले में पर्याप्त तेजी से नहीं चल सकता है। एम रजिस्टर (डेटाशीट देखें) जोड़कर आप 500 मेगाहर्ट्ज तक पहुंच सकते हैं। फिर आप एक ही क्लॉक में गुणा और जोड़ नहीं सकते।
मार्कस 10110

जवाबों:


3

मैंने अभी तक IIR फ़िल्टर के साथ काम नहीं किया है, लेकिन अगर आपको केवल दिए गए समीकरण की गणना करने की आवश्यकता है

y[n] = y[n-1]*b1 + x[n]

एक बार सीपीयू चक्र के बाद, आप पाइपलाइनिंग का उपयोग कर सकते हैं।

एक चक्र में आप गुणा करते हैं और एक चक्र में आपको प्रत्येक इनपुट नमूने के लिए योग करने की आवश्यकता होती है। इसका मतलब है कि आपका FPGA दिए गए नमूना दर पर नजर रखने पर एक चक्र में गुणा करने में सक्षम होना चाहिए! फिर आपको केवल वर्तमान नमूने का गुणा करने की आवश्यकता होगी और अंतिम नमूने के गुणा का परिणाम समानांतर होगा। यह 2 चक्रों के निरंतर प्रसंस्करण अंतराल का कारण होगा।

ठीक है, चलो सूत्र पर एक नज़र डालें और एक पाइपलाइन डिज़ाइन करें:

y[n] = y[n-1]*b1 + x[n]

आपका पाइपलाइन कोड इस तरह दिख सकता है:

output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input

ध्यान दें कि सभी तीन आदेशों को समानांतर में निष्पादित करने की आवश्यकता है और दूसरी पंक्ति में "आउटपुट" इसलिए अंतिम घड़ी चक्र से आउटपुट का उपयोग करता है!

मैंने वेरिलॉग के साथ ज्यादा काम नहीं किया, इसलिए यह कोड का सिंटैक्स सबसे अधिक गलत है (उदाहरण के लिए इनपुट / आउटपुट सिग्नल की थोड़ी-सी चौड़ाई गायब है; गुणन के लिए निष्पादन सिंटैक्स)। हालाँकि आपको यह विचार करना चाहिए:

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

पुनश्च: हो सकता है कि कुछ अनुभवी वेरिलोग प्रोग्रामर इस कोड को संपादित कर सकते हैं और बाद में इस टिप्पणी और कोड के ऊपर की टिप्पणी को हटा सकते हैं। धन्यवाद!

PPS: यदि आपका कारक "b1" एक स्थिर स्थिरांक है, तो आप एक विशेष गुणक को लागू करके डिजाइन को अनुकूलित करने में सक्षम हो सकते हैं जो केवल एक स्केलर इनपुट लेता है और केवल "बार b1" की गणना करता है।

इसका उत्तर: "दुर्भाग्य से, यह वास्तव में y [n] = y [n-2] * b1 + [[n] के बराबर है। यह अतिरिक्त पाइपलाइन चरण के कारण है।" उत्तर के पुराने संस्करण के लिए टिप्पणी के रूप में

हां, यह वास्तव में निम्नलिखित पुराने (INCORRECT !!!) संस्करण के लिए सही था:

  always @ (posedge clk or posedge reset)
  if (reset) begin
    t <= 0;
  end else begin
    y <= t + x;
    t <= mult(y, b);
  end

मुझे उम्मीद है कि इस बग को अब इनपुट मानों में देरी करके ठीक किया जाएगा, वह भी एक दूसरे रजिस्टर में:

  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

यह सुनिश्चित करने के लिए कि यह इस बार सही ढंग से काम करता है आइए देखें कि पहले कुछ चक्रों में क्या होता है। ध्यान दें कि पहले 2 चक्र अधिक या कम (परिभाषित) कचरा उत्पन्न करते हैं, क्योंकि पिछले उत्पादन मूल्य नहीं हैं (जैसे y [-1] == ??) उपलब्ध हैं। रजिस्टर y को 0 से आरंभ किया गया है, जो मान के बराबर है [-1] == 0।

पहला चक्र (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

दूसरा चक्र (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]

तीसरा चक्र (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]

चौथा चक्र (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]

हम देख सकते हैं, कि शुरुआत n = 2 से होती है, हमें निम्न आउटपुट मिलते हैं:

y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]

जो के बराबर है

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

जैसा कि ऊपर उल्लेख किया गया है, हम l = 1 चक्रों के अतिरिक्त अंतराल का परिचय देते हैं। इसका मतलब है कि आपके आउटपुट y [n] में lag l = 1 की देरी है। इसका मतलब है कि आउटपुट डेटा बराबर है लेकिन एक "इंडेक्स" द्वारा देरी हो रही है। अधिक स्पष्ट होने के लिए: आउटपुट डेटा में देरी 2 चक्र हो सकती है, क्योंकि एक (सामान्य) घड़ी चक्र की आवश्यकता होती है और मध्यवर्ती चरण के लिए 1 अतिरिक्त (अंतराल l = 1) घड़ी चक्र जोड़ा जाता है।

डेटा को कैसे प्रवाहित किया जाता है, इसका चित्रण करने के लिए यहां एक रेखाचित्र दिया गया है:

डेटा प्रवाह का स्केच

पुनश्च: मेरे कोड पर एक करीबी नज़र रखने के लिए धन्यवाद। तो मैंने भी कुछ सीखा! ;-) मुझे बताएं कि क्या यह संस्करण सही है या यदि आप कोई और समस्या देखते हैं।


अच्छा काम! दुर्भाग्य से, y [n] = y [n-2] * b + x [n-1] वास्तव में कार्यात्मक रूप से y [n] = y [n-1] * b + x [n] विलंबता के बराबर नहीं है। IIR ट्रांसफर फ़ंक्शन का रूप वास्तव में इस तरह दिखता है: y [n] = x [n] * b0 + x [n-1] * b1 - y [n-1] * a1 - y [n-2] * a2 और इसी तरह। आपका फॉर्म b0 और a1 से 0 सेट करता है और इसके बजाय b1 और a2 का उपयोग करता है। हालाँकि, यह परिवर्तन वास्तव में एक बहुत ही अलग फिल्टर का उत्पादन करता है। यदि पहले फ़िल्टर करने वाले (a1) के साथ शून्य पर सेट करने के लिए फ़िल्टर की गणना करने का एक तरीका था, तो आपके दोनों समाधान पूरी तरह से काम करेंगे।
मार्कस 10110 10

ठीक है, आपको "शुरू किए गए अंतराल" मुद्दे को सही ढंग से समझने की आवश्यकता है। उदाहरण के लिए, एक "डेटा स्ट्रीम प्रोसेसिंग" फ़िल्टर को बस इसके इनपुट को y [n] = x [n] के रूप में अग्रेषित करना चाहिए अगर यह आउटपुट के रूप में y [n] = x [n-1] का उत्पादन करता है। आउटपुट केवल 1 चक्र से विलंबित होता है (जैसे आउटपुट इनपुट सभी इनपुट सूचकांकों के सापेक्ष एक निश्चित मान से ऑफसेट होता है)! हमारे उदाहरण में इसका मतलब है कि आपका कार्य y[n+l] = y[n-1] * b + x[n]अंतराल के लिए एक निश्चित मूल्य के साथ है lजिसे y[n] = y[n-1-l] * b + x[n-l]l = 1 के लिए फिर से लिखा जा सकता है और यह है y[n] = y[n-2] * b + x[n-1]
SDwarfs

: अपने और अधिक जटिल IIR फिल्टर के लिए आप भी ऐसा ही करने की आवश्यकता होगी 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। यह मानते हुए कि आप सभी तीन गुणाओं को समानांतर (1. चरण / 1 चक्र) में कर सकते हैं और उत्पादों को जोड़ने के लिए आपको एक साथ करने की आवश्यकता है 2 चक्र (1 चक्र: जोड़ने / उप पहले दो उत्पाद परिणाम, 1 चक्र: जोड़ें / उप उन दो ऐड / सब्स्क्रिप्शन का परिणाम), आपको 2 अतिरिक्त चक्रों की आवश्यकता होगी। तो l = (3-1) = 2 आपको दे y[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
SDwarfs

बेशक आपके FPGA को काम करने के लिए समानांतर में करने में सक्षम होना चाहिए: 4 गुणा और 3 जोड़ / घटाव। मतलब आपको 4 गुणक और 3 योजक के लिए संसाधनों की आवश्यकता है।
SDwarfs

0

हाँ आप नमूना आवृत्ति पर घड़ी कर सकते हैं।

इस मुद्दे का एक समाधान मूल अभिव्यक्ति में हेरफेर करना है ताकि वांछित उत्पादन अनुक्रम को बनाए रखते हुए, पाइप लाइन रजिस्टरों को डाला जा सके।

दिया: y [n] = y [n-1] * b1 + x [n];

इसमें हेरफेर किया जा सकता है: y [n] = y [n-2] * b1 * b1 + x [n-1] * b1 + x [n]।

यह सत्यापित करने के लिए एक ही अनुक्रम है कि पहले कई नमूनों x [0], x [1], x [2] आदि के बारे में विचार करें, जहां पिछले से x [0] सभी x, y नमूने शून्य थे।

मूल अभिव्यक्ति के लिए अनुक्रम है:

y = x[0],

x[1] +x[0]*b1,

x[2] +x[1]*b1 +x[0]*b1*b1,

x[3] +x[2]*b1 +x[1]*b1*b1 +x[0]*b1*b1*b1, ...

यह स्पष्ट है कि यह आवश्यक है कि बी 1 <1, अन्यथा यह बाध्य बिना बढ़ेगा।

अब हेरफेर किए गए अभिव्यक्ति पर विचार करें:

y = x[0],

x[0]*b1 +x[1],

x[0]*b1*b1 +x[1]*b1 +x[2],

x[0]*b1*b1*b1 +x[1]*b1*b1 +x[2]*b1 +x[3], ...

यह वही क्रम है।

Xilinx लाइब्रेरी प्राइमेटीज़ में एक हार्डवेयर समाधान को कैस्केड में दो DSP48E की आवश्यकता होगी। पोर्ट के लिए UG193 v3.6 में आंकड़ा 1-1 देखें और नीचे नाम पंजीकृत करें। पहला आदिम बी 1 से गुणा कर रहा है और एक घड़ी बाद में जोड़ रहा है; दूसरा बी 1 * बी 1 से गुणा कर रहा है और एक घड़ी बाद में जोड़ रहा है। इस तर्क के लिए एक 4 घड़ी पाइपलाइन विलंबता है।

- DSP48E # 1

a_port1: = b1; - निरंतर गुणांक, सेट AREG = 1

b_port1: = x; - सेट विशेषता BREG = 1

c_port1: = x; - सेट CREG = 1

- आंतरिक से 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; - 1 डीएसपी 48 ई का उत्पादन

- DSP48E # 1 का अंत

- DSP48E # 2

a_port2: = reg_p2; - सेट विशेषता AREG = 0

                -- this means the output of register reg_p2

                -- directly feeds back to the multiplier

b_port2: = b1 * b1; - स्थिरांक, BREG = 1 सेट करें

c_port2: = reg_p1; - सेट CREG = 1

- आंतरिक डीएसपी 48 ई # 2 के लिए

reg_b2 <= b_port2;

reg_c2 <= c_port2;

reg_m2 <= a_port2 * reg_b2;

reg_p2 <= reg_m2 + reg_c2;

- DSP48E # 2 का अंत

Reg_p1 पर अनुक्रम:

एक्स [0],

x [१] + x [०] * b1,

x [२] + x [१] * b1,

x [३] + x [२] * b1,

आदि।

Reg_p2 पर अनुक्रम वांछित परिणाम है। 2 डीएसपी 48 ईई के लिए आंतरिक, रजिस्टर reg_m2 में एक अनुक्रम है:

एक्स [0] * B1 * बी 1,

x [1] * b1 * b1 + x [०] * b1 * b1 * b1,

x [२] * b1 * b1 + x [१] * b1 * b1 * b1 + x [०] * b1 * b1 * b1 * b1

इस परिणाम के लिए एक अच्छा लालित्य है। स्पष्ट रूप से DSP48E गुणा नहीं करता है और एक ही घड़ी में जोड़ता है, फिर भी यही अंतर समीकरण की आवश्यकता है। जोड़-तोड़ अंतर समीकरण हमें डीएसपी 48 ई में एम और पी रजिस्टरों को पूरी गति से सहन करने की अनुमति देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.