Posts Tagged with "FPGA"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.

Cmod A7の利用 (8)

posted by sakurai on November 29, 2023 #705

レベルダイアグラム

前稿のレベルダイアグラムを変数を用いて書き直したものが図705.1です。これに従いデータ変換器をBSVで開発します。ただし、前稿ではVRの開始角と使用角度範囲を105°, 90°と仮決めしましたが、試行錯誤で変更することを見越してパラメータ化したRTLとします。

図%%.1
図705.1 レベルダイアグラム

  • VRの全角度は300°
  • VRの使用角はパラメータ化し、開始角a[°]、範囲b[°]
  • VRの全角度の際のADC入力電圧はLTSpiceの結果より、0.2~0.94[V]

これらより、使用電圧は開始角の値を$V_\text{a}$、終了角の値を$V_\text{a+b}$として、

  • $V_\text{L}=0.2$, $V_\text{H}=0.94$
  • $V_\text{range}=V_\text{H}-V_\text{L}=0.74$
  • $V_\text{a}=\frac{V_\text{range}}{300}a+V_\text{L}$
  • $V_\text{a+b}=\frac{V_\text{range}}{300}(a+b)+V_\text{L}$

次にAD変換後のデータDは入力全範囲0~1[V]を4096分割する。開始角の値を$D_\text{a}$、終了角の値を$D_\text{a+b}$として

  • $D_\text{a}=4096V_\text{a}=\frac{4096V_\text{range}}{300}a+4096V_\text{L}=10.1a+819.2$
  • $D_\text{a+b}=4096V_\text{a+b}=10.1(a+b)+819.2$
  • $D_\text{range}=10.1b$

一方、y座標の制約は以下のとおりであり、上限$y_\text{top}$と下限$y_\text{bottom}$の値でクリッピングが必要。

  • $y_\text{bottom}=44$, $y_\text{top}=186$
  • $y_\text{range}=y_\text{top}-y_\text{bottom}=142$

これらからy座標を求めると、ADCのデータを$D$とすれば、

  • $y=\frac{y_\text{range}}{D_\text{range}}(D-D_\text{a})+y_\text{bottom}=\frac{142}{10.1b}D-\frac{142}{b}a-\frac{142\cdot 819.2}{10.1b}+44\\ =\frac{224.9}{b\ll4}D-\frac{142}{b}a-\frac{11514}{b}+44=\frac{225D-2272a-184216}{b\ll4}+44$

y式中のシフトは固定小数点演算を行うために分母分子を16倍しているものです。さらに最小値$D_\text{a}$、最大値$D_\text{a+b}$で入力ADCデータのクリッピングを行います。

  • $D_\text{a}=10.1a+819.2=(162a+13107)\gg4$
  • $D_\text{a+b}=10.1(a+b)+819.2=(162(a+b)+13107)\gg4$

以上より、完成したBSVコードは以下のとおりです。

 package FixedPointConverter;

    import Vector::*; // ベクター操作のためのモジュール

    interface ConverterIfc;
        method Bit#(12) convert(Bit#(12) adcValue);
    endinterface

    // ADCの値から座標に変換する演算器(固定小数点演算を使用)
    (* synthesize, always_ready, always_enabled, no_default_clock, no_default_reset *)
    module mkFixedPointConverter #(
        parameter Bit#(12) a,  // 角度の最小値
        parameter Bit#(12) b   // 角度範囲
    ) (ConverterIfc);

        method Bit#(12) convert(Bit#(12) adcValue);
            // パラメータの拡張
            Bit#(20) extendedA = zeroExtend(a);
            Bit#(20) extendedB = zeroExtend(b);

            // 座標の下限と上限に対応するADC値の計算
            Bit#(20) adcMinValue = (162 * extendedA + 13107) >>4;     // Min = 10.1A + 819.2
            Bit#(20) adcMaxValue = (162 * (extendedA + extendedB) + 13107) >> 4; // Max = 10.1(A+B) + 819.2
            // クリッピング処理
            Bit#(12) clippedAdcValue = (adcValue < truncate(adcMinValue)) ? truncate(adcMinValue) :
                                      (adcValue > truncate(adcMaxValue)) ? truncate(adcMaxValue) :
                                      adcValue;

              Bit#(24) coordinate = ((zeroExtend(clippedAdcValue) * 225
                                   - zeroExtend(extendedA) * 2272 - 184216)
                                   / zeroExtend(extendedB) >> 4) + 44;

            return truncate(coordinate);
        endmethod

    endmodule
endpackage: FixedPointConverter

これをVivadoに配置した図は以下のとおりで単なる組み合わせ回路です。

図%%.2
図705.2 変換器

このモジュールをダブルクリックすると以下のパラメータ設定画面が表示されます。aとbがすでに設定されているのは、残念ながらbsvにデフォルト値の設定が無いのですが、生成されたverilogのパラメータ文を修正したものです。verilogを10進で修正したため、vivadoでも10進表示となっています。

図%%.3
図705.3 パラメータ設定画面

左矢前のブログ 次のブログ右矢


ページ: