FPGAで固定小数点atan2を計算する方法


12

atan2(x,y)データの連続入出力ストリームを備えたFPGA での計算が必要です。展開されたパイプライン化されたCORDICカーネルを使用して実装できましたが、必要な精度を得るために、32回の反復を実行する必要がありました。これにより、この1つのタスク専用のかなり大量のLUTが作成されました。部分的に展開されたCORDICカーネルを使用するようにフローを変更しようとしましたが、連続した入出力フローを維持しながら繰り返しループを実行するには逓倍クロック周波数が必要でした。これで、タイミングを合わせることができませんでした。

だから今、私はコンピューティングの代替方法を求めていますatan2(x,y)

補間でブロックRAMルックアップテーブルを使用することを考えましたが、2つの変数があるため、ルックアップテーブルの2次元が必要になります。これは、ブロックRAMの使用に関して非常にリソースを消費します。

次に、象限調整にatan2(x,y)関連する事実を使用することを考えましたatan(x/y)。これに関する問題は、定数ではないx/yため真の除算が必要であり、yFPGAでの除算は非常にリソースを消費することです。

atan2(x,y)LUTの使用量を削減する一方で、優れた精度を提供するFPGA に実装する新しい方法はありますか?


2
処理クロックレートと入力データレートは何ですか?
ジム・クレイ

必要な精度はどれくらいですか?また、固定小数点計算を使用していると思います。どのビット深度を使用していますか?象限調整による多項式近似(またはLUT)は、実装する一般的な方法atan2です。ただし、部門がなくてもうまくいくかどうかはわかりません。
ジェイソンR

入力クロックは150MHz、入力データレートは150 MSamps /秒です。基本的に、クロックサイクルごとに新しい入力を取得します。レイテンシーは問題ありませんが、150 MSamps /秒の出力も生成する必要があります。
user2913869

私のシミュレーションでは、約1 * 10 ^ -9で生きることができます。絶対最小固定小数点ビットはわかりませんが、Q10.32固定小数点形式でシミュレーションを行っています
-user2913869

この記事では、の固定小数点実装について説明しatan2ます。それでも分割が必要になります。
マットL.

回答:


20

対数を使用して、除算を取り除くことができます。以下のための(x,y)第1象限に:

z=log2(y)log2(x)atan2(y,x)=atan(y/x)=atan(2z)

atan(2^z)

図1. atanのプロット2 zatan(2z)

あなたはおおよそのに必要となるatan(2z)の範囲内30<z<30 1E-9のあなたに必要な精度を得るために。対称性atan 2 z= πを利用できますatan(2z)=π2atan(2z)または(x,y)が既知のオクタントにあることを確認します。log2(a)を近似するには

b=floor(log2(a))c=a2blog2(a)=b+log2(c)

bは、最上位の非ゼロビットの位置を見つけることで計算できます。cはビットシフトで計算できます。あなたはおおよそのに必要となるlog2(c)の範囲で1c<2

log2(c)

図2. ログ2のプロットc log2(c)

あなたの精度要件、線形補間及び均一サンプリングのために214+1=16385のサンプルlog2(c)及び30×212+1=122881の試料atan(2z)のために0<z<30十分です。後者のテーブルはかなり大きいです。これにより、補間による誤差はz大きく依存します。

Error of atan(2^z) approximation

図3 atan(2z)の異なる範囲に対する近似最大絶対誤差zの単位期間あたりのサンプル数が異なるため(横軸)(8192から32)z。最大絶対誤差0z<1(省略)わずかに小さいためよりもfloor(log2(z))=0

atan(2z)の表は対応することが、複数のサブテーブルに分割することができ0z<1と異なるfloor(log2(z))z1を計算することは容易です。テーブルの長さは、図3に示すように選択できます。サブテーブル内インデックスは、単純なビット文字列操作で計算できます。精度の要件については、zの範囲を0に拡張すると、atan(2z)サブテーブルには合計29217サンプルが含まれますz0z<32簡単にするために。

