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内部で生成する必要があります。

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でも動作しているのは、 さすがによくできています。

計算結果の32bitはDMAしてPCに転送し、16bitにクリップしてwavファイルに出力しました。 これでFM復調のFPGA化は基本的に完成です。

あとは、上図の右下にDACへの点線が書いてありますが、基板上に実装している NAU8822 を動作させ、I2S出力回路も実装しないといけません。まだこちらのICは動作確認は一切できていないので、 音声出力まで、まだ少し作業が残っています。

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でどれくらいの性能が出るのか試してみたいですね。

« 3/7 »