FPGA

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

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

FM復調のFPGA実装(2)

前回までに、ミキサとCICはFPGA化ができました。

今回は、それに続くFIR一段分とCORDICによるarctanを実装しました。

FM復調全体の流れは次の図のようになっていますが、今回は図中のarctanまでFPGA化しました。

“FM flow”

NCO, ミキサ, CICは自分で実装しましたが、 FIR, arctanはそれぞれXilinxのFIR, CORDIC IPを使用して楽をしました。 FIRフィルタはマルチチャンネルに対応できるので、回路的には1つだけでI,Q両方を扱うことができますが、 乗算器も潤沢にあるので、それぞれのチャンネルでFIR回路を置いています。 また、arctanもY,X入力最大幅の49bitまで使用しています。

図の最下部にある40MHz, 160MHzというのはそれぞれの回路ブロックの動作クロック周波数になります。 160MHzはADCに使用されている40MHzのクロックをMMCMにて4逓倍して生成します。

1段目FIRの入力は、わずか1.25MHzしかありませんので、160MHzに対して160/1.25=128となり、 128クロックに1回しかデータが入力されません。さらに出力は2/5に間引かれますので、 平均して320(=128*5/2)クロックに1回しか出力されません。

このように、データは回路の動作周波数に対して間欠的にしかやってきませんので、 255タップのFIRフィルタを実装するにしても、ほんの少しの乗算器を使用するだけで実装できます。

ただ、最初はFIR, arctanを200MHzで動かそうとしましたが、 arctanのところでタイミングがメットしませんでした(WNS < 0)。 これだけのビット幅があるのに160MHzで動くのだから大したもんです。

arctanの出力をPCに取り込んで、残りの部分をソフトウェアで処理したところ、ちゃんと音声が再生できました。 あとは、残りの回路を粛々と実装します。FIR IPの使い方は分かったので、 手で実装しないといけないのはdiff(偏角の差分)とde-emphasisの部分になりそうです。

以下はおまけと備忘録

XilinxのFIR IPは、coeファイルというテキストファイルを指定することで、FIRの係数を設定できますが、 このファイルでは"-6.595122999934834e-03"といった指数表記の小数は使えないようです。 “-0.0065951…“のようにする必要があります。そのため

cat data.txt | awk '{print sprintf("%.12f", $1)}' > coef255_008.coe

のようにして表記を変更しました。

使用しているFIR, CORDIC IPコアの設定画面は次のようになっています。

FIR Compiler

“FIR Filter Options”

“Channel Specification”

“Implementation”

“Detailed Implementation”

“Interface”

“Summary”

CORDIC

“Configuration Options”

FM復調のFPGA実装(1)

前回までに、ADCでキャプチャした生データをパソコン上で処理することで、 FMラジオを視聴できることが確認できました。

PC上のソフトウェアでFM復調を行っている部分を、徐々にFPGA化していこうとしています。

いきなり全体をRTLで実装しても、動作しなかった場合のデバッグが大変です。 それで、ADCに近い側からFPGAの回路に落とし込みます。今回は複素ミキサ(ADC入力にチューニング周波数のsin, cosを掛け算することで、I, Q信号を得る)と、 CICフィルタを実装しました。

2の補数表現とビットシフトを注意深く行えばそれほど難しくないはずの回路でしたが、わりと手こずりました。 複素ミキサはFPGAのBRAMにてテーブルルックアップを行ってsin, cosの値を得るようにしています。

具体的には、32bitの値を持つ400エントリを使用して、各エントリに対応するsin, cosの値を符号付きで13bitずつ入れています。 なぜ400エントリかというと、40MHzのサンプリングレートで例えば84.7MHzを受信しようとする場合、 これはナイキスト周波数以上なので実際には4.7MHzとしてADCから見えます。 (4.710^6) / (4010^6) = 47 / 400ですから、ADCの400サンプルに対して、4.7MHzは47周期現れます。 この400回分について、sin(2 * π * i * (47/400)) (i=0…399)をテーブルとして準備しておきます。 テーブルの中身自体は、Zynqで動作するLinuxアプリケーションにて初期化しています。 BRAMはZynqのアドレス空間と、RTLの両方からアクセスできるようにTrue Dual Portで動作させています。

ADCの各クロックごとにアドレスをインクリメントすることで、対応する周波数のsin, cosの値を得ることができます。 それをADCから出力されている符号付き12bitと掛け算し、下位ビットは切り捨ててCICフィルタに入力します。

CICフィルタは3ステージの1/32間引き(1.25MHz出力)を行っています。出力は29bitとしています。

