2018.09.22

特殊電子回路を一度、閉じます

突然ですが、今月(今週?)で特電の本郷オフィスでの業務を閉じることにいたしました。

家賃が高いとかいろいろ理由はあるのですが、広がりすぎた業務を整理して本当に必要な業務に注力したいというのが理由です。

FPGAが好きで起業して14年やってきましたが、最近は如何に売るかということばかり考えていた気がします。

本来のFPGAの楽しさを感じる開発ができずに、広告や間接業務にばかり時間を取られてしまうようになっている自分に気が付きました。

特電のスタッフのほとんどは学生のアルバイトさんで、来年3月に卒業して就職する人が多かったので、タイミング的には幸いだったかもしれません。社会人のデザイナーさんもいますが、次が見つかるまでサポートしたいと思います。

sun

なお、特電の移転先は決まっていません。

復活の時期も未定です。それまで荷物はどこかの安い倉庫にしまっておきます。

一度、従業員ゼロのミニマムな会社に戻して、どこかのコワーキングスペースを借りて、これまでご購入いただいたお客様へのサポートと、面白みのある受託開発案件に注力したいと思います。その中でFPGAやJTAGの楽しさを再発見していきたいと思います。

そして、いままでに特電のスタッフさんが作ってくれた技術や製品のタネを育てながら、半年か1年くらい充電期間を取りたいと思います。

FPGAやJTAG製品の販売は、在庫がある分については発送します。

Cosmo-ZやCosmo-Z Mini、Cosmo-K、HyperFADCについては、今までよりは納期が多少かかるようになるかもしれませんが、受注生産で製造していきたいと思います。

在庫が尽きた後はどうするかは未定ですが、FPGA基板の製造を丸ごとアウトソーシングできる実装会社さんを探すとか、出荷業務をアウトソーシングできる商社さんを探すとかして、できるだけ滞りなく出荷できるようしていきたいと思います。製造や出荷のやり方についても、もっと手がかからない抜本的な改善方法を考えるいい機会ではないかと思っています。

sun

お客様、スタッフの皆様、応援してくれた皆様、ありがとうございました。

繰り返しになりますが、サポート業務や製品の販売は続けていきますのでご安心ください。

| | コメント (0)

2018.09.07

SDSoCでAXI Streamからバッファに入れる回路

SDSoCでAXI Streamからバッファに入れる回路が動きました。

Axis_test

どのような回路かというと、基本はコレです。

void pf_read_stream(unsigned long *rbuf) {}
void pf_write_stream(unsigned long *wbuf) {}

int s2mm_data_copy(unsigned long *fifo, unsigned long buf[BUF_SIZE])
{
#pragma HLS interface axis port=fifo
    do  {
    } while ((*fifo & 30) == 0);

    for(int i=0; i<BUF_SIZE; i++) {
#pragma HLS pipeline
        unsigned long tmp = *fifo;
        buf[i] = tmp;
     }
     return 0;
}

void s2mm_data_copy_wrapper(unsigned long *buf) {
    unsigned long rbuf0[1];
    pf_read_stream(rbuf0);
    s2mm_data_copy(rbuf0,buf);
}

SDSoCのチュートリアルでよく見るサンプルコードですが、バスの幅がunsigned longになっています。

このコードをmain.cppとは別のCPPファイルに保存しておき、Hファイルに

#pragma SDS data sys_port (fifo:axis_data_fifo_0_M_AXIS)
#pragma SDS data zero_copy(buf)
int s2mm_data_copy(unsigned long *fifo, unsigned long buf[BUF_SIZE]);
void s2mm_data_copy_wrapper(unsigned long *buf);

と書いておきます。main.cppと、ハードウェア関数が入るソースを分けておいたほうがいいでしょう。分けておくと、main.cppの中のコードを書き換えてからビルドをしても論理合成が走らないので早く出来上がります。

ハードウェア化するのはs2mm_data_copy関数であって、s2mm_data_copy_wrapperではありません。wrapperのほうが何をやっているのかいまだによくわかりませんが、ダミーの配列rbuf0[1]というのがハードウェアの配線に相当するようで、この記述を書くことによってAXI-4 Streamからハードウェア関数へつながります。

ポインタで指定された

また、#pragma SDS data sys_port の記述を使うことで、ハードウェアプラットフォームで定義されたAXI Streamのどこの部分に、この回路がつながるかを指定することができます。

Axis_test2

| | コメント (0)

2018.09.05

MITOUJTAGセミナー(応用編)を開催しました

本日、JTAGチャレンジ基板を使った初めてのセミナーを開催しました。

1536284277_mj_semi_3

JTAGチャレンジ基板とは