後で参照するために、近似誤差の計算に使用した不格好なPythonスクリプトを以下に示します。

from numpy import *
from math import *
N = 10
M = 20
x = array(range(N + 1))/double(N) + 1
y = empty(N + 1, double)
for i in range(N + 1):
    y[i] = log(x[i], 2)

maxErr = 0
for i in range(N):
    for j in range(M):
        a = y[i] + (y[i + 1] - y[i])*j/M
        if N*M < 1000: 
            print str((i*M + j)/double(N*M) + 1) + ' ' + str(a)
        b = log((i*M + j)/double(N*M) + 1, 2)
        err = abs(a - b)
        if err > maxErr:
            maxErr = err

print maxErr

y2 = empty(N + 1, double)
for i in range(1, N):
    y2[i] = -1.0/16.0*y[i-1] + 9.0/8.0*y[i] - 1.0/16.0*y[i+1]


y2[0] = -1.0/16.0*log(-1.0/N + 1, 2) + 9.0/8.0*y[0] - 1.0/16.0*y[1]
y2[N] = -1.0/16.0*y[N-1] + 9.0/8.0*y[N] - 1.0/16.0*log((N+1.0)/N + 1, 2)

maxErr = 0
for i in range(N):
    for j in range(M):
        a = y2[i] + (y2[i + 1] - y2[i])*j/M
        b = log((i*M + j)/double(N*M) + 1, 2)
        if N*M < 1000: 
            print a
        err = abs(a - b)
        if err > maxErr:
            maxErr = err

print maxErr

y2[0] = 15.0/16.0*y[0] + 1.0/8.0*y[1] - 1.0/16.0*y[2]
y2[N] = -1.0/16.0*y[N - 2] + 1.0/8.0*y[N - 1] + 15.0/16.0*y[N]

maxErr = 0
for i in range(N):
    for j in range(M):
        a = y2[i] + (y2[i + 1] - y2[i])*j/M
        b = log((i*M + j)/double(N*M) + 1, 2)
        if N*M < 1000: 
            print str(a) + ' ' + str(b)
        err = abs(a - b)
        if err > maxErr:
            maxErr = err

print maxErr

P = 32
NN = 13
M = 8
for k in range(NN):
    N = 2**k
    x = array(range(N*P + 1))/double(N)
    y = empty((N*P + 1, NN), double)
    maxErr = zeros(P)
    for i in range(N*P + 1):
        y[i] = atan(2**x[i])

    for i in range(N*P):
        for j in range(M):
            a = y[i] + (y[i + 1] - y[i])*j/M
            b = atan(2**((i*M + j)/double(N*M)))
            err = abs(a - b)
            if (i*M + j > 0 and err > maxErr[int(i/N)]):
                maxErr[int(i/N)] = err

    print N
    for i in range(P):
        print str(i) + " " + str(maxErr[i])    

関数近似から極大誤差f(x)直線的に補間することにより、FX のサンプルからF xが、間隔のサンプリングとの均一なサンプリングによって撮影されたΔ X、によって解析的に近似することができます。f^(x)f(x)Δx

f^(x)f(x)(Δx)2limΔx0f(x)+f(x+Δx)2f(x+Δx2)(Δx)2=(Δx)2f(x)8,

f(x)f(x)x

atan^(2z)atan(2z)(Δz)22z(14z)ln(2)28(4z+1)2,log2^(a)log2(a)(Δa)28a2ln(2).

関数は凹であり、サンプルは関数と一致するため、エラーは常に一方向になります。エラーの符号がサンプリング間隔ごとに1回ずつ交互に行われると、極大絶対誤差は半分になります。線形補間では、次の方法で各テーブルを事前フィルタリングすることにより、最適な結果に近づけることができます。

