サンプル周波数でクロック供給されるFPGAでIIRフィルターを作成することは可能ですか?


9

この質問は、非常に具体的な基準を使用して、DSPスライスを備えたFPGAにIIRフィルターを実装することに関するものです。

次の式を使用して、順方向タップがなく、逆方向タップが1つだけのフィルターを作成するとします。

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

(画像を参照)

例としてザイリンクスのDSP48A1スライスを取り上げます。ほとんどのハードIP DSPスライスは似ています。

クロックごとに1つのサンプルでアナログデータを受信するとします。サンプルクロックで同期的に実行されるIIRフィルターを設計したいと思います。

問題は、DSPスライスを最大レートで実行するために、同じサイクルで乗算と加算ができないことです。これらのコンポーネント間にはパイプラインレジスタが必要です。

したがって、クロックごとに1つの新しいサンプルがある場合、クロックごとに1つの出力を生成する必要があります。ただし、このデザインで新しいクロックを生成する前に、以前の出力2クロックが必要です。

明白な解決策は、データをダブルクロックレートで処理するか、パイプラインレジスタを無効にして、同じサイクルで乗算と加算ができるようにすることです。

残念ながら、完全にパイプライン化されたDSPスライスの最大クロックレートでサンプリングしている場合、これらのソリューションはどちらも不可能です。これを構築する他の方法はありますか?

(任意の数のDSPスライスを使用して、サンプルレートの半分で動作するIIRフィルターを設計できる場合のボーナスポイント)

目標は、ザイリンクスArtix FPGAで1 GSPS ADCの補償フィルターを実行することです。DSPスライスは、完全にパイプライン化されている場合、500 MHzをわずかに超えて実行できます。クロックあたり1サンプルのソリューションがある場合は、クロックあたり2サンプルのソリューションをスケーリングしてみます。これは、FIRフィルターを使用すると非常に簡単です。

単一フィードバックIIRフィルターの例


1
明確にするために、パイプラインメソッドでクロックサイクルごとに1つの出力がない理由はありませんよね?レイテンシを2クロックサイクルではなく1クロックサイクルに最小化しようとしていますよね?状況によっては、b1に整数を使用している場合、乗算をx [n]を含む巨大な加算に変換できます。
horta 2014年

右-クロックごとに1つの入力があるため、クロックごとに1つの出力が必要です。待ち時間も問題ではありません。DSPスライスには2入力の加算器しかなく、タップは通常かなり大きな数であるため、1クロックサイクルでb1回を追加することはできませんでした。主な制限は、出力が1クロックでフィードバックする必要があることですが、生成には2クロックかかります。
Marcus10110 2014年

1
パイプラインのしくみについてはまだ誤解されていると思います。パイプラインは潜在的にレイテンシを増加させますが、各クロックサイクルで各入力に対して1つの出力を取得できます。結果は、理想的な1クロック後ではなく、2クロック後になります。入力は次のようなシーケンスになります:x [0]、x [1]、x [2]、x [3]、x [4]出力は同じ時間間隔y [-2]、yになります[-1]、y [0]、y [1]、y [2]。サンプルを失うことはありません。また、FPGAを使用しているため、DSPパイプラインの設計よりも多くの作業を実行したい場合は、fpgaを使用してワークロードを並列化します。
horta 2014年

そのDSPは、1つのサイクルで融合積和演算を実行できます。ただし、DSPスライスの出力をフィードバック付きの独自の入力に1サイクルで接続できるかどうかは不明です。
jbarlow 2014年

horta-一般にパイプライン処理については正しいですが、問題はこの場合のタブb1にフィードバックがあることです。つまり、パイプラインのステージは前の値の出力に依存しています。前の出力から次の出力を生成するために常に2クロックかかる場合、追加したレイテンシの量に関係なく、クロックごとに1つの出力を生成する方法はありません。jbarlow-そうです、DSPスライスには1サイクルの融合オプションがあります。ただし、この場合は十分に速く実行できません。Mレジスタ(データシートを参照)を追加すると、500 MHzに到達できますが、同じclkに乗算して追加することはできません。
Marcus10110 2014年

回答:


3

私はまだIIRフィルターを操作していませんが、与えられた方程式を計算するだけでよい場合

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

CPUサイクルごとに1回、パイプライン処理を使用できます。

1サイクルで乗算を実行し、1サイクルで各入力サンプルの合計を実行する必要があります。つまり、FPGAは、所定のサンプルレートでクロックが供給されている場合、乗算を1サイクルで実行できる必要があります。次に、現在のサンプルの乗算と最後のサンプルの乗算結果の合計を並行して行うだけで済みます。これにより、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

