7シリーズFPGAのBUFMRを有効活用する

Xilinxの7シリーズFPGAを使用していると、Implementation時にCLOCK_DEDICATED_ROUTE=BACKBONEを設定しないと他のクロックリージョンのCMTを駆動できないよ、といったエラーが出ることがあります。

多くの場合、下図(Kintex-7 160T)を例とすると、Bank15とBank14のCMTを同一のクロックで駆動しようとしたときに、このエラーが発生します。

“Clock Region”

このような場合、もちろんメッセージに従ってCLOCK_DEDICATED_ROUTE=BACKBONEを指定することも可能ですが、 “その場合は最適ではないよ(sub-optimal)“といった怪しい内容を承諾することになります。

でも実は、それ以外にもあまり知られていない(かもしれない)逃げ道があるのです。

それはBUFMRを使用することです。BUFMRは、入力されたバンクの上下も駆動できます。 例えば、上図でBank15(のMRCCピン)に入力されたクロックは、Bank16, Bank14のCMTを駆動することができます。

それで、MRCC pin->BUFMR->BUFR->CMTというように接続すれば、Bank15に入力されたクロックでBank14-16のCMTをエラー無く駆動することができます。

SRCCにクロックが入力されていた場合は… 残念ですが、CLOCK_DEDICATED_ROUTE=BACKBONEを指定してください。

ADC基板の電源測定

オシロスコープを入手したので、早速電源のノイズをみてみました。

ノイズ測定をするにあたって、正確な測定のためには、GNDクリップは使用しないで、 直近のGNDで測定しないと意味がないようですが、ノイズの大きさの傾向だけはつかめるかと思いました。

Z-turn boardから送られてくる3.3V電源。これはスイッチング電源の出力です。

"+3.3V"

上記電源がFBを通過した後の様子

"+3.3V"

相当ノイズは減っているように見受けられます。

次に、LDO出力の3.0V(上の二枚と異なり、垂直軸が10mVレンジなのに注意)

"+3.0V"

上記がFBを通過した後の様子

"+3.0V"

スイッチング電源ではないのでFBはいらなかったかもしれません。

いずれにしても、LDO出力のノイズが大きすぎるような気がします。 全くノイズが減少しているように見受けられません。

急ぎで製作してしまったので、LDOの推奨レイアウトのようにベタにしなかったのがまずかったのか、 それともそのほかの理由があるのか検討しないといけませんね。

2017/7/28 追記: 今になって分かったのですが、LDOは一般的に数百kHz以上のノイズについてはほとんどフィルタの役割を果たしません。そういった周波数帯のノイズを除去したいのであれば、ちゃんとしたフィルタを通す必要があります。 上記の結果はそれを確認していることになります。

また、LDOでできるだけノイズを除去したいのであれば、ドロップアウト電圧も1V以上とることが推奨されるようです。 あまりにドロップアウト電圧が小さいと、ノイズ除去能力も低減します。

上記のような内容は、LDOのデータシートをよーく読めばわかります。また、LDOに使用されているオペアンプの特性からしても、 高周波のノイズ除去はできないのは明らかそうです。

SiglentのDSOを購入

FMステレオ復調のところは、時間が無くて取り組めていません。

その間に、基板の性能の方を調べて見たくなり、いろいろとオシロスコープを物色しました。

最初はTektronixの中古をヤフオクなどで落とそうかと思ったのですが、最終的には新品を購入してしまいました。

大体100MHzの帯域が測定できる必要があります。それと、FFTも欲しいです。 安くて確実そうなのはRIGOLのDS1054Zかと思いましたが、 最終候補になったのは、HantekのDSO5102Bと、 SiglentのSDS1202X-Eでした。 前者は大体339USD, 後者は379USD程度です。

SDS1202X-Eは、I2C, SPI, UART, CANなどの信号のデコード機能も持っているのが優位点でした。 また、SDS1202X-Eの方が新しいです。こちらによると、Zynqの7020を使用しているようです。

