« 2013年3月 | トップページ | 2013年5月 »

2013.04.26

PCI Expressの本が出版されました

なひたふの書いた本「FPGAでゼロから作るPCI Express: PC拡張用の定番バスはこうやって動かす」が、本日、出版されました。

この本は、Interface誌に連載したPCI Expressの記事をまとめて本にしたものです。単なるPCI Expressの解説本ではなく、PCI ExpressのプロトコルをどのようにFPGAに実装していくかという試行錯誤の過程が書かれたものです。

Techi54_1_2

この本の中には、FPGAの話だけではなく、Windowsデバイスドライバの作り方や、Windowsでの割り込みやDMAの話、基板設計の話、測定の話など、PCI Expressを自作する人が必要になりそうなことを詰め込みました。

基板設計の話と測定の話は、連載の時点ではなかった新しい原稿です。

Techi54_2

そして、ページ数はなんと、255ページもあります。とても分厚いです。
TECH-Iの中でも一番厚いのではないかと思います。

この本には、プロトコルを処理するような面倒なロジックを、どのようにしてステートマシンに落とし、最終的にHDLに落としこんでいくか、ということが書かれているわけです。

最近では『FPGAをHDLで書くスタイルは古い』という話もあります。それは事実だと思います。けれども、それは誰かがHDLで書いたIPコアを積み木のように重ねているだけなので、そういうIPコアを作る人もどこかに必要なのではないかと、私は思うのです。

「XPSやQsysを使ってFPGAができました」というのではなく、そういう人たちに使ってもらうための回路設計をするレアな人になりたい、そういう方のための本ではないかと思います。つまり、FPGAのコアを作る中の人のための本というわけです。

でも、そういう人は少なくなっているし、HDLでガリガリと書いていく人はこれからもどんどん減っていく(=希少な存在になる)でしょうから、あまり販売数量は見込めなかったと聞きました。その結果、ちょっとお値段が高めの4800円になってしまったそうです。

でも、そんな出版側の予想を跳ね返して、ぜひとも、第二版の増刷が見込めるように、お力をお貸しください。

Amazonでも販売されています。ぜひとも、皆様ご購入をお願いします!

http://www.amazon.co.jp/dp/4789849821/

現在の順位は、

Amazon ベストセラー商品ランキング: 本 - 3,831位 (本のベストセラーを見る)
38位 ─ 本 > 資格・検定 > ビジネス関連
179位 ─ 本 > コンピュータ・IT

Techi54

皆様、どうかよろしくお願いします。

| | コメント (3)

2013.04.22

MITOUJTAGでLattice MachXO2の書き込み

LatticeのCPLD(FPGA?)にMachXO2というのがあります。このMachXO2の評価ボードは秋月でも売られていて、入手も容易です。

MITOUJTAGでこのMachXO2が扱えるかどうかを試してみることにしました。

まず、バウンダリスキャンを行って、デフォルトのLEDチカチカの動作を見てみました。

Machxo2_bscan

ここまでは問題なし。MITOUJTAGでちゃんとバウンダリスキャンができました。

さて、Latticeに書き込む方法なのですが、実は、MITOUJTAGはMACHXO2のJEDECファイルを書き込むためのアルゴリズムを知りません。そのため、SVFファイルというのを経由してやる必要があるのです。

そのためには、Lattice Diamondで生成したJEDファイルを、Latticeのツールを使ってSVFファイルに変換してやる必要があります。

その手順は次のとおりです。

1.まず、WindowsのメニューからLattice DiamondのAccessoriesの中にあるDeployment Toolを起動します。

Xc2svf_1

2.Diamond Deployment Toolが起動したら、最初のダイアログで、
 Function Type=Tester
 SVF - Single Device

を選択し、OKを押します。

Xo2svf_2

3.「Step 1 of 4」と書かれたダイアログが表示されたら、File Nameの欄に、Diamondで生成したJEDECファイルを指定します。

Xo2svf_3

4.「Step 2 of 4」と書かれたダイアログでは、Rev D Standard SVFと、RUNTEST from Rev CのチェックをONにします。

Xo2svf_4

5.「Step 3 of 4」と書かれたダイアログでは、出力するSVFファイルの名前を入力します。

Xo2svf_5

6.「Step 4 of 4」と書かれたダイアログでGenerateを押すと、進捗バーが動いて、SVFファイルが生成されます。

Xo2svf_6

Xo2svf_7

7.こうしてSVFファイルが生成されたら、MITOUJTAGで書き込むための準備をします。
MITOUJTAGを起動たら、デバイスの自動認識を行って、Lattice MachXO2が見えていることを確認します。このとき、デバイスの形状が正確に表示されなくても構いません。

Xo2svf_8

8.Pocket JTAG Cableのアイコンをダブルクリックし、Pocket JTAG Cableの設定画面を出してください。下の図のようなダイアログが表示された場合は、OKを押します。

