レジスタファイルのシリアライゼーション,プチ実験

データ並列性が活用できる処理では,並行処理した結果を,それぞれのレジスタに格納しておいて最終的にそれをシリアライゼーションして取り出したい,というケースがままあります.

FPGAが大規模になって,かなりたくさんの処理を並べられるなってきた今日このごろ,問題になりそうなのが結果のシリアライゼーションどうするか,という話.

たくさんのレジスタを順になめていくような回路を作ってしまうとマルチプレクサがばかでかくなってしまうように思われます.それを回避するために,たとえばシフトレジスタ的に読み出すようにすればいいかもしれません.実際のところ,どうなの?というのを試してみました.

作りたい回路

おさらいすると,作りたい回路はこんな感じ.

7c541cbc7dafbe47efad2a6027d37750

マルチプレクサで選択する場合には,シリアライゼーションの部分で,カウンタをつかって,レジスタ0〜nまでを順に出力することになります.nが大きい場合には,大きなマルチプレクサが必要になってしまいますね.

シフトレジスタだと

97cf57287ae9b3291d66bbd42c37650e

こうなります.直感的にはnが大きくなっても問題ないように見えますね.

RTL記述

簡単のため,Synthesijer.ScalaでRTL設計します.

マルチプレクサ版はこんな感じ.

シフトレジスタ版はこんな感じ.

 たとえば,レジスタの数が4個の場合のシフトレジスタ版の動作をシミュレーションしてみると,こんな感じ.結果がシリアライゼーションして出力されることが確認できます.

e5ec6952ae00bdc70632c1b83e2d784d

合成してみる

ISE14.7で,KC705のXC7K325T-2をターゲットFPGAとして合成してみることにします.ワード数は,強気の1000個.計算はなしで入出力はI/Oピンに出すことにします.ただし,独立に1000本の32bitデータを入力させるにはピン数が足りないので,入力側はアドレスでデコードします.さらに,1000出力のデコードを一度に行うのはファンアウト的に厳しいので,16個にコピーした上で割り振りました.

Synthesijer.Scala的には,こんな感じ.

結果

リソース使用量

レジスタは,どちらもおよそ32*1000個と想定通りです(当たり前).シフトジスタ版ではLUTがレジスタとほぼ同数必要になります.ただし,使用スライス数は,どちらも同じ程度.これはシフトレジスタ版のレジスタとLUTが,ほぼ100%,同じスライスにマッピングされるからです.

動作周波数

200MHzで制約をかけて合成したところ,マルチプレクス版はワーストケースが5.093n秒とタイミングメットしませんでした.一方シフトレジスタ版は4.6n秒と余裕.

シフトレジスタ版に,制約を3.3n秒に設定して合成すると,ワーストケース3.09n秒と,これまた,かなりいい感じです.

最後に

PlanAheadでみてみると,まだ最適化の余地もありそうな気も…時間をみつけて,こういうアプリケーションでよく使うパタンというののライブラリを充実させていきたいものです.

あ,今回はXilinxでのプチ実験でしたが,Altera版もやっておこう.

ちなみに,合成に利用したソースコードは,それぞれ次の通りです.