このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
HDL 用に最適化した正規化逆数の使用方法
この例では、関数 normalizedReciprocal
および Normalized Reciprocal HDL Optimized ブロックを使用して入力の正規化逆数を計算する方法と、使用のタイミングを示します。
値の逆数は範囲が広くなることがあり、固定小数点型は浮動小数点型に比べて範囲が制限されます。入力値 u
が小さければ 1/u は大きくなり、u が大きければ 1/u は小さくなります。したがって、1/u の固定小数点型には高い精度と広い範囲が求められ、長い語長が必要となります。
逆数と別の変数の積の範囲がわかっているアプリケーションでは、正規化逆数を計算し、それに他の変数を乗算してから、最終的な出力にシフトを適用すると効率的です。これには、たとえば、後退代入でピボット要素による除算が必要な最小二乗のアプリケーションなどが該当します。
正規化逆数の計算
入力を u
とすると、正規化逆数 y
および指数 e
は、次のように計算されます。
(2.^e).*y = 1./u,
および
0.5 < |y| <= 1.
u = 0
で u
が固定小数点またはスケーリングされた double の場合、y = 2 - eps(y)
になります。
u = 0
で u
が浮動小数点型の場合、y = inf
になります。
u~=0
の場合、この関数が返すのは以下と等価になります。
[y,e] = log2(1./abs(double(u))) y(u<0) = -y(u<0)
異なる点はシフトと加算のみを使用して計算されることです。
MATLAB 関数または Simulink ブロックの選択
C コードの生成およびシステムの設計には、MATLAB 関数 normalizedReciprocal
を使用します。この関数ではレイテンシでの計算は行われません。シミュレーションでは、fiaccel
、buildInstrumentedMex
、または codegen
を使用する速度について、関数を MEX ファイルにコンパイルします。
最適化された HDL コードを生成するには、Normalized Reciprocal HDL Optimized
ブロックを使用します。このブロックは HDL において高いスループットを小さい面積で実現できるように最適化されており、生成された HDL コードと同じレイテンシでシミュレーションを行います。
結果の数値出力はブロックと関数で同じです。
MATLAB を使用した正規化逆数の計算
固定小数点入力 u
の正規化逆数を計算し、その値を実際の逆数の値と比較します。
u = fi([-pi,0.01,pi])
u = -3.1416 0.0100 3.1416 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13
[y,e] = normalizedReciprocal(u)
y = -0.6367 0.7806 0.6367 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 14 e = 1x3 int32 row vector -1 7 -1
computed_reciprocal = 2.^double(e).* double(y)
computed_reciprocal = -0.3183 99.9141 0.3183
actual_reciprocal = 1./double(u)
actual_reciprocal = -0.3183 99.9024 0.3183
正規化逆数と実際の逆数の値が近いことがわかります。
Simulink モデルの入力の定義
Normalized Reciprocal HDL Optimized ブロックを使用して、正規化逆数を取得する固定小数点入力 u
を定義します。
x = linspace(0.001,100,100); x = [fliplr(-x),x]; u = fi(x,1,18);
Normalized Reciprocal HDL Optimized ブロックのレイテンシ
Normalized Reciprocal HDL Optimized ブロックは、二分探索を使用する入力を正規化することで機能します。二分探索のレイテンシは入力の語長の約 log2、それに続く CORDIC 逆数カーネルのレイテンシは入力の語長とほぼ同じです。
Normalized Reciprocal HDL Optimized ブロックは、常にデータを受け入れる準備ができています。最初のレイテンシの後、サンプルごとに有効なサンプルが出力されます。固定小数点入力 u
のサンプルのレイテンシは次のとおりです。
D = ceil(log2(u.WordLength)) + u.WordLength + 5
この例に含まれている関数 normalizedReciprocalLatency
を使用して、固定小数点、double、または single の数値型の入力のレイテンシを計算できます。
入力サンプルを Normalized Reciprocal HDL Optimized ブロックの出力と合わせるには、レイテンシ D
を遅延で使用します。
D = normalizedReciprocalLatency(u)
D = 28
正規化逆数 Simulink モデルの実行
逆数と別の変数の積の範囲がわかっている簡単な例として、値の正規化逆数を計算し、それにその値自体を乗算します。この最終的な積は 1 と等しくなるはずです。入力値と逆数の範囲が広い場合でも、値とその逆数の積は既知の範囲になります。
0.5 < abs(y) <= 1
であり、積の大きさがこれよりも大きくなることはないため、積 u*y
は u
と同じ型で計算できることに注意してください。
model = 'NormalizedReciprocalModel';
open_system(model)
out = sim(model);
正規化逆数 Simulink モデルの結果の解析
次のプロットから、入力 u
と逆数 1/u
の範囲が広いのに対し、正規化逆数 y
の範囲は -1 ~ 1 であることがわかります。
入力 u
は -100 ~ 100 の範囲の fi 値のベクトルです。
normalizedReciprocalPlot(1,u,out.y,out.e,out.z);
逆数 1/u
の実際の値は正規化逆数 (2.^e).*y
とほぼ同じです。逆数 1/u
は範囲が広いため、直線的な逆数を固定小数点で計算するにはハイ ダイナミック レンジのデータ型 (つまり語長と小数部が長いデータ型) が必要になります。
normalizedReciprocalPlot(2,u,out.y,out.e,out.z);
正規化逆数 y
の範囲は次のとおりです。
0.5 < |y| <= 1
u
と同じ語長のデータ型に効率的かつ正確に格納できます。y
の数値型の小数部の長さは u
の語長よりも 2 短くなります。この追加の整数ビットにより、y
の正または負の区別に加え、値 -1 および +1 を正確に表現できます。
normalizedReciprocalPlot(3,u,out.y,out.e,out.z);
正規化指数 e
と入力 u
の大きさは逆相関関係にあります。u
の大きさが大きいと、e
は大きい負の値になります。u
がゼロに近いと、e
は大きい正の値になります。この関係を次に示します。
(2.^e).*y = 1./u,
normalizedReciprocalPlot(4,u,out.y,out.e,out.z);
このモデルでは、正規化逆数 y
に入力 u
を乗算し、e
でシフトして結果をスケーリングしています。y
の大きさは 1 より小さいため、u
の固定小数点型で積を計算できます。出力 z = 2^e (y * u) は 1 とほぼ等しくなります。
normalizedReciprocalPlot(5,u,out.y,out.e,out.z);
正規化逆数を固定小数点データ型で計算した結果として、出力 z
には僅かな丸め誤差があります。
normalizedReciprocalPlot(6,u,out.y,out.e,out.z);