Xo2svf_9

9.Pocket JTAG Cableの設定画面では、TCK=1MHz、高速化オプションはOFFにしてください。

Xo2svf_10

10.メインメニューから[ツール→SVFプレイヤー]を起動し、[ファイル→開く]で先ほど作成したSVFファイルを開きます。すると、真っ白な画面の領域にSVFファイルが読みこまれて表示されます。

Xo2svf_11

11.メインメニューにある「開始ボタン」を押します。

Xo2svf_12

12.SVFファイルが実行され、CPLDへの書き込みが行われます。

Xo2svf_13

このように、SVFファイルを経由して、LatticeのMachXO2に書き込みができました。

実際にご利用になる際には、さらに細かい注意点がいくつかありますので、ぜひお問い合わせください。

LatticeのSVFファイルはLOOPという独自の拡張命令が入っています。これを使えるようになると、書き込み速度の高速化が期待できます。

そういうわけで、SVFプレイヤーのDLLを更新して、LOOP命令に対応させたり、TCK周波数の変更などの手続きをしなくても動くように改良しようとしています。

ご期待ください!

| | コメント (3)

2013.04.21

ZED BoardでOSERDES、ISERDESを試してみる

XILINXのFPGAには、OSERDES、ISERDESというのがあります。

Iserdesoserdes

これは、普通のI/Oピンの中にSERDESが組み込まれているもので、ほとんどすべてのI/Oで使えます。つまり、普通のI/Oが1Gbpsくらいの信号が入出力できる、高速トランシーバになるというものなのです。しかも、ISERDESにはIDELAYといって微小な可変ディレイを入れることもできます。

このSERDESはSpartan-6やVirtex-4から使えるようになったので、当然ながら7シリーズのZYNQでも使えます。というわけで、今日はこれを試してみました。

まず、ISERDES/OSERDESは、自分でプリミティブからできなくもありませんが、CoreGenを使ったほうが楽です。無理をせずにCoregenを使いましょう。

Coregen


そして、OSERDES10個と、ISERDES9個をZYNQの中にインスタンシエートしてみました。

さて、ZED Boardでは、ZYNQのPL部分(FPGAのロジック部分のこと)は、BANK13、BANK33、BANK34、BANK35の4つのI/Oバンクが使えます。このうち、BANK13と33は3.3Vの固定I/O電圧です。BANK34とBANK35は、VADJという名前で2.5Vまたは1.8Vに設定できます(自分でジャンパJ18の未実装の部分をつなげば3.3Vにもできる)。このBANK34と35はFMCコネクタに出ている信号に主に使われます。

つまり、高速な差動信号を使いたいなら、BANK34とBANK35を使って、FMCからやりとりしなければなりません。

ですが、FMCは表面実装で実装が大変だったので、とりあえず、ピンヘッダの部分から高速差動信号を出すようにしました。

JC1_P/Nからクロックを出力したクロックをJA4とJA10から入力し、JC2_P/Nから出した信号をJC4_P/Nから入力し、JD1_P/Nから出した信号をJD3_P/Nから入力するようにして、自分自身で出した高速差動信号を自分自身で受けるようにしてみました。

Zynq_loopback1


これなら、ピンヘッダ部分にジャンパをはめ込むだけで、ループバックの試験ができるはずです。クロックは専用ピンから入力しないといけないので、ちょっと配線しなければだめでしたが。

Zynq_loopback2


こんな感じでループバックしてみたのですが、データレートが100MHzくらいなら問題なく動きました。でも、目的の960MHzにすると、データ化けが多発します。

下の図は、ゆっくり変化するバイナリカウンタを、960MHzの速度で送って、それを受けて、LEDに表示してみたものです。要するに、高速差動信号でLEDチカチカを送ってみたわけです。

Zynq_led


みてのとおり、信号が変化するところでバタバタとしています。

しかたがないので、ISERDESの前にIDELAY2を入れて、遅延を調整して、もっともベストなポイントでデータをサンプリングできるようにしてみたのですが、それでもダメ。普通は遅延をいれてベストなポイントに合わせさえすれば問題なくできるはずなのですが、そうもいかないようです。おそらくシンボル間干渉が起きているのでしょう。

やはり、このジャンパを通じて960Mbpsをやりとりするのは無理があるのかもしれません。FMCの嵌合するコネクタを入手したので、今度はこれで試してみることにします。

Zedboard_fmc

ZED Boardで使われているコネクタはASP-134603-01というもので、それに対応するコネクタはASP-134604-01ですが、Digikeyでは手に入りません。

うまく嵌合するコネクタで入手可能なものは10列のやつです。400ピンのコネクタですがZEDボードに挿すときにはそのうちの160個を使います。型番や入手先は上の写真をご覧ください。

