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に書き込んで、起動時にコンフィグが終了すれば音が止むようになりました。

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

DE10-Nano Kitは結構良さそう

つい先日、FPGA評価ボードを購入して、基板まで製作しFPGAによるFMラジオまで製作してしまいましたが、 最近発売されたDE10-Nano Kitも悪くないのではないか?と思いました。 Z-turn Board(7020版)と比較してみると、次のような利点、欠点がありそうです。個人的に重要なポイントは太字で。

Pros:

  • 130USDなので、送料も含めるとZ-turn Boardよりは高くなると思われるが、JTAGケーブルは別途必要ではないので、トータルでは安いと思われる。
  • 多ピンコネクタが2.54mmピッチのようなので、汎用性は高い
  • 搭載FPGAのサイズもZynqの7020より少し大きい。ARMも少しだけ早く動作する(800MHz vs 667MHz)。
  • +5V電源もキットに標準で含まれている(でもこちらも電源SWは無さそう?)。
  • IOもZ-turn Board搭載Zynqの400pinパッケージよりも多い672pinパッケージ。でも実際に使用可能なIOはそれほど変わらない雰囲気です。

Cons:

  • DDR3の動作周波数は遅い(1066MHz vs 800MHz)。
  • ロジックの動作は多分Zynqの方が速い?
  • Alteraは無料で高位合成ツールは提供されていない。ソフトコアCPUも有償。

2017/4/17追記: Terasicの公式ページだとStockが無い様で、 “Contact Us"となっていますが、Mouserだと在庫があるようです。 しかも送料無料です。レート換算してみると、1USD=121.5円なので若干悪いですが、送料無料と思えば適正ではないかと思います。 追記終わり

一長一短という感じですが、用途(と好み)によっては良いのではないでしょうか。ちなみに、 搭載されているCyclone V SE 5CSEBA6U23I7は、digikeyで調べてみると、 1個買いで29,694円(2017/3/28調べ)です。そう考えるとかなりお値段頑張っていると思います。 ただし、Alteraは機能のわりにXilinxより元々少し高いという印象がありますが。

Z-turn Board搭載のZynqは、同じくdigikeyで調べてみると、 13,724円です。これも一個買いするのであれば、それほど変わらない値段でZ-turn Boardが買える計算になります。

ADC基板のBPFのシミュレーション

今回は、LTspiceを使用して、 ADC基板に実装しているBPF(Band Pass Filter)の周波数特性をシミュレーションしてみました。

“Simulation”

実線が左側の軸(振幅)に対応し、点線が右側の軸(位相)に対応しています。

初めて使ったので、少し使い方に迷いましたが、比較的簡単に使えました。 シミュレーションを行う周波数を50M-120Mと入力したらメガヘルツになるかと思ったら、 Mはミリと解釈されるようです。メガを指定するにはmegと入力しないといけません。 LTSpice入門を読んで分かりました。

シミュレーション結果を見てみると、-3dBになるのは大体60MHzと105MHzあたりでしょうか。 70-90MHzの範囲はほぼ0dBで通過しているのが見て取れます。 もう少し急峻にバンド外を落とすかと思っていましたが、わりとゆるやかな特性なのですね。

Wikipedia によると、これはバターワースフィルタのCauer形のようです。ロールオフ特性は緩やか、とはっきり書いてありました。

DDSデータキャプチャとFFT表示

前回、ADCキャプチャのためのFPGAとLinux周りの準備を行いました。

まだ実際のADC基板は完成してきていないので、FPGAにてDDS(Direct Digital Synthesizer: デジタル的に正弦波を生成する仕組み)を使用して、仮想的なデータを作ってみました。

具体的には、FPGAにDDS Compilerをインスタンシエートして、 PCのソフトウェアにてキャプチャ&FFTを実行しました。

DDS Compilerにて作成するIPは、3MHzの正弦波としました。

DDS compiler

12bit出力ですが、AXI Streamポートは16bit幅となっています。どうやら16bitの内、下位12bitにデータが入っている様子でした。符号付きデータです。

この12bitを5データ集めて、かつ4bitのダミービットを付加して64bitとし、前回のAXI DMA IPにてDDRに転送します。 PC側のソフトウェアは、手っ取り早くC#で作成しました。

いろいろ細かいデバッグを行って、現状次のような表示になっています。

ADC_FFT