これで毎秒のデータ量は1.25MHz*8bytes=10MBytesに減少しましたので、メモリ上に取り込むことのできる時間が一気に長くなりました。 PC側でサンプリングレートの調整を実装すれば(基板に実装されている発信器の周波数とPC上の周波数は異なるため、 48kHz出力を行うにしても、クロックレートの微調整のためにサンプルレート変換が必要)、 リアルタイム転送とFM変調処理が行えるのですが、そちらはまだ今後の課題ということで。

結局最後まで手こずった原因は、BRAMのアドレスの下位2bitは無視されていることに気づかず、 0-399までのカウンタをそのままアドレスに入力していたことでした。 0-399のカウンタに下位2bit"00"を付加してBRAMの32bitアドレスとすることで、 想定通りの正弦波が得られたようです。

それでも、PC上で処理した場合より明らかに音質は悪いです。もう少しミキサのビット数を増やしたりしてみようかと思います。

2017/4/20追記: ミキサの出力を17bitにして、CICを32bitまで拡張しました。 ミキサ出力の部分も実際のデータを観測して、オーバーフローしない範囲でできるだけ下位ビットを取るようにして、 可能な限り精度を落とさないようにしました。CICの結果から残りをパソコンのソフトで処理してみたら、 かなり音質は改善しました。これならひとまず良さそうです。 残るFIRとCORDICによるarctanの実装を粛々と行っていけばFM復調のFPGA化が完成する予定です。

また、これまでソフトウェアではarctanを求める前に複素数の割り算をすることで、偏角の差分を一発で求めていました。 でも、FPGA化する場合、これだと乗算と加算が入るので、CICのデータが32bitあると64bitほどになってしまいます。 それで、まずarctanを各データに対して行って、その結果の偏角を引き算する、という計算順序に変更しました。 arctanが返す角度の範囲が-πからπまでなので、単純に引き算するだけだと、この範囲を超えてしまうことがあります。 そのため、下記のように必要な場合2πずらすようにしました。

    private double[] fm_demodulate_sub(double[] i, double[] q)
    {
        double[] result = new double[i.Length];
        double prev = 0.0, tmp;

        for (int x = 0; x < i.Length; x++)
        {
            tmp = Math.Atan2(i[x], q[x]);
            if (tmp - prev > Math.PI)
            {
                result[x] = tmp - prev - Math.PI * 2.0;
            }
            else if (tmp - prev < -Math.PI)
            {
                result[x] = tmp - prev + Math.PI * 2.0;
            }
            else
            {
                result[x] = tmp - prev;
            }
            prev = tmp;
        }
        return result;
    }

これならばarctanの計算に必要な精度はI, Qそれぞれ32bitで良いことになります。

FM復調(モノラル)の実装

前回までに、ADCでキャプチャした生データをパソコン上で処理することで、 AMラジオが視聴できることが確認できました。

加えて今回はFMも復調できるようになりました。

FM復調の流れは、次のようになります。

  • ADCデータ(12bit@40MHz)に、チューニングしたい周波数のsin,cosを生成(NCO)してそれぞれ掛け算してI, Qデータを得る
  • I, Qデータを4ステージCICフィルタで1/32に落とす(1.25MHz)
  • 続いてFIRフィルタで2/5倍(500kHz)に周波数変換する。2/5倍で使用する係数は255タップ、遮断周波数0.08fs(fc=200kHz)とする。
  • 500kHzサンプリングのI, Qデータの隣り合ったサンプル同士からarctan(タンジェントの逆関数)をもとめる。 具体的には、Math.Atan2(i[x-1]*q[x] - q[x-1]*i[x], i[x-1]*i[x] + q[x-1]*q[x])を求める。 I, Qを複素平面のx,y座標とみなして、C[x]とするとき、arctan(C[x+1]/C[x])を求めることで、サンプル間の偏角の変化量を求めることになります。
  • 上記の偏角の変化量をFIRフィルタで2/5倍(200kHz), 3/5倍(120kHz), 2/5倍(48kHz)に周波数変換する。 係数はすべて255タップ、遮断周波数はそれぞれ0.08fs(fc=80kHz), 0.08fs(fc=48kHz), 0.0625fs(fc=15kHz)とする。0.0625fsとすることで、15kHz以下を通過させるLPFとなります。 19kHzにステレオ放送用のパイロット信号が入っているので、その前の段階で十分に減衰できるようにします。
  • 48kHzまでサンプルレートが落とされたデータ系列に対して、デエンファシスをかける。具体的には、 Low-Pass Single-Pole IIRフィルタを通します。 上記ページによれば、減衰量dはd=e^(-2pifc)という関係になるようです。fs=48kHzなので、大体3kHzで-3dBになればよいようなので、 fc=3kHzとし、d=e^(-2pi(3/48))=0.67523…となります。
  • デエンファシス後のデータを(適当にゲイン調整を行ってから)WAVファイルに出力する。

