FPGAでの割り算は怖くない
これまで割り算回路は規模が大きくなったりレイテンシが遅くなると思って避けてきたのですが、どうしても割り算を避けられない計算が必要になったので、XILINXのCoreGenに用意されている割り算IPコアを使ってみることにしました。
そのCoreGenのIPコアというのは、Divider Generatorというものです。
設定すべきところはいくつかあるのですが、
- Dividend and Quotient・・割られる数のビット幅
- Divisor Width・・割る数のビット幅
- Remainder Type・・余りの出し方 (余りを出すか小数点以下の計算をするか)
- Fractional Width・・余りのビット幅
- Operand Sign・・符号ありかなしか
- Clocks per Division・・何クロックごとにサンプリングするか
です。詳しいことは後程解説します。
さて、実際に65535/xを計算する回路を作って、BLOGANAを埋め込んで実験してみたところ、下の図のような感じで反比例の関数が描けました。
さて、いったい何クロックで計算してくれているのかを調べてみます。

このRFDという信号は、コアが出力する信号で「今のデータを取り込みますよ」というのを示すものだそうです。この信号が出てから35クロック後に計算結果が出ていました。
「35クロック」はちょっと遅くないかなと思って調べてみたのですが、どうやら正解でした。
この割り算コアは筆算の要領で計算しているのでしょう。だから、割られる数のビット幅が16bitだったら、基本的には16回の繰り返しをするので、16+3クロックかかります。
「あまり」の出し方を「Remainder(あまり)」にするか「Fractional(小数)」にするかの選択があって、Fractionalにすると、もう16クロックかかります。
Remainderなら単純にあまりを計算するだけなのですが、Fractionalという出力は、余りではなく、小数点以下の数値を計算するものということです。
この意味は、たとえば、65535÷3 = 16383.75 です。この0.75を2進数にすると、0.1100000000000000なので、小数点以下を16bitの整数としてみれば49152になるわけです。
もうひとつ例を出します。たとえば、65535÷93を計算させると商は704で、余りは44394と出ます。この44394というのは0.67740…を意味します。
このようにあまりを小数として出すときには、 Fractional = 余り×2^(Fractionalのビット幅)÷割る数 なので、もう1回割り算をしなければいけません。そういうわけで、16クロック余計にかかっていると思われます。
Remainder TypeをRemainderに戻したら、ちゃんと19クロックで計算してくれるようになりました。

それでも、19クロックはかかります。乗算と違ってすぐには出ません。
◆
CoreGenの設定項目で「Clocks per Division」というのがありますが、これは何クロックごとにサンプリングするかを設定するものです。これを1にすると、毎クロックごとに計算してくれます。(RFDは上がりっぱなしになる)
でも、レイテンシは19クロックなので、つまり、中でパイプライン化して処理しているようです。結果が出る前に次のデータを与えても、ちゃんと古いデータを覚えていて計算をしてくれています。
16bit÷16bitの計算で、余りはFractionalとして出すようにした場合の、使用スライス数と、論理合成時間を計ってみました。スライス数は、除数の生成カウンタやロジアナコアも含めたサイズです。結果は以下のとおりです。
| Clocks per Division | slice数 | 論理合成時間 | XC6SLX45の何%を使うか |
| 1 | 365 | 6分55秒 | 5% |
| 2 | 301 | 1分44秒 | 4% |
| 4 | 193 | 1分39秒 | 3% |
| 8 | 130 | 1分32秒 | 2% |
| 除算器なし | 41 | 1分26秒 | 1% |
※XC6SLX45での実験結果
1クロックごとに計算するような設定にすると、論理合成時間が極端に長くなります(特にImprementation)。データが毎クロックごとに到着するのでなければ、Clocks per Divisionはできるだけ大きくしておいたほうが良いでしょう。
逆に、Clocks per Division = 8ならば、このコアを入れても論理合成時間が長くなることはないようです。何も入れない回路と大した差はありません。また、radix-2の設定にしておけば、乗算器も使いません。
◆
XILINXのCoreGenが生成する割り算回路はちゃんと動作してくれます。Clocks per Division = 8ならSliceもそれほど食いませんし、論理合成が極端に長くなることもありません。
乗算と違って1クロック後に結果が出るわけではありませんが、余りを「あまり」として出すならレイテンシは、BIT数+1クロックです。(符号付きの場合は2クロック増える)
※回路構成の選択で、Radix-2ではなくHigh Radixを選択すると、何ビットかまとめて計算してくれるらしく、レイテンシをとても短くできる。たとえば32bit÷16bitなら5クロックで計算可能。ただし、BlockRAMやDSP48A1sを大量に消費する。
結論を言うと、SLICE数や論理合成時間を気にすることなく使っていいと思います。
| 固定リンク





コメント