わざと間違いを作りこんだFPGA基板。正常に動作せず、FPGAメーカー純正のツールでもデバッグできない。

1536125922_jtag_challenge2

この基板はそのままでは動作しませんが、MITOUJTAGというツールを使うと、FPGAが起動しない理由や、FPGA間の断線の発見などができるというものです。

1536126314_jtag_challenge_bscan

アンケートを集計したところ、5人中3人の方が「とても満足」ごご記入くださいました。

お寄せいただいた感想やご意見はこのような感じでした。

  • セミナーの内容とは別の不明点も教えてもらえて、勉強になった。
  • 実際に不具合のある基板を実践的にチェック出来たことは良かったと思います。
  • JTAGはメーカーの独自拡張が跋扈する深い魔窟というイメージでしたが、怖がらずに挑戦できる気がしてきました。
  • Basic版でかなりの事ができることが分かった
  • ALTERAのFPGAは使った事は無かったのですが興味のあるMAX10に触れられた事、SVFプレーヤーが何であるかも分かった

次回のセミナーは10月3日(水)に弊社会議室(東京都文京区本郷)にて行います。

ご興味のある方は、ぜひご参加ください。

| | コメント (0)

2018.09.01

SDSoCで作ったニューラルネットワークの回路がZynqberryで動いた!

ZYNQを搭載したRaspberry PiライクなFPGAボード「Zynqberry」で、SDSoCプラットフォームを作り、ニューラルネットワークの計算をハードウェアでアクセラレートするデザインを動かすことができました。

Zb

私もいよいよSDSoCデビューです。

sun

使用したニューラルネットワークの構造と学習済みモデルは、オライリーのDeepLearning本のものを使用しています。したがって、隠れ層は2層で、ニューロンの数は50個と100個です。

MNISTの実行結果はというと、認識率が93%程度。これはオライリー本のコードをPythonで実行した場合と同じです。

動作速度は、ZYNQ上のARMで実行するのと比べて約2~3倍にアクセラレートできています。初めて書いたSDSoCのコードですが、まずまずでした。

Zb_mnist

作られたSDSoCの回路はこんな感じになりました。

Zb_nn

multsumという関数をハードウェア化し、それを3回呼び出すようにしています。

#pragma SDS data zero_copy(input[0:row])
#pragma SDS data zero_copy(output[0:col])
#pragma SDS data zero_copy(w[0:row*col])
#pragma SDS data zero_copy(b[0:row])
#pragma SDS data access_pattern(input:SEQUENTIAL)
#pragma SDS data access_pattern(output:SEQUENTIAL)
#pragma SDS data access_pattern(w:SEQUENTIAL)
#pragma SDS data access_pattern(B:SEQUENTIAL)
void multsum(int *input,int *output, int *w, int *b, int row, int col)
{
	for(int i = 0; i < row; i++) {
    	int tmp = 0;
		for(int j=0;j < col;j++) {
#pragma HLS PIPELINE II=1
			tmp += input[j] * *w++;
		}
		tmp += b[i] * 256;
		output[i] = sigmoid(tmp / 65536.) * 256;
	}
}

void hw_predict(int *p, int *y1, int *y2, int *y3,
	int *w1_8b, int *b1_8b,
	int *w2_8b, int *b2_8b,
	int *w3_8b, int *b3_8b,
	int w1r, int w1c, int w2r, int w2c,	int w3r, int w3c) {
	multsum(p, y1    ,w1_8b, b1_8b, w1r, w1c);
	multsum(y1,y2    ,w2_8b, b2_8b, w2r, w2c);
	multsum(y2,y3    ,w3_8b, b3_8b, w3r, w3c);
}

ちょっとワーキング用の配列が多いのと、シグモイド関数を実行するときに浮動小数点になっているのが気になりますが、それでも何も考えずに書いて、動いてしまいました。

sun

パフォーマンスを見てみると、毎回の積和計算が整数化して6クロックで行えているので、自分でHDL書けばもっと最適化できるのにな・・と思えます。

Multsum

また、シグモイド関数の中身は1/(1+exp(-x))をdouble型でベタに実行していますが、実行時間はというと・・

Sigmoid

100クロック以上使っています。

浮動小数点の除算や、exp、加算などを愚直に行っているようでした。これならソフト、というかNEONでやったほうが速いかもしれませんね。

でも、sigmoid関数の計算はニューロン1個に対して1回なので、それほどパフォーマンスに影響はしないのではないかと思われます。

sun

リソース使用量は76%。ほとんどがシグモイド関数だと思われます。

Utilize