3つのコマンドすべてを並行して実行する必要があり、2行目の「出力」は最後のクロックサイクルからの出力を使用することに注意してください。

私はVerilogであまり機能しなかったので、このコードの構文はおそらく間違っています(たとえば、入力/出力信号のビット幅がない;乗算の実行構文)。しかし、あなたはアイデアを得るべきです:

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:おそらく、経験豊富な一部のVerilogプログラマーがこのコードを編集して、このコメントとコードの上のコメントを後で削除することができます。ありがとう!

PPS:係数 "b1"が固定定数である場合、1つのスカラー入力のみを使用して "time b1"のみを計算する特別な乗数を実装することにより、設計を最適化できる場合があります。

「残念ながら、これは実際にはy [n] = y [n-2] * b1 + x [n]と同等です。これは、追加のパイプラインステージが原因です。」古いバージョンの回答へのコメントとして

はい、それは実際には次の古い(INCORRECT !!!)バージョンに適していました。

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

私はうまくいけば、2番目のレジスタでも入力値を遅らせることにより、このバグを今すぐ修正します。

  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

今回は正しく機能することを確認するために、最初の数サイクルで何が起こるかを見てみましょう。以前の出力値(y [-1] == ??など)が利用できないため、最初の2サイクルは多かれ少なかれ(定義された)ガベージを生成することに注意してください。レジスタyは0で初期化されます。これは、y [-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

2番目のサイクル(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]

3番目のサイクル(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]

4番目のサイクル(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]

cylce 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]はラグl = 1だけ遅れます。つまり、出力データは同等ですが、1つの「インデックス」だけ遅延します。より明確にするために、1つの(通常の)クロックサイクルが必要であり、中間ステージに1つの追加(ラグl = 1)クロックサイクルが追加されるため、出力データは2サイクル遅れます。

以下は、データがどのように流れるかをグラフィカルに示すスケッチです。

データフローのスケッチ

PS:私のコードをよく見ていただきありがとうございます。だから私も何かを学びました!;-)このバージョンが正しいかどうか、またはさらに問題が発生した場合はお知らせください。


よくやった!残念ながら、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)をゼロに設定してフィルターを計算する方法があった場合、どちらのソリューションも完全に機能します。
Marcus10110 2014年

さて、あなたは「導入された遅れ」問題を正しく理解する必要があります。例として、「データストリーム処理」フィルタは、y [n] = x [n-1]が出力として生成される場合、y [n] = x [n]が正しく機能するため、入力を転送するだけです。出力は1サイクル遅れるだけです(たとえば、出力インデックスはすべての入力インデックスに対して固定値でオフセットされます)。私たちの例では、これは、書き換え可能なy[n+l] = y[n-1] * b + x[n]ラグの固定値が関数ly[n] = y[n-1-l] * b + x[n-l]あり、l = 1の場合、これがであることを意味しますy[n] = y[n-2] * b + x[n-1]
SDwarfs 2014年

より複雑な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。3つの乗算をすべて並行して(1.ステージ/ 1サイクル)実行でき、積を加算する必要がある場合、2サイクルが必要です(1サイクル:最初の2つの積の結果の加算/減算、1サイクル:加算/減算これら2つのadd / subsの結果)、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は2014年

もちろん、これがFPGAで機能するには、4つの乗算と3つの加算/減算を並行して実行できる必要があります。つまり、4つの乗算器と3つの加算器のリソースが必要です。
SDwarfs 2014年

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, ...

b1 <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], ...

これは同じシーケンスです。

ザイリンクスライブラリプリミティブのハードウェアソリューションでは、2つのDSP48Eをカスケード接続する必要があります。次のポートおよびレジスタ名については、UG193 v3.6の図1-1を参照してください。最初のプリミティブはb1を乗算し、1クロック後に追加します。2つ目は、b1 * b1を掛けて、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番目のDSP48Eの出力

-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に設定します

-DSP48E#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のシーケンス:

x [0]、

x [1] + x [0] * b1

x [2] + x [1] * b1

x [3] + x [2] * b1

reg_p2のシーケンスが望ましい結果です。2番目のDSP48Eの内部で、レジスタreg_m2にはシーケンスがあります。

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

この結果には素晴らしい優雅さがあります。明らかに、DSP48Eは乗算と加算を同じクロックで実行しませんが、それが差分方程式に必要なものです。操作された差分方程式により、DSP48EのMおよびPレジスタを許容し、フルスピードでクロックすることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.