今日得られた知見は次のとおりです。

  • OSERDES、ISERDESのビット幅はSDRのときには2~8bit。DDRのときには4,6,8,10,14bit。12bitには設定できないので要注意。
  • ZYNQのLVDS_25は、VCCIOが本当に2.5Vでなければだめ。3.3Vにすると信号が出なくなる。1.8Vでは出てくるが、サポート外。
  • I/O規格をDIFF_SSTL18_IIとかにすると、確かに信号は出てきたけど、正しく読み取れなかった。おそらく、同じ値が何ビットもつづくと電圧がどっちかに大きく振れてしまうからだと思われる。
  • IDELAYのためのリファレンスクロックは200MHzでなければならない。そうしないと、タイミング解析でエラーが出るほか、遅延時間が正しくならないのかもしれない。
  • CoreGenが作るISERDESのラッパは、IDELAYのクロックにdiv_clkを使う。そういうものなのかもしれない。つまり、IDELAYのクロック入力「C」は、本来、リカバリして出てきたクロックを与えるものなのかもしれない。
  • ISERDESで使うことができるクロック端子とデータ入力端子組み合わせには、制約がある。

| | コメント (0)

2013.04.19

LT Spiceを使ってみた

最近、アナログ回路の設計を行っているのですが、やはりシミュレータがほしくなります。

昔のDesignWaveMagazineの第12号に付属していたPSpiceはあるのですが、ちょっと古すぎます。

最近はLT Spiceというのが流行っているようなので、この使い方を学んでみました。

ダウンロードページはこちら。

http://www.linear-tech.co.jp/designtools/software/

参考にしたページはこちら。

http://homepage1.nifty.com/ntoshio/rakuen/spice/1st/index.htm

回路図エディタに相当な癖がありますが、回路図を書くことが目的ではなく、ノードの接続を描くことが目的なのですから、これでいいのでしょう。

試しに適当な回路を描いてみました。

Ltspice


ちゃんと動いています。それに、結構速い!

LT Spiceは重宝しそうです!

| | コメント (0)

2013.04.18

MITOUJTAGの遠隔操作スクリプト機能をリリースします

MITOUJTAG Proには、JTAGスクリプト機能があります。この機能を使うと、ユーザプログラムの中から、

if(SW == 0) LED <= 1;
for(int i=0;i<1000;i++) GPIO <= i;

のように、VHDLのような矢印 <= を用いて、C言語で端子の動作をプログラムできます。

この機能は今までもMITOUJTAG Proに入っていたのですが、今回の更新ではこのスクリプト機能をユーザプログラムの中から使えるような「リモート操作機能」を作りました。

つまり、ユーザが、VisualStudioや、C++ Builderでもなんでもいいのですが、C++で作成したプログラムの中で、 if(SW == 0) LED <= 1; のような記述をすれば、ユーザプログラムの中からMITOUJTAGを操作して、実際のハードウェア上の信号にアクセスできてしまうというわけです。

そのためのプログラムをここに置いておきます。

さて、このMITOUJTAGのスクリプト機能はとても強力です。LEDをチカチカさせるだけではなく、SDRAMの検査などもできてしまいます。

MITOUJTAGにはSDRAM操作ライブラリとして、こんな感じのプログラムがあるのですが、

static void set_clock_0()
{
	*dsigs->ck <= "0";
}