結果はというと、

  • オライリー本の第3章のMNIST認識多層パーセプトロンのプログラムをCで書き直してSDSoCに移植
  • ZYNQのARMより2~3倍高速
  • 何も考えなくても、浮動小数点のシグモイド関数ができてしまった!

私もついにSDSoCデビューできました。

sun

こちらのスタータキットを使って試せるよう、デザインのアップロードを準備中です。

https://www.trenz.jp/product/TE0726-STARTER-KIT

お楽しみに

| | コメント (0)

2018.08.25

ZynqberryにRasPiカメラをつなでJupyterで表示

世の中にはたくさんの種類のZYNQボードがあります。

どんなZYNQボードでも、Jupyterや機械学習やSDSoCは動きます。

私は言いたい。

「PYNQにできることは他のZYNQボードにだってできる。」

PYNQ一辺倒の世の中に一石を投じ、脱PYNQ化を進めるため、ZynqberryにRaspberryカメラを接続し、画像をJupyter上で表示させてみることにしました。

Zynqberry(ジンクベリー)というのは、ドイツTrenzElectronic社が開発したZYNQボードで、その名のとおりRaspberry Pi形状のZYNQボードです。

Te072603m_0

ZynqberryはRaspiカメラ(V1.3)とHDMI出力をつなげることができます。

Zbcam

まず、公式サイト https://shop.trenz-electronic.de/en/TE0726-03M-ZynqBerry-Zynq-7010-in-Raspberry-Pi-form-factor のページにあるDownloadタブからReference Design→2017.1→zynqberrydemo1をダウンロードし、書き込んで動かします。

zynqberrydemo1のサンプルプログラムを動かすと、SDカード上にあるinit.shが起動され、その中で

rpicam /dev/i2c-5
devmem 0x43c10040 32 $rc

という2つのプログラムが動作します。

rpicamはTrenz社が作成したプログラムで、ソースはzynqberrydemo1\os\petalinux\project-spec\meta-user\recipes-apps\rpicam\files にあります。

Rpicam

中を見てみると、V1.3用のコードとV2.1用のコードがあり、解像度もいくつか用意されているようです。基本的にはI2Cのレジスタを操作してカメラの設定を行っています。

devmemは単体のプログラムではなく、busyboxの中の機能です。このコマンドは0x431c0040番地に1または3を書き込んで、VDMAの転送を開始します。

フレームバッファとビデオタイミングコントローラはFSBLで初期化され、RasPiカメラから取り込んだ画像が0x1FC00000に格納されます。

サンプルのzynqberrydemo1では0x1FC00000は画面に出力するバッファにもなっているので、カメラで撮った画像がそのままHDMIから出力されます。

zynqberrydemo1と3はRAMDISKで動くシンプルなLinuxなので、GUIのデスクトップは動きません。zynqberrydemo3は、カメラバッファと表示バッファが別々のアドレスなので、そのまま出力はされませんが、

dd if=/dev/fb1 of=/dev/fb0 bs=5120 count=720

で表示することができます。(ddすごい!)

sun

使用したカメラは、秋月で購入しました。

Akizuki_cam

sun

Zynqberryにはスタータキットというのがあり、Ubuntu Linux 14.04とJupyterが動くように作りこまれています。Trenz社のサンプルとはLinuxのディストリビューションが全く異なるのですが、zynqberrydemo1で使用されていたrpicamはUbuntu 14.04に持っていっても動きました。

devmemはbusyboxのコマンドなので、同等のものを/dev/memを叩いて動かすようにします。こうすることで、リッチなUbuntu LinuxでもRasPiカメラを動かすことができます。

int fd = open("/dev/mem", O_RDWR | O_SYNC);
uint32_t *vaddr = (uint32_t *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x43c10000);
*(vaddr + 0x10) = 0x1; // 0x43c10040
munmap((void*)vaddr, 4096);
close(fd);

Linuxが起動したら、ddを使って/dev/fb1から生画像を得ることができます。

また、fbgrabというツールを使うことで、フレームバッファの中身をPNG画像として保存することもできます。

Fbgrab

fbgrabで画像を取得する時間は10秒くらいかかりました。結構遅いので、その間に手ブレすると歪んでしまいます。

Test

ddまたはfbgrabで画像が読み出せることがわかったので、Jupyter上で画像を表示させてみることにします。

ZynqberryでJupyterを動かす方法は「ZynqberryでJupyter notebookを動かそう!」 にあります。

書いたPythonのコードは

#for Zynqberry Stater kit (https://www.trenz.jp/product/TE0726-STARTER-KIT)
from PIL import Image
 
import matplotlib.pyplot as plt
import numpy as np
import subprocess

