ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

IIR フィルターの浮動小数点から固定小数点への変換

この例では、IIR フィルターを浮動小数点から固定小数点の実装に変換する方法を示します。二次型 (または "双二次") の構造は、伝達関数を直接実装する構造よりも、固定小数点演算を使用する場合にうまく機能します。ここでは、"浮動から固定" の変換を成功させるための最も確実な方法を説明します。この方法は、以下の 2 つの手順で構成されています。

  • 2 次セクション型構造の選択

  • フィルターの各ノードに対するダイナミック レンジ解析の実行

「FIR フィルターの浮動小数点から固定小数点への変換」も参照してください。

ローパス チェビシェフ I 型フィルターの設計

この例では、最小次数ローパス チェビシェフ I 型設計を使用します。フィルターの設計仕様は、以下のとおりです。

  • 通過帯域周波数エッジ:0.4*pi

  • 阻止帯域周波数エッジ:0.45*pi

  • 通過帯域リップル:0.5 dB

  • 阻止帯域の減衰:80 dB

f = fdesign.lowpass('Fp,Fst,Ap,Ast',0.4,0.45,0.5,80);
Hdf1sos = design(f, 'cheby1', 'FilterStructure', 'df1sos');

手順 1: 2 次セクション型構造の選択

ここでは、伝達関数への変換が、固定小数点演算が使用される場合に (浮動小数点演算が使用される場合であっても) 適切でない理由を説明します。まず、フィルターを作成します。

[b,a] = tf(Hdf1sos);
Hdf1 = dfilt.df1(b,a);

ここで、演算を固定に設定します。係数を表すために 16 ビットを使用し、小数部の長さをオートスケールします。量子化された係数のあるフィルターの周波数応答が、基準となる倍精度フィルターの周波数応答からまったく遠いところにあることに注意してください。

Hdf1.Arithmetic = 'fixed';
hfvt = fvtool(Hdf1,'legend','on');
legend(hfvt,'Direct-Form I')

このため、伝達関数はお勧めできません。その代わりに、2 次セクション型 (SOS) を量子化します。この場合、量子化されたフィルターと基準のフィルターの周波数応答がかなりの倍率で拡大しない限り区別が付かないほど似ていることがわかります。

Hdf1sos.Arithmetic = 'fixed';
setfilter(hfvt,Hdf1sos);
axis([0 1 -120 5])
legend(hfvt,'Direct-Form I SOS', 'Location','NorthEast')

ここで紹介したような量子化されたフィルターの良好な周波数応答の取得は、データを適切にフィルターするために必要な手順ですが、それだけでは不十分です。[-1, 1) の範囲で乱数データを使用して、フィルター処理し比較対照してみます。

rng(5,'twister');
q = quantizer([10,9],'RoundMode','round');
xq = randquant(q,1000,1);
x = fi(xq,true,10,9);

さらに、ターゲットとしているハードウェアには、ガード ビットのない加算器があることが前提とされています。

Hdf1sos.AccumWordLength = Hdf1sos.ProductWordLength;

次に、最小値/最大値およびオーバーフローのログ作成をオンにし、作成したテスト データをフィルター処理します。フィルター処理は、量子化済み係数を使用して行いますが、演算は倍精度、浮動小数点演算を使用して実行されます。固定小数点設定の許容範囲は保持されているため、いくつの値が範囲外であるかを観察できます。

fipref('LoggingMode', 'on', 'DataTypeOverride', 'ScaledDoubles');
y = filter(Hdf1sos,x);
fipref('LoggingMode', 'off', 'DataTypeOverride', 'ForceOff');
R = qreport(Hdf1sos)
 
R =
 
 
                                             Double-Precision Floating-Point Report                           
                 ---------------------------------------------------------------------------------------------
                      Min              Max       |        Fixed-Point Range        |             Out of Range
                 ---------------------------------------------------------------------------------------------
         Input:              -1       0.99414063 |             -1       0.99996948 |              0/1000 (0%)
        Output:      -1.0284968        1.0587401 |            -16        15.999512 |              0/1000 (0%)
    Num States:      -308.58311        300.33067 |             -1       0.99996948 |        12137/20000 (61%)
    Den States:      -1985.4018        1932.3062 |             -1       0.99996948 |         8207/20000 (41%)
      Num Prod:      -617.16623        600.66134 |             -8                8 |        14258/30000 (48%)
      Den Prod:      -1983.9633        2038.4784 |             -4                4 |        13733/20000 (69%)
       Num Acc:      -845.46965        818.80068 |            -32               32 |        16883/20000 (84%)
       Den Acc:      -1985.4018        2038.4784 |            -16               16 |       20000/20000 (100%)

フィルター処理操作の各ステージに大量のオーバーフロー値があることに注意してください。オーバーフローの問題を低減するための手段として、使用できるスケーリング基準のいずれかを使用して 2 次セクション型フィルターをスケーリングすることが挙げられます。フィルター処理操作は、最も厳密なスケーリングである 'l1' を選択した場合、オーバーフローする外れ値が最も少なくなりますが、この厳密な正規化によって最悪の S/N 比 (SNR) が発生します。Linf スケーリングは、オーバーフロー防止と SNR の間で良好なバランスを取れるため、実践で最も一般的に使用されるスケーリングです。このため、実践例としてこのスケーリングを使用します。

それでは、2 次セクション型スケーリング ノルムを 'Linf' に設定してみます。この設定は、Hdf1sos のスケール メソッドを以下のように呼び出して実行できます。

scale(Hdf1sos,'Linf');

または、適切なパラメーターのある設計法を以下のように呼び出しても実行できます。

