2016.01.28
Cosmo-Zのアクリルケース入りを作って納品です。

今回のお客様は何かの粒子を飛ばしてTOFを測りたいそうです。
このCosmo-Zで、お客様の研究が成功することを願っています。
FPGA向きのFFTアルゴリズム
2016.01.23
今、FPGAでハードウェアFFTを行わなければならない案件を2つ抱えています。そのうちの1つは、65536ポイント~1Mポイント程度のFFTをつなぎ目なく行うというものです。
FFTのアルゴリズムですが、もっとも基本的な基数2のCooley-Tukeyアルゴリズムを考えてみます。

これは基数2の16ポイントFFTなので、ステージ0,1,2,3と4つあります。
ごく普通のFFTなのですが、これを65536ポイントや1Mポイントでやろうとした場合、厄介なことが生じます。それは、FFTする途中経過のデータを格納するアドレスが連続しないという問題です。
最初のステージでは、データの0と1、2と3・・を演算します。
次のステージでは、データの0と2、1と3・・を演算します。
・・
だんだんバラバラになってきます。
1Mポイントとかとなると、
・アドレス0とアドレス524288を計算
・アドレス1とアドレス524289を計算
・アドレス2とアドレス524290を計算
という風に、読み出す場所がかなり離れてしまいます。
プログラムで書くと、
int b = 2;
for (stage = 0; stage < N; stage++) {
for (i = 0; i < DataLength / b; i++) {
int offset = b * i;
for (j = 0; j < b / 2; j++) {
Complex A = mem[offset + j];
Complex B = mem[offset + j + b / 2] * W[j * DataLength / b];
mem[offset + j] = A + B;
mem[offset + j + b / 2] = A - B;
}
}
b = b * 2;
}
このようになります。アドレスが飛ぶところをbという変数にしていますが、ややこしいですね。シーケンシャルではなく、ランダムアクセスになってしまいます。
FPGA内のBRAMに収まるサイズのFFTなら無理やりできますが、1Mポイントだと内蔵BlockRAMに納まらないのでDDR3などの外部メモリを使うことになります。
DDR3メモリはランダムアクセスが苦手です。つまり、通常のFFTのアルゴリズムでは大きなサイズのFFTがやりにくくなります。
![]()
そこで、私が提案するのは、以下のようなアルゴリズムです。VFFTと呼びます。

VFFTは、普通のCooley-Tukeyのアルゴリズムとやっていること同じなのですが、計算のフローをねじった形になっています。
このFFTでは、データの読み書きするアドレスが独特です。
- アドレス0とアドレス1のデータを演算→アドレス0とアドレス8に格納
- アドレス2とアドレス3のデータを演算→アドレス1とアドレス9に格納
- アドレス4とアドレス5のデータを演算→アドレス2とアドレス10に格納
・・・ - アドレス12とアドレス13のデータを演算→アドレス6とアドレス14に格納
- アドレス14とアドレス15のデータを演算→アドレス7とアドレス15に格納
と、連続した番地へメモリアクセスができます。
計算結果は2本のFIFOを用意すれば、256バイト程度に分けて、連続したアドレスに書き込みができます。
それに嬉しいことにステージが変わっても、読み書きするアドレスは変わらないので、メモリの読み書きアドレスを計算するためのロジックが軽くてすみます。
プログラムで書くと、
Complex *work = new Complex[DataLength];
int mask = ~((2 << (N-2))-1);
for (stage = 0; stage < N; stage++) {
int offset = DataLength/2;
for (j = 0; j < DataLength / 2; j++) {
Complex A = mem[j*2];
Complex B = mem[j*2+1] * W[j & mask];
work[j] = A + B;
work[j + DataLength/2] = A - B;
}
mask = mask >> 1;
for (j = 0; j < DataLength; j++) {
mem[j] = work[j];
}
}
delete[] work;
と、元のFFTは3重のループだったのが、2重のループになっていることがわかります。
メリットは、
- メモリが連続アクセスできる
- ステージが変わってもアドレスの生成規則が変わらない
ということで、FPGA向きだと思います。
欠点は、メモリの読み書きアドレスが異なるので、ワークメモリ用に2倍のメモリを使うことです。
メモリの必要量が2倍になっても気にならない場合には、ぜひ、検討してみてください。
Cosmo-Zの32ch版用のアルミケースを作りました・・と思ったら
2016.01.20
Cosmo-Zの32ch版を作って、タカチのアルミの箱に納めました。
裏面は、このように凹んだパネルの中にコネクタ類があります。
なぜ凹んだリアパネルになっているかというと、タカチの既製品の箱を使っているため、Cosmo-Zの基板のサイズが短いからです。
中身はこうなっています。

このアルミの加工は板金屋さんにお願いしましたが、凹んだリアパネルの設計はアルバイトのスタッフがやってくれました。構造が難解なケースであるにもかかわらず、一発で成功させてくれました。さすが東工大。
なかなかいい感じのケースに仕上がったと思います。
・・と思っていたら、このお客様の要求仕様は、全部のコネクタがLEMOコネクタでした!!! SMAじゃなかった! 作り直し!
ZYNQのAXI HPポートを通じた読み書き速度
2016.01.19
Cosmo-ZでハードウェアFFT回路を作ろうとしています。
FFTする元データと変換後のデータはDDR3メモリにあるので、PLからDDR3メモリにアクセスするにはHPポートというのを使わなければなりません。
AXI HPポート越しにDDR3にアクセスすると、どのくらいの読み書き速度がでるのでしょうか。実験してみました。
![]()
作ろうとしている回路は次のようなものです。バタフライ演算器が2個あって、2chのFFTを同時に実行します。
演算前のデータと演算後のデータはDDR3メモリにあって、ZYNQのPLとPSの間は、250MHz 64bitのAXI HPポートでつないでいます。