static void set_clock_1()
{
	*dsigs->ck <= "1";
}
・・・
void sdram_read_mem(unsigned long *buf,unsigned long addr,int len)
{
	unsigned long *p = buf;
	set_dm(0);
	cmd_act((addr >> 20) & 0x3 ,(addr >> 8) & 0xfff);
	cmd_nop();
	cmd_nop();

	int fin = false;
	int step = 0;
	int maxstep = len + 2;
	*dsigs->d <= "Z";
	for(step = 0;step < maxstep ; step++)
	{
		if(step >= maxstep - 2 - 8)
		{
			fin = true;
		}
		if((step & 7) == 0)
		{
			*dsigs->cas  = "0";
			*dsigs->ba   = (addr >> 20) & 0x3;
			*dsigs->a    = (addr & 0xff) | (fin ? 0x0400 : 0); // A10 = 1
		}
		else
		{
			*dsigs->cas  = "1";
		}
		set_clock_0();
		・・・・

このように普通のC言語で端子の状態を書けてしまうのです。

で、実際にやってみたときの波形がこちら。

Jtagsdram


RASとかCASとか、データ線とかアドレス線とか、そういった信号をバウンダリスキャンで動かしています。

実は、これは究極のRX62Nボード上にあるSDRAMのためのメモリテストです。

Rx62n_bscan


このボードはRX62NのBGA176ピンを使っていて、SDRAMもBGAなので、RX62NとSDRAM間の配線はオシロではあたることができません。幸いなことにRX62Nはバウンダリスキャンに対応しているので、I/O端子をJTAG経由で自由に操作できます。

C言語とバウンダリスキャンを組み合わせればどこまで複雑な波形が作れるかという一例を紹介します。

次の図では、SDRAMのバーストリードやバーストライトコマンドを発行しているのが見えます。A12と書かれた端子が実際にはA10につながっているので、ここが1になればオートプリチャージを示しているわけです。

Jtagsdramburst


SDRAMのメモリテストの内容は、

  1. 32本のデータバスのうち1本だけを順次'1'にする (walking 1)
  2. 32本のデータバスのうち1本だけを順次'0'にする (walking 0)
  3. アドレス線の1本だけを1にしたアドレスを生成して、乱数を読み書きする

このようなシーケンスを生成して、書いたデータを読んだデータを照合して、データ線やアドレス線に断線やショートがないかどうかを効率よく検査しています。

もしボード上の接続が正常ならば、

●データバスは正常につながっています
●アドレスバスは正常につながっています

と表示されますが、異常が見つかった場合は、

●D[15]に異常があります
★アドレス00100000への読み書きでエラーが生じています

のように表示されるので、どこに実装不良があるかわかるというわけです。(幸いなことに不良はまだありませんが)

このような感じで、BGAの基板検査も楽々できてしまいます。

さて、この機能を使うにはCコンパイラがなければなりませんが、このたび、BorlandC++と、GCCとVisualC++に対応しました。

使い方はとても簡単で、ユーザが作ったプログラムに、AjfgClient.DLLを組み込むだけです。どんなプログラムからでもMITOUJTAGに遠隔アクセスできるようになります。

  • Borland C++なら、bcc32 sample.cpp AjfgClient_bcc.lib
  • Vislal C++なら、cl sample.cpp AjfgClient_vc.lib
  • GCC(MinGW)なら、gcc sample.cpp AjfgClient_mingw.a -o sample.exe

とビルドすればOKです。

詳しい使い方は、サンプルプログラムの中のREADMEをご覧ください。

MITOUJTAGで快適な基板の操作をお楽しみください。

| | コメント (0)

2013.04.15

Xeonのマシンの組み立て

サポート掲示板のほうで、XeonとWindows7 64bit版でEXPARTAN-6Tがうまく動かないというご意見が寄せられたので、同じ構成のマシンを作ってみることにしました。

そのCPUは、XeonのE3-1275で、チップセットはC206とのことでした。さっそく秋葉原に買いに行ったのですが、ショップの店員さんによればC206のマザーボードはこれしかないとのことで、Intelの「Server Board S1200KP」というものを買いました。また、せっかくだから160GBのSSDを買うことにしました。

Xeon_mb_ssd

これでワシもXeonデビューだと心躍りました。

このマザーボードはMini-ITX仕様の小型のものです。昨年、アルバイトの優秀な学生さんが、Mini-ITXの筐体(JX-FS100B)にCore-i7のボードをギチギチに詰め込んだマシンを作ってくれていたので、そのガワを再利用することにしました。

Mini-ITXの筐体は狭いのでCPUに元からついているヒートシンクが使えません。そこで、薄型で平べったいヒートシンクを使います。

Xeonheatsink

すると、CPUのファンのところにつなぐコネクタがヒートシンクの下に隠れてしまうので、筐体用ヒートシンクのコネクタからCPU用ファンの配線をつなぎます。

中蓋にSSDとDVDドライブを取り付けて、筐体に収めるとこんな感じ。

Xeonminiitx_2

ちゃんと蓋も締まります。

Xeonminiitx2

そして、Windows 7のインストールを行います。SSDだから超速い。

これでベンチマークしてめでたしめでたし・・・ではなくて、目的はPCI Expressの動作を調べることですから、再び蓋をあけてPCI Expressのコネクタを探します。

Mini-ITXという筐体のパソコンはPCI Expressの拡張スロットに何もさせません。何かを挿そうとすると筐体にぶつかります。そこで、PCI Expressの拡張治具を使います。

Xeonpcie_1

このマザーボードにはPCI Expressのスロットが1つしかなくて、しかもそのx16のスロットを、エクステンダーでx1にして引き出します。

そして、こんな感じでEXPARTAN-6Tボードをつなぎました。

Xeonpcie_2

ちゃんと動いてくれました。

そして、ようやくPCI ExpressのPIOリードとライトの波形がみられるようになりました。

まず、PIOリードの波形。

Xeonpioread_2


なんと、4DWのリードが発行されている!!

今まで1DWや2DWしか見たことがなかったのですが、はじめて4DWのリードを見ました。しかも、Core2のころは各パケットの間隔が1.8usくらいだったのに、Xeonでは1.4usに縮まっています。その結果、PIOリードのスループットは10MB/secくらいになりました。Core2やPentium4のころの4倍の速度です。

でも、大きな違いはこのくらいです。後は特に違いはありませんでした。

PIO(コンバインド)ライトはまったく同じでした。

Xeoncombwrite

190MB/secくらいのスループットで平常運転しています。

私としてはXeon=食パンみたいなイメージしかなかったのですが、今のXeonはCorei3/5/7と同じ格好をしているのですね。初めてXeonを触ってみたのですが、なんか、Xeonという名前のカッコよさに惹かれてわくわくします。

このXeonマシンは今後、XILINX ISEのビルド用マシンにされる予定です。

| | コメント (0)

2013.04.13

PCI ExpressのPIOリードの謎(2)

昨日の、PIOリードのアドレスがバラバラになる件ですが、PCI ExpressのBAR空間をMmMapIoSpaceで仮想アドレスを割り当てるときに、

PVOID MmMapIoSpace(
  _In_  PHYSICAL_ADDRESS PhysicalAddress,
  _In_  SIZE_T NumberOfBytes,
  _In_  MEMORY_CACHING_TYPE CacheType
);

の第三引数MEMORY_CACHING_TYPE CacheTypeをどうするかで挙動が変わることがわかりました。

このタイプは、MmNonCachedか、MmCachedか、MmWriteCombinedなのですが、MmWriteCombinedにしておくとWriteは超高速になります。なお、MmWriteCombinedにしておくと書き込みアドレスの順序がバラバラになるのは仕方がないことです。

MSDNのドキュメントによればキャッシュに関してはMmWriteCombinedもMmNonCachedもキャッシュされないとあるので同じだと思うのですが、読み出したときの挙動は、

  • MmNonCached → 読み出しアドレスは順番
  • MmCached → 読み出しアドレスは順番
  • MmWriteCombined → 読み出しアドレスはバラバラ 2DWリードも発行される

でした。

MmNonCachedでアドレスが順番になるのはいいのですが、2DWリードが発行されないので、速度は遅くなります。あまりメリットはありません。

| | コメント (0)

2013.04.12

PCI ExpressのPIOリードの謎

PCI ExpressのPIOリードで不思議なことが起こっています。

まず、最初の波形をご覧ください。これはWindowsXPで、物理メモリ拡張したマシンでの実際の波形なのですが、

Pae_piord_comp

PC→FPGA方向に、00000001 00001E0F FEBE0000というパケットが流れています。
これは、メモリリードで、32bitアドレスのFEBE0000番地を読み出せ、というコマンドです。

FPGAは、4A000001 02000004 00001E00 F3BC756Bという応答をしています。
これは、このパケット(タグ1E)に対する応答はF3BC756Bだよと返しています。

さて、これだけ見るとふつうの1DWのリードコマンドとそのコンプリーションなのですが、PIOリードのサイズを大きくしていくと、不思議なことが起こりました。

次の図は、PIOリードのサイズを大きくした場合です。

Pae_piord_comp_1mbyte

なんと、2ワードのリード要求が発行されているのです。

PC→FPGA方向に、00000002 00001CFF FEBE99E8というパケットが流れています。
これは、メモリリードで、32bitアドレスのFEBE99E8番地から2DWを読み出せ、というコマンドです。

FPGAは、4A000002 02000008 00001C68 34DC61D2 AA0C28・・という応答をしています。
これは、このパケット(タグ1E)に対する応答は34DC61D2 AA0C28・・だよと返しています。

普段32bitのPIOリードしか発行しないはずなのに、なぜか64bitサイズで読み出しリクエストしています。不思議ですね~

1DWになったり2DWになったりする現象は、Windows 7 64bit版でも起きています。

Win764bit_piord_comp

PC→FPGA方向に、00000002 000008FF FEBEAF90というパケットが流れています。
これは、メモリリードで、32bitアドレスのFEBEAF90番地から2DWを読み出せ、というコマンドです。

FPGAは、4A000002 02000008 00000810 326DFE5C 3AB955EEという応答をしています。これは、このパケット(タグ1E)に対する応答は326DFE5C 3AB955EEだよと返しています。

どうやらわかってきたことは、アドレスのBAR+0番地から始まる流れでは1DWの読み出しが行われて、中途半端なアドレスから流れでは2DWで行われるようです。

そして、さらに波形を3回とって調べていったところ、

1回目
RD FBEB0000 4byte
RD FBEB0040 8byte
RD FBEB0004 4byte
RD FBEB0048 8byte
RD FBEB0008 4byte
・・・

2回目
RD FBEB04D0 8byte
RD FBEB0508 8byte
RD FBEB0548 8byte
RD FBEB04B0 8byte
RD FBEB04D8 8byte
・・・

3回目
RD FBEB0000 4byte
RD FBEB000C 4byte
RD FBEB0018 4byte
RD FBEB001C 4byte
RD FBEB0008 4byte
・・・

こういう感じでした。

PIOリードの場合はアドレス0から順に読んでいくのではなくて、2つ以上の流れがあってそれぞれ勝手に読んでいるのです。

1回目の読み出しシーケンスを見てみると、

  1. FBEB0000→FBEB0004→FBEB0008
  2. FBEB0040→FBEB0048

という2つの流れが確認できます。

2回目の読み出しシーケンスを見てみると、

  1. FBEB04D0→FBEB04D8
  2. FBEB0508
  3. FBEB0548
  4. FBEB04B0

という4つの流れが確認できます。

3回目の読み出しシーケンスを見てみると、

  1. FBEB0000→FBEB0008
  2. FBEB000C
  3. FBEB0018→FBEB001C

という3つの流れが見えます。

この流れがなんなのかはわかりませんが、読み出すアドレスがバラバラになっているような感じがします。

このような処理をチップセットで行っているのか、それともHALが行っているのかはわかりません。もしかすると、PIOリードは時間がかかるということで複数の読み出しが行われるように勝手に複数のスレッドに分割されているのかもしれません。

引き続き調査します。

| | コメント (0)

2013.04.09

MITOUJTAG Proの遠隔操作

MITOUJTAG Proの特徴は、JTAGスクリプトといって、C++言語を使ってバウンダリスキャンのやりかたを記述できるところにあります。

この機能を拡張して、ユーザが作ったプログラムにDLLを組み込むだけで、MITOUJTAGを介して端子の遠隔操作ができるようにしようと思っています。

この計画は2年ほど前に始めて作りかけの途中だったのですが、この2~3日で再び進めています。だいぶん安定して動くようになってきました。

まず最初はSpartan-6で簡単に試してみます。

最初にSpartan-6を認識したところの画面をご覧ください。

Mitoujtag_remote_sp6_2 

ここで右上にあるAdvanced JTAG Function Generatorの「待ちうけ」と書かれたボタンを押すと、外部のプログラムから接続を待ちうけるようになります。

作ったプログラムはこんな感じ。とても簡単です。

#include "sp6.h"

#define AJFG_CLI_API extern "C" __declspec(dllimport)
AJFG_CLI_API int AJFGInitialize(const char *pin_file);

int main(int argc,char *argv[])
{
	int errcode = AJFGInitialize("sp6.pin");  // ピン定義ファイルを指定
    if(errcode == ERR_CANNOTCONNECT)
    {
        printf("MITOUJTAGサーバに接続できませんでした\n");
        return -1;
	}
    if(errcode < 0)
    {
        printf("MITOUJTAGサーバに接続中にエラーが発生しました code=%d\n",errcode);
        return -1;
	}

	j_bypass();
	j_sample();j_extest(); // AJFGで端子を操作するにはこの行を有効にしてください
	for(int i=0;i<100;i++)
	{
		LED <= i;
	}

	return 0;
}

そして、メインのプログラムとは別にsp6.pinというファイルを作っておきます。LEDと、SWという名前の信号が、どのピンにつながっているかを指定するためのファイルです。

LED A7 B8 A8 B9 A9 C9 C11 F13 
SW  D6

次にビルドします。今はBorland C++でしかコンパイルできませんが、今日の夜にはVisual C++やMinGWにも対応しているでしょう。

bcc32 sp6.cpp AjfgClient.lib

出来上がったsp6.exeを実行すると、ボード上のLEDがチカチカ・・と光るのが見えます。

Sp6_remote

ユーザプログラムが終わったときの状態は、こんな感じです。

Mitoujtag_remote_sp6_end

この「待ちうけ」状態は、「停止」を押すまで繰り返し使えますので、MITOUJTAGには一切手を触れずにsp6.exeを何度も何度も起動できます。つまり、MITOUJTAGは常駐型のJTAGプログラムになって、プロセス間通信の要領でユーザプログラムからの指令を待つようにできるというわけです。

LEDチカチカだけではなく、結構複雑なこともできます。例えば、基板の実装検査なんかにバウンダリスキャンは最適です。

Mitoujtag_remote1

次のプログラムは、究極のRX62Nボード上のSDRAMの端子をJTAGバウンダリスキャンで操作して、SDRAMの動作テストを行うものです。SDRAMはJTAGに対応していませんが、RX62NがJTAGに対応しているので、バウンダリスキャンで操作して間接的に読み書きして検査するというものです。

// バウンダリスキャンでSDRAMの読み出し

#include "jtagscr.h" // JTAGスクリプト
#include "pindef.h"  // ピン定義(ユーザ定義)

#define AJFG_CLI_API extern "C" __declspec(dllimport)
AJFG_CLI_API int AJFGInitialize(const char *pin_file);

unsigned long sd_cmd(int ba,int addr,int ras,int cas,int wen,int cs)
{
	SD_A   = addr; SD_BA  = ba;
	SD_RAS = ras; SD_CAS = cas; SD_WEN = wen; SD_CS = cs;
	SD_CLK <= "0"; SD_CLK <= "1"; // クロックトグル
	return SD_D;
}

int main(int argc,char *argv[])
{
    if(AJFGInitialize("sample.pin") < 0) // ピン定義ファイルを指定
    {
        printf("MITOUJTAGサーバに接続できませんでした\n");
        Sleep(1000);
        return -1;
    }

	j_bypass();j_sample();j_extest();
	SD_D   = "Z"; SD_CKE <= "1"; // 初期設定
	sd_cmd(0,0,1,1,1,1); // インアクティブ
	sd_cmd(0,0x400,0,1,0,0); // プリチャージ
	for(int i=0;i<10;i++) {
		sd_cmd(0,    0,1,1,1,0); // NOP
	}
	sd_cmd(0,0x400,0,1,0,0); // プリチャージ
	for(int i=0;i<10;i++) {
		sd_cmd(0,    0,1,1,1,0); // NOP
	}
	// モードレジスタセット
	sd_cmd(0, 0x23,0,0,0,0); // CL=2,Burst=8
	for(int i=0;i<10;i++) {
		sd_cmd(0,    0,1,1,1,0); // NOP
	}
	sd_cmd(0,    0,0,1,1,0); // ROWアドレスセット
	sd_cmd(0,    0,1,1,1,0); // NOP
	SD_D <= 0x12345678; sd_cmd(0,0,1,0,0,0); // ライト
	SD_D <= 0x11111111; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x22222222; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x33333333; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x13579bdf; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0xdeadbeef; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x98765432; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x31323123; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x2345aaaa; sd_cmd(0,0x408,1,0,0,0); // ライト
	SD_D <= 0x30303030; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0xffffffff; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x00000000; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x5a5a5a5a; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0xa5a5a5a5; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x69966996; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= 0x96699669; sd_cmd(0,0,1,1,1,0); // NOP
	SD_D <= "Z";
	sd_cmd(0,    0,1,1,1,0); // NOP
	sd_cmd(0,    0,1,1,1,0); // NOP
	sd_cmd(0,    0,1,1,1,0); // NOP
	sd_cmd(0,    0,1,1,1,0); // NOP

	sd_cmd(0,    0,0,1,1,0); // ROWアドレスセット
	sd_cmd(0,    0,1,1,1,0); // NOP
	sd_cmd(0,    0,1,0,1,0); // リード
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,0x408,1,0,1,0)); // リード・プリチャージ
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("%08x ",sd_cmd(0,    0,1,1,1,0)); // NOP
	printf("\n");
	SD_CKE <= "0";

	for(int i=0;i<1000;i++)
	{
		P84_BUZZ <= i & 1;
	}

	return 0;
}