上記のように、FMでのステレオ復調は行っていません。これでなんとか音声として聞こえるようになりました。 各フィルタの遮断周波数は、変換後の1/2fsよりもそれなりに小さいところで設定しておかないと、折り返しがもろに入ってしまうと思われます。 そのため、上記のように1/2fsの80%, 62.5%と設定しています。

ここまでで、曲がりなりにも論理的にはAM/FMの復調ができることは確認できました。すぐに思いつく今後の方向性としては

  • FPGA化
  • ADCの精度確認と改善

があります。後者は機材をそろえたり、受動部品の定数を変更したりしてみないと難しいと思われるので、 ひとまずFPGA化の方を少しずつ進めていこうと思います。また、基板上には音声出力用のICも搭載しているので、 そちらの動作確認もしないといけません。

参考にしたページ

FMトランスミッタ: プリエンファシス(1)

三重大学の資料?

エンファシス

石川高専 山田洋士 研究室 (FIRフィルタの窓関数法による設計)

ADC基板でのAM/FMキャプチャと復調

ADC基板でAM信号をキャプチャして、 パソコン上のソフトウェアでAM復調を行う、というところまで最低限動作しました。

波形を取得しFFTしたときの画面を示します。

“AM Capture”

赤丸で囲ってあるところは、それぞれ810kHz(AFN), 1422kHz(RFラジオ日本)と思われます。 実際にC#で適当にこしらえたソフトウェアで810kHzをAM復調してみたら、カントリーミュージックが流れていました。

AM復調の流れは、ざっと次のようになります。

  • ADCデータ(40MHz@12bit)に、チューニングしたい周波数のsin,cosを生成(NCO)してそれぞれ掛け算してI, Qデータを得る
  • I, Qデータを4ステージCICフィルタで1/32に落とす(1.25MHz)
  • 続いてFIRフィルタで2/5倍(500kHz)、2/5倍(200kHz)、6/25倍(48kHz)と変換を行う。2/5倍で使用する係数は51タップ、遮断周波数0.2fs。 6/25倍で使用する係数は51タップ、遮断周波数0.04fs。
  • 48kHzまで落としたI, Qデータからsqrt(I^2+Q^2)を求めて振幅を求める(AM復調)。 この値をwav形式(モノラル)でファイルに出力する。

SDRについては勉強中の身なので、上記のタップ数や遮断周波数の設定などはあまりよろしくないのかも? しれません。 現状NCOとFIR演算は整数演算ではなく、浮動小数点演算を用いています。 また、FIRのために実装したポリフェーズフィルタもコードが正しいか、まだちょっと不安です。

ただ、上記画面からもわかるように、他にも954kHz(TBSラジオ, 100kW)や1134kHz(文化放送, 100kW), 693kHz(NHK第二, 500kW)などの、出力が大きい局の信号がほとんどとれていません。

Wikipedia - AFNによれば、AFNは出力が50kWらしいので、 他の局も十分受信できても良いように思います。 手元にちゃんとしたAMアンテナが無いので、FMロッドアンテナを基板に装着しているのですが、それが原因なのか? それとも、サンプリングの折り返しなどの原因があるのか(AM側の入力はBPFなどを一切設けていない)? まだ不明です。

また、810kHzなども、「なんとか聞こえる」という程度であり、お世辞にも音質は良いとは言えません。 所有している乾電池式ポータブルラジオの方がはるかに音質が良いです。 もっとも、これについては復調処理に問題があるのかもしれません。

4/5追記: やはり間違いがありました。Wikipedia - サンプリング周波数変換 の通り、a/b倍の周波数変換をするときには、変換後の周波数の1/2の周波数を遮断周波数としなければいけないようです。 上記の設定だと、変換後の1/2fs以上の周波数が折り返してしまいます。 そういうわけで、2/5倍に使用する係数は0.1fsを遮断周波数とし、6/25倍に使用する係数は0.02fsとしました。 また、タップ数もそれぞれ71, 255に増やしました。 そうしたら音質が(まだまだ十分ではないですが)かなり改善されました。

4/11追記: さらに変更して、現在の信号処理の流れは次のようになりました。

  • ADCデータ(40MHz@12bit)に、チューニングしたい周波数のsin,cosを生成(NCO)してそれぞれ掛け算してI, Qデータを得る
  • I, Qデータを4ステージCICフィルタで1/32に落とす(1.25MHz)
  • 続いてFIRフィルタで2/5倍(500kHz, fc=156.25kHz)、2/5倍(200kHz, fc=62.5kHz)、3/5倍(120kHz, fc=48kHz)、2/5倍(48kHz, fc=15kHz)と変換を行う。 使用する係数は255タップ。2/5倍で使用する係数の遮断周波数は0.0625fs。3/5倍で使用する係数の遮断周波数は0.08fs。 上記の通り、2/5倍で0.1fsとすることもできるとは思いますが、それだと1/2fsで-3dBしか落ちませんので、 周波数変換後の高音部にかなりエイリアスが入り込んでしまうと思います。
  • 48kHzまで落としたI, Qデータからsqrt(I^2+Q^2)を求めて振幅を求める(AM復調)。振幅が符号付き16bitに収まるようにゲイン調整を行う。 この値をwav形式(モノラル)でファイルに出力する。