![]()
FPGAの中にロジアナのIPコアを埋め込んで、MITOUJTAGを使ってFIFOやAXI HPの信号を見てみました。
まずは、DDR3からの読み出しのみを行ったときの波形です。
上の図で見えているのは、アドレスと長さ(0xff=256QWORD)を与え、arvalidを'1'にして、16回分の転送を開始したところです。
AXIバスがarreadyを'1'にしたときに、自分の回路がarvalidを'1'にすると転送コマンドがセットされます。そして、AXIバスがrvalidを'1'にしたときにDDR3から読み出したデータが送られてきます。
AXIのデータバスは64bitで、1回の転送サイズは256QWORD=2048バイトで、それが16回行われるのですから、全体で32768バイトの転送が行われています。それに要した時間は約20usなので、1638MB/secの速度でメモリから読み出せていることがわかります。
Cosmo-ZのDDR3メモリは32bit幅で533MHzでインタフェースしているので、4264MB/secのバス速度があります。

AXI HPを1chで読み出した場合、実に38%しか活用できていないことになります。
![]()
次に、メモリのReadと並行して、Writeを行ってみました。

先ほどの波形とは違い、AWVALIDなどの書き込み系信号も使っています。
32768バイトの読み出しと、32768バイトの書き込みが並行して行われているのですが、全体で23.6usしかかかっていません。したがって、速度は2777MB/sec出ていることになります。
なんと、メモリのバス速度の65%を活用できていることになります。
![]()
DDR3メモリの読み出しだけだと、あまり帯域は活用できません。
その原因となるのは、
- AXI HPポート1個の読み出し速度が、そもそも2GB/secしかない。
- DDR3メモリに読み出しコマンドを与えてから実際にデータが出てくる(rvalid)まで180nsかかる。(これは45QWORD読み出せる時間で、バス帯域の15%が無駄になる)
だからです。
DDR3の読み出し速度が遅いのではなく、AXI HPポートが遅いのです。
メモリから見ればスカスカなRead要求しかしてこないので、読み書きを同時に行うとバスの使用効率が飛躍的に上がるのでしょう。
![]()
今回は試していませんが、より高速に読み出すためには、
- READ要求にIDを付けて、複数のリクエストをオーバーラップさせる
- 複数のAXI HPポートを使う
といった手が考えられます。
台形型波形整形回路の結果
2016.01.12
台形型波形整形回路を調整しました。
その波形整形の様子をアニメーションGIFにしました。

(クリックで拡大)
このフィルタは、HPFとLPFを組み合わせたようなものなのですが、積分回路のパラメータで時定数を調整できるようになっていて、うまく合わせると台形の頂上の部分が平らになるようになります。
下の図は、バックグラウンドのスペクトルです。
4本のグラフがありますが、オレンジと青の線がプラスチックシンチレータからの信号のパルスハイトを分析したものです。茶色と黄色の線が台形フィルタを通したものです。2つの線はほとんど同じで有意な差はありません。
プラスチックシンチレータの横に塩化カリウムの試薬を置いた状態のスペクトルが下の図です。
青・黄色の線の、横軸50のあたりにピークが見えます。塩化カリウムを置くことでこれらのピークが出たので、40Kからのガンマ線によるものと思われます。
波形整形回路を通してもエネルギーの分解能は向上することも、悪化することもありませんでした。これは、おそらく元の波形のパルスが十分に大きく、非常に綺麗であるため、波形整形回路を通す必要がなかったのだと思います。
ノイズにまみれていたり、ひずみが多いようなセンサの場合に威力を発揮するかもしれません。
逆に言えば、特電のプラスチックシンチレータ+フォトマルでは、これまで、計測が容易なエネルギーの高い波形しか取ってこなかったということです。もっと小さな(エネルギーの低い 10~100KeV領域)の波形取得にも挑戦するべきかもしれません。
台形フィルタとマルチチャネルアナライザ
2016.01.09
FPGAに波形整形回路の台形フィルタを入れて、プラスチックシンチレータからの信号を整形してからMCAに入れてみました。
波形整形回路を入れるとエネルギー分解能が上がるとのことです。
まずは、フィルタを通す前と後の信号。

これは、たまたま2つのシンチレータが同時に発光したときの波形です。CH1とCH4の波形が生の波形、CH1+filterとCH4+filterと書かれた波形がフィルタ後のものです。
何もないときのバックグラウンドのスペクトラムを見てみます。
下の図は、塩化カリウムをプラスチックシンチレータの横に置いたときのスペクトルです。
プラスチックシンチレータなのでスペクトルはいい加減ですが、増えた部分がカリウム40によるものと思われます。
CH1は18くらい、CH4は50くらいのところにピークが出ています。
しかし、フィルタを通すことによって、ピークが鋭くなるどころか、なだらかになって分解能が下がってしまいました。
調整をしなければならないのかもしれません。