これで、MITOUJTAGは、VisualStudioだろうが、C#だろうが、複雑なネットワークが絡んでくるシステムだろうが、ファンクションテスタだろうが何からでもつなぐことができるようになるわけです。この追加機能は今夜あたりにはリリースしたいと思います。

| | コメント (0)

2013.04.07

特殊電子回路ではアルバイトを募集します

春です!

新入学!進級!おめでとうございます。

この春、新しく大学生や大学院生になられた方、おめでとうございます。特殊電子回路ではアルバイトさんを募集します。

● 採用情報はこちら http://www.tokudenkairo.co.jp/jobs.html

募集する職種は2つで、

① Webサイトの作成スタッフ ・・1名
② 製品の検査・製造スタッフ ・・1名

です。

Webサイトの作成というのは、今の特電のWebサイトを全面的にリニューアルするお仕事です。私はWebサイトの作成のそういうデザインセンスがないので、今の特電のWebサイトはひどいものです。そこで、皆様のもっているCSSやJavaScriptやFlashや、そういったテクニックを使って綺麗でわかりやすく、センス良いサイトに甦らせてください!

製品の検査・製造スタッフというのは、特電の各種ボード製品の最終工程を行ってくれるスタッフのことです。特電のボードは全品検査を行っているのですが、今は、なひたふが1つ1つ手作業で行っているため、ボードの出荷検査でとても多くの時間をとられてしまいます。

