29 |
Cmod A7の利用 (8) |
レベルダイアグラム
前稿のレベルダイアグラムを変数を用いて書き直したものが図705.1です。これに従いデータ変換器をBSVで開発します。ただし、前稿ではVRの開始角と使用角度範囲を105°, 90°と仮決めしましたが、試行錯誤で変更することを見越してパラメータ化したRTLとします。
- 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に配置した図は以下のとおりで単なる組み合わせ回路です。
このモジュールをダブルクリックすると以下のパラメータ設定画面が表示されます。aとbがすでに設定されているのは、残念ながらbsvにデフォルト値の設定が無いのですが、生成されたverilogのパラメータ文を修正したものです。verilogを10進で修正したため、vivadoでも10進表示となっています。