Hdf1sos = design(f, 'cheby1', 'FilterStructure', 'df1sos', ...
    'SOSScaleNorm','Linf');

これで、2 次セクション型スケーリングの 'Linf' への設定が終わりました。ここで、オーバーフロー解析を以下のように繰り返してみます。

Hdf1sos.Arithmetic = 'fixed';
Hdf1sos.AccumWordLength = Hdf1sos.ProductWordLength;
fipref('LoggingMode', 'on', 'DataTypeOverride', 'ScaledDoubles');
y = filter(Hdf1sos,x);
fipref('LoggingMode', 'off', 'DataTypeOverride', 'ForceOff');
R = qreport(Hdf1sos)
 
R =
 
 
                                             Double-Precision Floating-Point Report                           
                 ---------------------------------------------------------------------------------------------
                      Min              Max       |        Fixed-Point Range        |             Out of Range
                 ---------------------------------------------------------------------------------------------
         Input:              -1       0.99414063 |             -1       0.99996948 |              0/1000 (0%)
        Output:      -1.0288827        1.0591385 |            -16        15.999512 |              0/1000 (0%)
    Num States:              -1       0.99414063 |             -1       0.99996948 |             0/20000 (0%)
    Den States:      -1.0288827        1.0591385 |             -1       0.99996948 |             2/20000 (0%)
      Num Prod:     -0.48666099       0.51742745 |             -2                2 |             0/30000 (0%)
      Den Prod:       -1.221679        1.1933533 |             -4                4 |             0/20000 (0%)
       Num Acc:     -0.94522508       0.97998685 |             -8                8 |             0/20000 (0%)
       Den Acc:      -1.4690041        1.5583651 |            -16               16 |             0/20000 (0%)

このレポートには、オーバーフローの件数が大幅に減少されたことがはっきりと示されています。実際、範囲外の値は、分母の状態のみで発生していることがわかります。2 次セクション型スケーリングによってオーバーフローの件数が大幅に減少したのは事実ですが、これらの発生する可能性があるオーバーフローがフィルター処理操作で問題を引き起こす場合があります。'Linf' ノルムの使用によってオーバーフローを完全に回避することはできませんでしたが (これは、フィルターにオーバーフローを発生させるまで累積される可能性のある非線形位周波数のコンポーネントがあるため)、オーバーフローの発生件数を大幅に減少しました。前述のとおり、オーバーフローを完全に排除するには、さらに厳密な 'l1' スケーリングが必要です。しかし、この 'l1' スケーリングは、SNR を大幅に減少することがあるため通常使用されません。次の手順 2 では、オーバーフローを完全に排除するよりよい方法について説明します。

手順 1 では、適切な 2 次セクション型フィルター構造の選択と、スケーリング基準の選択を説明しました。

手順 2: ダイナミック レンジ解析の実行

IIR フィルターの固定小数点変換のための 2 番目の手順では、ダイナミック レンジ解析をフィルターに適用して各ノードのスケーリングを微調整する方法を説明します。浮動小数点シミュレーションで取得された最大値および最小値を使用して、シミュレーション範囲がカバーされ、かつ、精度が最大化するように小数部の長さを設定します。語長は変化しません。

Hdf1sosf = autoscale(Hdf1sos,x);

フィルターを以下のように固定小数点で実行することで、設定が適切であることを確認できます。

fipref('LoggingMode', 'on', 'DataTypeOverride', 'ForceOff');
y = filter(Hdf1sosf,x);
fipref('LoggingMode', 'off');
R = qreport(Hdf1sosf)
 
R =
 
 
                                                  Fixed-Point Report                                          
                 ---------------------------------------------------------------------------------------------
                      Min              Max       |              Range              |      Number of Overflows
                 ---------------------------------------------------------------------------------------------
         Input:              -1       0.99414063 |             -1       0.99996948 |              0/1000 (0%)
        Output:      -1.0288696        1.0595703 |             -2         1.999939 |              0/1000 (0%)
    Num States:              -1       0.99414063 |             -1       0.99996948 |             0/20000 (0%)
    Den States:      -1.0288696        1.0595703 |             -2         1.999939 |             0/20000 (0%)
      Num Prod:     -0.48684623       0.51724424 |             -2                2 |             0/30000 (0%)
      Den Prod:      -1.2222208        1.1936579 |             -8                8 |             0/20000 (0%)
       Num Acc:     -0.94556686       0.97967018 |             -2                2 |             0/20000 (0%)
       Den Acc:      -1.4688253        1.5591116 |             -8                8 |             0/20000 (0%)

この入力信号に対するすべてのオーバーフローがこれで排除されました。さらに、固定小数点レポートを詳細に検討すると、分母係数の乗算とアキュムレータ用に 2 つの最も重要なビットが使用されていないことがわかります。

さらに、振幅応答推定は、丸めのノイズによるフィルター出力のパワー スペクトル密度とともに、固定小数点フィルターが倍精度浮動小数点基準に非常に近い結果を出すことを裏付けています。

close(hfvt);
fvtool(Hdf1sosf,'Analysis','magestimate');
fvtool(Hdf1sosf,'Analysis','noisepower');

まとめ

ここでは、浮動小数点 IIR フィルターを固定小数点実装に変換する簡単な 2 段階の手順を説明しました。DSP System Toolbox™ のフィルター オブジェクトには、自動的かつ動的に内部信号をスケーリングする 'オートスケール' 機能が装備されています。さらに、'qreport' や 'fvtool' のさまざまな解析などの関数を使用することで、このプロセスの各手順で確認を実行できます。

この情報は役に立ちましたか?