ボードの実装(部品をはんだ付けすること)は、専門の実装業者さんに任せていますが、製品の特性や波形を測ったり、電圧測ったり、パソコンとつないで動作チェックするといった作業は、自社内で行っています。そういう作業を手伝ってくれる方を募集します。

なお、②の検査スタッフは、大学生や大学院生の若いパワーを求めています!

大学生や大学院生の本業は学業ですから、基本的に学校の空いた時間に来ていただければ結構です。週2で数時間でOKということです。

実は、私は大学1年生~3年生のときに、秋葉原のある部品屋さんやパソコンショップでバイトしていたのですが、学校に真面目に行くとバイトをしている余裕なんてありませんでした。そういう事情はよくわかりますので、無理をしない範囲で働いてくれる方を募集します。(逆に、大学生・大学院生なのに毎日来たいという方はご遠慮ください)

もし、設計や開発(CADを使って基板を設計したり、FPGAを開発したりする仕事)を希望される方も、まずはこの検査スタッフとしてご応募ください。

あと、技術士一次試験に受かったので技術士補の登録をしたいという方も大歓迎です。そういう方には働いてもらいながら、みっちり教えます。といっても電気電子部門のみですが・・

勤務場所は、東京都千代田区神田佐久間河岸84番地。秋葉原駅から徒歩5分です。