画面上部にキャプチャした波形そのものを少し表示しています。横軸はサンプル番号です。 マイナスからプラスの範囲でしっかりフルスケールの正弦波となっている様子がわかります。 画面下部はキャプチャしたデータをFFTしてdB表示しています。 どうも使用しているFFTライブラリの正規化の挙動が不明で、0dBを超えてしまっています… 3MHzにびしっと信号があることを確認できます。

FFTライブラリには、C#でマイク音声をFFTするを参考に、 Math.NET NumericsをNugetにてインストールして使用しました。

これで基板が来るまでの準備は大体満足するところまで作成できました。

ADCデータキャプチャのためのLinuxとFPGAの設計

現在Elecrowにて製作中のADC基板ができてきた折に、Z-turnボードと接続してイーサネットにてADCデータを取得するためのファームウェア周りを作成しています。

FPGAについて

Zynqに接続されているDDRメモリにADCデータを保存します。 DMAマスタをRTLで記述するのは割と面倒(とにかくAXIはポートが多いので、どうしても行数は増える)なので、できるだけ楽をしたいと思います。 そういうわけで、Vivado HLS一択です。DMAコントローラのコードは次のように至極単純です。

ちなみに、AXI DMAを使えばいいじゃないか、という意見もありそうです。 しかしながら、AXI DMAは一回の転送で最大8MBしか転送できないという理解不能な制限があるので、今回はわざわざ作成しました。 SGDMAを駆使すればできると思いますが、とりあえずデータを取り込むことが目的なので、そのあたりは別途余裕ができたところで検討したいと思います。

#include "hls_stream.h"
#include "ap_int.h"
#include "axi_dma.h"

void axi_dma(ap_uint<64>* addr, ap_uint<32> offset, ap_uint<32> len, hls::stream<ap_uint<64> > &in){
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=offset
#pragma HLS INTERFACE s_axilite port=len
#pragma HLS INTERFACE m_axi depth=4096 port=addr
#pragma HLS INTERFACE axis port=in
    ap_uint<32> i;
    
    for (i = 0; i < len; i++){
#pragma HLS PIPELINE
    	addr[offset+i] = in.read();
    }
}

ん?Hugoでc++のシンタックスハイライトが効かない…

AXI Liteインタフェースでoffsetアドレス、転送長をレジスタで設定します。また、モジュールの開始終了もAXI Lite経由で操作できるようになっています。

VirtualBoxでブリッジ接続ができない問題の対処方法

VirtualBoxで動作しているUbuntuをTFTP,NFSサーバとして(ブリッジインタフェースで)動作させ、 Z-turn BoardからイーサネットでアクセスしてLinuxを動かそうとしてみたところ、 どうにも仮想マシンとZ-turn Boardとの間で通信ができませんでした。

ホストOS(Windows10)からゲストOSのUbuntuのブリッジインタフェースへの通信はできているし、 Z-turn BoardからホストOSへのイーサネット通信もできているので、物理的な故障ではなく、 VirtualBoxのブリッジが正常に動作していないように思われました。

結果としては、Stackoverflow にあった方法で解決できました。**VirtualBoxをいったん削除して、管理者モードでインストーラを起動してインストールする、**というものです。 VirtualBoxのバージョンは5.1.14です。

2017/3/11追記 上記で解決したかと思いましたが、どうやら実際は解決していませんでした。インストールした直後は動作するようですが、 パソコンをサスペンドして、復帰してから試すと、また動作しなくなっています。VirtualBoxがブリッジに使用するためのドライバに不具合があり、 パソコンのサスペンドを正しくハンドルできていないようです。

検索してみたら、まさにこの問題が登録されていました。 Network adapters not working after host returns from sleep Win 7 host Linux Mint 17.2 guest

上記ページに、ひとまずの解決策があります。VirtualBoxの設定からブリッジネットワークアダプタを一旦解除して、再度有効にする、という方法です。 私の場合もその方法で接続できる様子でした。それで、下記のようなBATファイルを作成して実行することにします。

"c:\Program Files\Oracle\VirtualBox\VBoxManage.exe" controlvm Ubuntu nic3 null
"c:\Program Files\Oracle\VirtualBox\VBoxManage.exe" controlvm Ubuntu nic3 bridged "Intel(R) Ethernet Connection I219-V"

Ubuntuというのは、仮想マシンの名前で、nic3はアダプター3に対応します。