subprocess.call(["/usr/bin/fbgrab","-d","/dev/fb1","/tmp/grab.png"])
im = np.array(Image.open("/tmp/grab.png"))
plt.figure(dpi=100)
plt.imshow(im)

です。

このとおり、Jupyter上で、カメラ画像を表示することができました。

Zb_jupyter_camera

| | コメント (0)

2018.08.24

Spartan-7ボードを設計しています2

Spartan-7ボードですが、FPGAを45度回転させることで配線がすっきりし、ここまでできました。

Sp7brd2

USBのコネクタは最近流行りのMicro-Bにして、EZ-USB FX2を使って480Mbpsの速度を出します。UARTではないので画像も流せるほど高速です。

9月中に試作が完了し、発売開始できるのではないかと思います。

| | コメント (0)

2018.08.23

Spartan-7ボードを設計しています

特電のアルバイトさんが、Spartan-7ボードを設計してくれています。

Sp7brd

名刺サイズで、XC7S50を中心にDDR3メモリとUSB2.0が乗っていて、40ピンx2のコネクタから64本のI/Oを取り出せます。

2.54ピッチなので、万能基板に乗せてケーブルを引き出すことができる、試作用途に使いやすいボードになります。

メザニンコネクタではないので、ユーザが拡張するのにわざわざ基板を起こす必要がありません。それに、PMODでもないのでたくさんのI/Oが使えます。

USB2.0は、遅いUARTではなく、40MByte/secが出る生のHighspeed(デバドラあり)なので、画像の転送にも使えます。

sun

さて、Spartan-7は、コア電源1.0VとAUX電源1.8Vを必要とし、DDR3メモリを使うには1.5Vが必要になります。また、入出力にLVDSを使う場合はこれに加えて2.5Vが必要になります。

そういうわけでこの基板は5種類の電源が使われることになりますが、VCCAUXの1.8Vって何に使うのでしょう。

FPGAが空のときは20mA程度ですが、PowerEstimaterを使って調べてみるとDDR3を動かしたデザインでは250mA程度消費します。

たぶん、コアの1.0Vロジックと外部のVCCIOのバッファの間に入って信号を中継するバッファに使われているのではないかと思うのですが、いまいちわかりません。

| | コメント (0)

2018.08.22

ZYNQ UltraScale+のJTAGに異常を発見

Ultra96ボードを入手して、さっそくやってみたことはJTAGのテストです。

Uscale1

ボードから12Vの電源と、JTAGの配線を引き出してテスト開始です。

MITOUJTAGで認識させてみると、XCZU3しか見つかりません。実際にはXCZU3のほかにARMのDAPというのがつながっているので2個のデバイスが見つかるはずなのですが・・

そこで、SVFプレイヤーを用いて

STATE RESET;
STATE IDLE;
SDR 128 TDI (00000000000000000000000000000000) TDO (00000000000000000000000000000000);

というコマンドを実行して、JTAGの低レベルなデバッグをしてみると、XCZU3のIDCODEが1bitずれたものが読み出されました。

ARM DAPのDRが1bitになっていて(ZYNQ7000では32bitあった)、JTAG IDCODEが存在していないことがわかります。これは、ちょっと問題です。ARM DAPのIRは4bit長なので規格どおりですが。

この点は、ARM DAPのBSDLを作成して手動で追加すれば何とかなりました。

MITOUJTAGのバウンダリスキャンで、端子のI/Oが見えているように見えます。

Uscale2

また、端子のAA3、AA4あたりをEXTESTで動かすとLEDがチカチカするので、MITOUJTAGから操作もできていることがわかりました。

Uscale3

しかし、問題はここからです。基板上のSW4を押してもそれに相当する端子の状態が変化しないのです。

Uscale4

これはUltraScale+の持つJTAGのバグではないかと思います。

sun

本来、JTAGバウンダリスキャンでは、I/Oパッドから入力した値は入力セルから読み出されます。

Bscan1_2

しかし、コンフィギュレーションされたUltraScale+では、なぜか出力セルから読み出されます。

Bscan2

これが仕様なのか設計ミスなのかわかりませんが、JTAGの動作としては間違っているように思われます。

なお、バウンダリスキャンセルを手動で書き換えて、出力セルの値を見るようにすると、一見正しい動作をするのですが、FPGAが出力する値を読めなくなってしまうので、これも正しくありません。

Bscan3

BSDLファイルが間違っているというわけではなく、チップレベルで間違っているようです。

sun

それから、DDR4メモリの端子が全く動いていないことも気になります。Ultra96ボードのデフォルトのSDカードでは、DDRメモリは使用していないのでしょうか。

| | コメント (0)

«UltraScale+用のJTAG書き込みアルゴリズム