いずれも自社内での業務となります。(派遣じゃありません)

Tokuden_new_office

大学1年生になったのでエンジニアっぽいアルバイトがしたい、3年生になったので少し時間ができた、もっと電気や組み込みのことを勉強したいなど、どんな動機でも構いません。皆様の若いパワーをお待ちしております。

● 採用情報はこちら http://www.tokudenkairo.co.jp/jobs.html

| | コメント (0)

2013.04.02

PCI ExpressのDMAを高速化したい

PCI ExpressのDMAを高速化したいと思って実験を重ねてきました。

EXPARTAN-6TでスキャッタギャザーDMAを使って、FPGA→PC方向の転送をしてみました。

下の図の緑色の濃いひと固まりが128バイトなので、転送開始の時点では、256バイトの送信に1.216usかかっているので、210MB/secで転送できていることがわかります。

Dma210mb

といっても、これは実際にバスに送信される速度ではなく、FPGA内のBlockRAMに蓄えられているだけです。実際にはルートコンプレックス(PCの中のチップセット。NorthBridge)がWAITをかけてくるので、次第に速度は落ちます。

64kB転送した時点で、256バイトのデータを送るのに1.440u秒かかるようになりました。よって、速度は178MB/secに下がってしまいました。

Dma178mb

このような速度の低下がなぜ生じるのか、なぜ、RootComplexはブレーキをかけてくるのか、ということをもう3年くらい悩んできました。