結局、SDS1202X-Eを購入しました。最初はAmazon.comから買おうかと思いましたが、 調べてみたらAliExpressにて送料無料で購入できることがわかり、 そちらに出店していたSains Electronix Storeから購入しました。 6/15(木)の夜に注文して、6/19(月)には到着しました。早いです。

(2019/1/12現在、日本のAmazonからも購入できるみたいです)

注文したら、すぐにお店から、“USコードを選択していたけど、EUコードしか在庫がないんだよ。 USコードは2週間待ちなんだけど、EUコードで送っても良いかい? (意訳)“という内容のメッセージが届きました。 “いやいや、待っても良いからUSコードでお願い。でもできるだけ早くね! (意訳)“と返しました。 そうしたら翌日6/16(金)には発送のお知らせが来たので、まさかEUコードが添付されているのではないか、 とはらはらしましたが、到着した商品を確認したら、ちゃんとUSコードが添付されていました。

うっかりしていたのは、このコードは3ピンタイプだったので、家にある電源プラグに接続するために変換プラグを購入する必要がありました。こういうやつですね。 あるいは3ピン2ピンケーブルでも良いですね。

AliExpressは初めて使いましたが、楽天のように店舗によって対応がまちまちのようです。 今回使用した店舗は迅速で満足でした。Web上での評価も高いようです。梱包も問題ありませんでした。

“同梱物”

当たり前ですが、プローブが2本ついています。写っていませんが、USBケーブルも添付されていました。

“SDS1202X-E”

オシロ本体です。とりあず、電源を入れてプローブ補正だけしました。

早速ADC基板を少し測定してみました。 基板に電源は投入せずに、FMアンテナを接続して、BPFの後の個所にプローブを当て、FFTをしてみた結果が次になります。 ちなみに、GNDは基板上に立てたピンでとっているので、あまり良くないかもしれません。

“BPF後のFFT”

そういえば、画面キャプチャも本体でできるはずですね。わざわざ撮影する必要は無かったですね。

それは置いておいて、上の画面では84.7MHz近辺を拡大しています。Y軸の単位はdBVrmsになっています。 大体20dB位は信号が出ているようですね。

問題は、電源を投入した時の様子です。順次調べていこうと思います。

Artix-7でのMIGエラー

とある基板を製作するにあたり、Artix-7にてDDR3のピン配置がどうなるか確認したいと 思い、MIG(Memory Interface Generator)にてDDR3コントローラを作ってみました。 IP IntegratorにてAdd IPにてMIGを追加し、ダブルクリックして所望の設定をしていきました。 最後にGenerateボタンで完了!

…と思ったら、Artix-7 MIG DDR3 fails to generate custom UI と同じ症状が発生して、生成に失敗します。

リンク先の情報によれば、Windows8、またVivado 2015.3では修正予定とあります。 質問した方はWindows8はやめてWindows7で動かすことにしているようです。

私が問題に遭遇した環境は、Windows10 Proです。しかもVivado 2016.4 / 2017.1どちらでも同じエラーが出てしまいます。 実際、リンク先の最後(2017/2/1付)の投稿を見ると、Windows10/Vivado 2016.4で同じエラーが出ている方がいるようです。

Xilinxのツールの質の低さには辟易しますね。デバイスの特性はIntel(旧Altera)より良いと思っているのですが、 これではぶち壊しです。

XilinxのFPGAをKiCadのコンポーネントライブラリにするPerlスクリプト

XilinxのFPGAをKiCadで使用するために必要なコンポーネントライブラリ(のたたき台)を作成するためのやっつけPerlスクリプトを作成しました。

以下にソースを張っておきます。無保証です。使用方法は、Usageにも簡単に書きましたが、 まず、XilinxのページからPackage Device Pinout Filesを持ってきます。 例えば、Artix-7ではこちらのページからデバイス一覧のリンクをたどれます。次に、標準入力からスクリプトに流し込み、標準出力を*.libにリダイレクトします。 このlibファイルをKiCadのコンポーネントエディタで開くと、次のような感じになります。

“バンク0のピン”

すいません、矩形の描画はさぼっています。適宜矩形を追加したり、リファレンスを移動したり、 ピンの入れ替えなどを行ってください。 矩形の描画等は複数ユニットのコンポーネントだと、ちょっと注意しないといけません。実際の作業方法については、 KiCadで複数ユニット部品を作るが参考になります。

ピンはバンク毎に別々のユニットに分かれています。 こうするとVCCOも各バンクに属してしまうようです。必要であればlibを直接編集するなりしてください。

#!/bin/perl

# Usage:
# $ wget https://japan.xilinx.com/support/packagefiles/a7packages/xc7a50tfgg484pkg.txt
# $ cat xc7a50tfgg484pkg.txt | perl xilinx_kicad.pl > xc7a50tfgg484.lib

use strict;

my %banks;

# skip header
while (<>){
    last if $_ =~ /Pin\s+Pin Name/;
}

while (my $line = <STDIN>){
    chomp($line);
    last if $line =~ /^\s+$/;       # skip footer
    my @lst = split(/\s+/, $line);
##    foreach my $val (@lst){
##        print "$val ";
##    }
##    print "\n";
    push @{$banks{$lst[3]}}, "$lst[0] $lst[1]";
}

my $number_of_banks = keys %banks;

print "EESchema-LIBRARY Version 2.3\n";
print "DEF FPGA IC 0 40 Y Y $number_of_banks F N\n";
print "F0 \"IC\" 0 -100 60 H V C CNN";
print "F1 \"FPGA\" 0 -200 60 H V C CNN";
print <<'END';
F2 "" 0 0 60 H I C CNN
F3 "" 0 0 60 H I C CNN
DRAW
END

my $bank_count = 1;
foreach my $bank (keys %banks){
    #my $number_of_pins = @{$banks{$bank}};
    #print "Bank: $bank ($number_of_pins pins)\n";
    my $i = 0;
    foreach my $pin (@{$banks{$bank}}){
        #print "$pin\n";
        my @val = split(/\s+/, $pin);
        #print "\t$val[0]=$val[1]\n";
        my $posy = $i * 100;
        print "X $val[1] $val[0] -550 $posy 200 R 50 50 $bank_count 1 B\n";
        $i++;
    }
    $bank_count++;
    print "\n";
}

print "ENDDRAW\nENDDEF\n";

参考文献

Kicad/file formats

FMステレオパイロット信号の確認

前回までに、FM復調処理全体のFPGA実装とDACによるヘッドフォン出力が完成しました。

今回は、ソフトウェアを少し修正して、FM復調した信号そのものをFFTして観察できるようにしました。

これはステレオ復調のための布石です。

“FM復調信号のFFT画面”

FFT画面下部のMHzという表示は嘘で、KHzです。500kHzのサンプリング周波数でFM復調処理が動作していますが、 FFTを見てみると、確かに19kHzのところに信号が常に一定値で含まれています。 これがFMのパイロット信号だと思われます。この信号を2倍した38kHzを中心として、 L-Rの音声信号がAM変調されDSBとなっているそうです。

ステレオ復調にあたっては、この19kHzにロックした正弦波をFPGA内部で生成する必要があります。

豪徳寺から高円寺まで散歩

少し時間がたってしまいましたが、GWの休みを利用して東京散歩をしました。

小田急の豪徳寺駅で下車して、中央線の高円寺まで歩きました。

ルート を測ってみたら、大体9km位でした。

11:30頃に豪徳寺駅に到着し、早速早めの昼食をとる予定だったのですが、 事前調査をしていたお店が休業だったので、 仕方なく、まずは歩くことにしました。

豪徳寺近辺は、これぞ世田谷区という雰囲気で、狭い道路の左右に所狭しと家が並んでいます。 甲州街道を渡ると杉並区になるせいか、街の雰囲気もかなり落ち着いた感じでした。 個人的には気に入りました。永福町駅を過ぎると、駅前商店街が(あまり栄えている感じではないですが)小ぎれいでした。 また、あまり高い建物がなく、しかも平地なので、結構遠くまで見通せるのが新鮮でした。

ハイライトは善福寺川周辺です。

“善福寺川”

こんな感じの風景が数km続いています。晴天の休日でしたので、多くの人がのんびり時間を過ごしています。 かといって、人は多すぎず、とてもくつろげる雰囲気で良かったです。

さすがにおなかが減ったので、南阿佐ヶ谷駅を過ぎたあたりでとにかく見つかったお店に入ることにしました。 結局、聖庵になんとなく目を引かれて、こちらでランチにしました。 確か13:40位だったと思います。

休息を得たので、また歩いて阿佐ヶ谷駅を通り抜け、中央本線に沿って歩いて高円寺に到着しました。 ここから中央線に乗って帰宅。

程よい疲れで楽しめました。

FM復調のFPGA実装(4)

前回までに、FM復調処理全体のFPGA実装が完了しました。

今回は、製作した基板上に実装されているオーディオDAC NAU8822 を動作させ、リアルタイムにヘッドフォン端子から音声出力が得られるところまで確認しました。

これで、ひとまずFMラジオの完成です。以下がFM信号をFFTした画面です。

“FM信号のFFT画面”

やっとリアルタイムで音が聞けるようになったので、アンテナの向きを変えたり、基板上の部品を触ってみたりして、 ノイズがどう変化するかを確認できました。

FPGA基板に載っている大きいインダクタを触るとかなりノイズが乗る。また、 デバッグのために接続しているUSBケーブル、LANケーブルを抜くとノイズが減る。 余計なケーブル類を除いてアンテナの向きを最適化すると、自分の耳ではノイズが聞こえないくらいのレベルでは 音声が聞けるようになりました。

基板が到着してから暇を見つけて少しずつ進めてきました。 結局、ここまで来るのに、1カ月ちょっとかかりました。 ADC動作のために修正が必要な基板のミスは無くて、半田コテを一切使用せずここまで来ることができました。 また、デバッグにあたりショートチェックと電圧測定のためにマルチメータは使いましたが、 DSOは使用しないで済みました。

最後に少し苦戦したのは、DACのレジスタ設定でした。なかなか音が鳴らなくて、 いよいよオシロが必要かと思いましたが、たった1bitを変えるだけで音が出るようになりました。 やれやれ。

ここまでできたので、ひとまず満足です。まだソフトウェアの作りこみは甘いので、 FPGAで動作するファームウェアやPCのソフトウェアの使い勝手をもう少し向上させたいと思います。 また、現状JTAGケーブル、LANケーブルも接続してNFSマウントでデバッグしています。 これを一旦は単独動作するようにまとめたいとも思っています。

ラジオ機能としては、あとはステレオ再生の実装でしょうか。

参考にしたページ:

現状上記の状態ですが、本基板を試してみたい、というご要望がありましたらtwitterでお知らせください。 件名に"[ADC基板]“と入れていただけると助かります。 利用するには、最低限Z-turn boardとACアダプタ、SMAメスに接続できるFMアンテナが必要です。

また、「自分の持っているXXX FPGA基板でも動作させてみたい」というような要望につきましても、 ひょっとしたら対応可能かもしれません(基板書き換えで)ので、お知らせください。

以下は備忘録

アンテナを装着しないでFM側入力をキャプチャしてFFTしたもの。

“アンテナ未装着時のFFT”

同様に、アンテナを装着しないで(かつアンプも通さず)AM側入力をキャプチャしてFFTしたもの(こちらはシングルエンド入力でADCを使用)。

“アンテナ未装着時のFFT”

次に、アンテナを装着しないで、アンプを通したAM側入力をキャプチャしてFFTしたもの。

“アンテナ未装着時のFFT”

FM復調のFPGA実装(3)

前回までに、FM変調のキモであるarctanのところまでFPGA実装しました。

今回は、それに続く偏角の差分計算から、FIR3段とデエンファシスまでFPGA実装しました。

FM復調全体の流れは次の図のようになっています。

“FM flow”

前回までは、最初のFIRフィルタから160MHzで駆動するようにしていましたが、 FPGAのVivadoプロジェクトを2017.1にアップグレードしたら、CORDICが160MHzで動作しなくなってしまいました。 そのため、FM復調全体までは40MHzで行うようにしました。

おかげで、FIRに使用するDSPの数が増えてしまいました。リソース使用量の観点からすると、 できるだけ高速で動作させたほうが(リソース使用量が減って)望ましいのです。

前回までにFIRフィルタの使い方は分かったので、ひたすら必要な逓倍数のフィルタを作成し、 連結します。ただ、FIRフィルタの間は小さなFIFOを入れて、データ出力間隔が均等にならないのを埋め合わせています。

また、FM復調のための偏角の差分計算は、C#ではこちらの記事で書きましたが、 Verilogで書くにあたっては、

parameter signed[33:0] PI = (2.0 ** 29.0) * 3.1415926535897932384626433832795;
parameter signed[33:0] PI2 = (2.0 ** 30.0) * 3.1415926535897932384626433832795;

のようにπと2πを定義して、

assign  w_atan_tdata2   <=  {w_atan_tdata[31], w_atan_tdata[31], w_atan_tdata};
assign  r_atan_tdata2   <=  {r_atan_tdata[31], r_atan_tdata[31], r_atan_tdata};

always @(posedge w_fir_ck) begin
    if (w_atan_tvalid) begin
        r_atan_tdata    <=  w_atan_tdata;
        if (w_atan_tdata2 - r_atan_tdata2 > PI)
            r_atan_diff <=  w_atan_tdata2 - r_atan_tdata2 - PI2;
        else if (w_atan_tdata2 - r_atan_tdata2 < -PI)
            r_atan_diff <=  w_atan_tdata2 - r_atan_tdata2 + PI2;
        else
            r_atan_diff <=  w_atan_tdata2 - r_atan_tdata2;
    end
end

としています。w_atan_tdataは小数部29bitの符号付き32bit固定小数点数なので、 34bitに符号拡張してから、πを2^29乗したものと比較します。r_atan_diffは32bitに戻ります。 これが偏角の差分値になります。

最後のデエンファシスも小数点位置に気を付けてIIRフィルタを実装しました。 安直に実装したデエンファシスの回路は160MHzではタイミングエラーを起こしたため、 非同期FIFOで40MHzに落として運転しました。そう思うと純正IPのFIRが160MHzでも動作しているのは、 さすがによくできています。

FPGAを使用した1bit ADCの方法を調査

ADCを一切使用せず、FPGAのみを使用することでADCの代わりとすることができるという情報が流れてきたので、 少し調べてみました。

情報源としては2つ見つかりました。

どちらも、FPGAの外側にRCのみの回路を組むことで1bitのデータを取り込み、それを平均化することでビット数を稼いでいます。 また、LVDSのような差動入力ペアを使用して1,0を判定することは共通しています。上記XCell Journalの記事によれば、IBUFDSを使用すると、 1mVp-pの電位差があれば1,0を判定できるようです。

N側のピンの使い方が二つの記事では異なっています。XCell Journalの記事の方だと、N側は単純にP側とバイアスして同電位になるように設定し、 RCで低域通過フィルタを構成しているようです。 Latticeのドキュメントの方では、FPGAのシングルエンドピンから1,0を出力して、それをRCの低域通過フィルタを通してN側のピンに入力しています。 この方法は、ΔΣ型ADコンバータΔΣ変調で説明されているように、 誤差をフィードバックするということで、ΔΣ型ADCと同じ考え方のようです。

XCell Journalの記事では、240MHzで1,0をサンプリングし、NCOで発生させたsin,cosを直接乗算し、 それをCICしてサンプルレートを落としてFM復調まで行えたと書かれています。

Latticeのドキュメントは、キャプチャした1,0をCICに通すことで、ビット幅を稼いでいるようです。

機会があれば実際にZynqでどれくらいの性能が出るのか試してみたいですね。