y[k]={b0x[k]+b1x[k+1]+b2x[k+2]if k=0,c1x[k1]+c0x[k]+c1x[k+1]if 0<k<N,b2x[k2]+b1x[k1]+b0x[k]if k=N,

xy0kNc0=98,c1=116,b0=1516,b1=18,b2=116c0,c1N

(Δx)NlimΔx0(c1f(xΔx)+c0f(x)+c1f(x+Δx))(1a)+(c1f(x)+c0f(x+Δx)+c1f(x+2Δx))af(x+aΔx)(Δx)N={(c0+2c11)f(x)if N=0,|c1=1c020if N=1,1+aa2c02(Δx)2f(x)if N=2,|c0=98

0a<1f(x)f(x)=exb0,b1,b2

(Δx)NlimΔx0(b0f(x)+b1f(x+Δx)+b2f(x+2Δx))(1a)+(c1f(x)+c0f(x+Δx)+c1f(x+2Δx))af(x+aΔx)(Δx)N={(b0+b1+b21+a(1b0b1b2))f(x)if N=0,|b2=1b0b1(a1)(2b0+b12)Δxf(x)if N=1,|b1=22b0(12a2+(2316b0)a+b01)(Δx)2f(x)if N=2,|b0=1516

0a<1

Approximation error with and without prefilter and end conditioning

log2(a)

この記事では、R。グティエレス、V。トーレス、およびJ.バルズの「対数変換とLUTベースの手法に基づくatan(Y / X)のFPGA実装Journal of Systems Architecture、vol 。56、2010。要約では、その実装は、速度においては以前のCORDICベースのアルゴリズム、フットプリントサイズにおいてはLUTベースのアルゴリズムに勝ると述べています。


3
Matthew Gambrellと私は1985年のYamaha YM3812サウンドチップをリバースエンジニアリングし(顕微鏡による)、同様のlog / exp読み取り専用メモリ(ROM)テーブルを見つけました。ヤマハは、各テーブルの2番目のエントリを前のエントリとの差で置き換えるという追加のトリックを使用していました。スムーズな関数の場合、差は関数よりも少ないビットとチップ面積で表現できます。彼らはすでにチップ上に加算器を持っていて、それを使って前のエントリに違いを加えることができました。
オリニーミタロ

3
どうもありがとうございました!数学的な性質のこの種の悪用が大好きです。私は間違いなくこれのいくつかのMATLABシミュレーションを開発し、すべてがうまく見えたら、HDLに移ります。すべてが完了したら、LUTの節約を報告します。
user2913869

私はあなたの説明をガイドとして使用しましたが、LUTによってほぼ60%削減されたことに満足しています。BRAMを減らす必要があったので、不均一なサンプリングを行うことでATANテーブルで一貫した最大エラーを取得できることがわかりました。複数のLUT BRAM(すべて同じアドレスビット数)があり、ゼロ、サンプリングが高速。テーブルの範囲を2の累乗になるように選択したため、どの範囲にあるかを簡単に検出し、ビット操作を介して自動テーブルインデックスを作成できます。私は同様に黄褐色の対称性を適用したので、波形の半分しか保存しませんでした。
user2913869

また、編集内容の一部を見逃しているかもしれませんが、2 ^ zを2 ^ {if} = 2 ^ i * 2 ^ {0.f}に分割して実装することができました。ここで、iは整数部分で、fは小数部分。2 ^ iは単純で、ビット操作だけで、2 ^ {0.f}の範囲は限られているため、補間を使用したLUTに適しています。負のケースも処理しました:2 ^ {-if} = 2 ^ {-i} * 1 /(2 ^ {0.f}。したがって、1/2 ^ {0.f}のもう1つのテーブルです。次のステップlog2(y)LUTに2のレンジング/不均一サンプリングの累乗を適用することは、その種の事柄に最適な候補波形になると思われるためです。乾杯!
-user2913869

1
笑うん 今から試してみます。さらに多くのLUTとさらに多くのBRAMを保存する必要があります
-user2913869
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.