追記終わり

ちなみに、FM側の入力波形を見てみると、次のようになっています。

“FM Capture”

ADC基板到着

ついに、Elecrowに発注していたADC基板が到着しました。

3 / 9 (木)にPayPalにて支払いを行い、3 / 29に発送のお知らせメールが到着し、3 / 30 (木)に到着しました。 Elecrowから送られてきたL/Tは2-3weeksでしたが、ぴったり3週間で到着です。

3 / 29までは全く音沙汰がなかったので、ちゃんと進んでいるのか、それとも実装に失敗しているなどの問題が起きていないか、心配でした。

完成した写真を送ってくれたという方もいるようですが、私の場合はいきなり発送されました。 OCSの履歴を見てみると、3/28の夜に中国から送られて3/29の午前には日本に到着していました。 配達はさすがに速いですね。

ちなみに、基板2枚実装で241USD, π割引3.14USDで237.86USDでした。日本円で27,784円でした。1USD=116.8円なので、 あまりレートは良くないタイミングでした。

基板の包装は次のような感じでした。

基板のパッケージ

テンション上がります。

ちなみに、かの有名なElecrowガチャは2枚でした(実装したのも2枚)。

おまけ基板

ステンシルは入っていませんでした。再度製造を依頼する場合に必要になるので、こちらから頼まなければ保管しておいてくれているのかもしれません(未確認)。

ADCの部分は次のような感じです。

ADCパターン

KiCadに習熟していないせいで、若干センターのGNDが甘い気もしましたが、勢いで作ってしまいました。

あらかじめ購入しておいたSMA-BNC変換コネクタとジャンパを装着した状態が次です。

テンションMAX

うーん、美しい。初めての基板製作で我ながらよくここまで頑張った。 フットプリントがおかしくて墓石になることもなかったようです。 また、ちゃんとDIP部品もしっかり基板に入っています。ヘッドフォン端子はフットプリントが結構変態的だったので、ちゃんと基板に入るか心配でした。 ちなみに、画面下の赤いのは、SMAコネクタを保護しているプラスチックのキャップです。

ちょっと部品間隔が狭すぎるかと予想していましたが、しっかり実装できているようです。抵抗アレイはほとんど横並びです。 自分の実力だと、これほど近接していたらチップ部品の交換はしんどいですね。

右下のジャンパの接続のためのシルクも小さいけどしっかりと見えます。

それにしても、実際の基板ができた時の満足感はすごいですね。もうデバッグはいらない気分になってしまいます。

この基板をこれまた購入済みのZ-turn Boardに装着すると、次のような感じです。

最高の組み合わせ

さすがに80ピンもあると抜き差しは慎重にやらないと危険です。

1枚の基板はこの80ピンコネクタが少し曲がっているという不具合がありましたが、ひとまず手でなんとか挿入できるくらいまでは真っ直ぐに直しました(汗)。

あ、もちろん、電源を入れる前に電源とGNDがショートしていないことは確認しましたよ。

いよいよ(すぐにアダプタを抜ける態勢で)緊張の電源ON!!

「ピー」 ….. え??? ひとまず電源を抜きます。

おかしい?? ショートしている?? というわけで基板チェック開始。いろいろ調べてみたけど、やはりショートは問題ない。 どうやらJ6のジャンパを入れてADCの電源が入ると音が鳴る。J6がoffだと音はしない。

いろいろ調べてみたところ、どうやらビープを駆動するNPNトランジスタのゲートに接続されているネットがオープン状態なのですが、 そこの電位が数百ミリボルトあがっているようでした。それでトランジスタがONしてしまっているのではないかと思いました (参考)。 こうなってしまっている原因は不明ですが、ショートは恐らくないことを考えると、 ADC出力が開始されることで、当該ネットに近い他のネットからのクロストークを受けてしまっているのかもしれません。

というわけで、本来ならばビープのネットをプルダウンするのが良い解決策だと思いますが、FPGAで当該ネットをLow駆動することで音は出なくなりました。 ひとまず変更したデザインをQSPI ROMに書き込んで、起動時にコンフィグが終了すれば音が止むようになりました。

ちょっと先が思いやられますが、デバッグを続けます。