「DMAでPCのメインメモリに直接送りこんでも、Windowsのカーネル(HAL)がキャッシュにライトバックするから、その待ち時間がかかる」という仮説のもとに、いろいろ実験を重ねてきました。

その検証方法として、スキャッタギャザーをさらにバラバラにして32バイトごとに次のページに飛ぶようにしたり、PCI ExpressのパケットのRelaxOrderingやNoSnoopビットをONにしたり、そんなことをいろいろ重ねてきました。

また、ドライバの中でも、KeFlushBuffersをコメントアウトしてみたり、いろいろやってきました。

でも、どうやってもDMAの後半で速度が落ちることを回避できませんでした。だから、やっぱりキャッシュじゃないんじゃないか・・と思い始めてきたのです。

で、ようやくたどり着いたのが、この文章。

「物理アドレス拡張 - PAE メモリと Windows」
http://msdn.microsoft.com/ja-jp/library/windows/hardware/gg487503.aspx

つまり、ある条件のもとでは、HALの中でダブルバッファをしてしまうんだそうです。OSがメモリ空間を拡張している場合、PCI(Express)が32bitのメモリ空間しか指定してこなければ、PCIの中からメインメモリの全域をターゲットにはDMAできません。当然といえば当然ですよね。

本来ならば、物理アドレスは、Dual Address Cycle (DAC) コマンドといって、上下32bitの2回にわけて指定するようになっています。でも、ハードウェア側がそれをサポートしていない、つまり純然たる32bitアドレスで出来ている場合、HALが先頭4GBの適当なアドレスをハードウェアに教えて、ハードウェアにそのアドレスにDMAさせて、その内容をHALが本来のメモリの中にコピーする。そういうことが行われてしまうようです。

上のページには、次のような表があります。

バス アダプタ 結果
DAC DAC 最も高いパフォーマンスと安定性。
DAC DAC 以外 ダブル バッファリングが必要。 1 2
DAC 以外 DAC PCI 標準に準拠していないため、メモリ破損が生じる可能性。Windows は特定の回避操作を実行。3
DAC 以外 DAC 以外 ダブル バッファリングが必要。4

このダブルバッファが起こる条件とは、DMAアダプタがDACをサポートしていない場合に生じます。バスが非DACで、アダプタが非DACの場合でも起こります。

DMAアダプタを作る際にDma64BitAddresses フラグをTRUEにしたとしても、バスが64bitアドレスをサポートしていないと、強制的にFALSEにされてしまうそうです。

まぁ、よくわかりませんが、PCI Expressデバイスが64bitのアドレスを指定できなければ、アダプタは強制的に非DACになってしまって、ダブルバッファが使われてしまうと考えられます。したがって、FPGAがPCI Expressのトランザクションを発行する際に、64bitアドレスを指定できるようにすればいいのだと思います。

| | コメント (0)

« 2013年3月 | トップページ | 2013年5月 »