カスタム設計の MicroBlaze
追加 2011.3.4 プログラムメモリの初期化、defparam 作成ツール (β版 v0.13)追加 2011.6.20
最近のISEのソフト開発環境、SDK 追加 2011.3.24
カスタム設計の MicroBlaze、 risc2s.ngc を含むソース一式。XC3S200 で動作します追加 2011.3.26
カスタム設計の MicroBlaze、 XC6SLX45T で動作します 追加 2011.8.20 プロジェクトファイル一式追加。2011.8.30
カスタム設計の MicroBlaze、 XC4VFX12 で動作します 追加 2011.8.21 プロジェクトファイル一式追加。2011.8.29
カスタム設計の MicroBlaze、 XC6SLX45 で動作させ、DDR2メモリチェックに使った例 追加 2011.10.24 プロジェクトファイル一式追加。2011.10.24
カスタム設計の MicroBlaze、 XC6SLX45T で動作させ、DDR3メモリチェックに使った例 追加 2011.11.9 プロジェクトファイル一式追加。2011.11.9
プログラムはブロックメモリのみで可能。外部メモリではプログラムを走らせることができません。I/O、データメモリのみ使えます。2012.1.5

なぜソフトコアのCPUを組み込むのか

FPGAとマイコンを組み合わせてボードを作っていると、FPGAの回路のチェックや動作中の状態を把握するのに、マイコンから内部のレジスタやメモリを読み出すことがよくあります。また、特定のフリップフロップを、マイコンからセット、リセットして、回路の振る舞いを確認することもしばしばです。また、外部にマイコンを装備するほどではないとか、基板の実装面積が足りないとか、ニーズはさまざまですが、FPGA内部にCPUがあると、開発工数が減ることも確かです。その為に、FPGAメーカーもそれなりのソフトコアのCPUを提供してきました。当方は、XilinxのMicroBlazeや、ハードコアの内臓PowerPCを使ってきました。価格性能比では、マイコン単体を外部に装備するほうが勝りますが、簡単だがハードで作ると時間がかかる場合、CPUを内臓して解決するという設計スタイルが定着してきました。
さて、ソフトコアのCPUを内臓する場合、第一番に要求される仕様は、

ソフトの開発は、C言語などが使えること

であろうかと思います。さらに言うなら、そのコンパイラが無償で使えること ではないでしょうか。

ソフトコアのCPUは、8ビットや簡単な16ビットなら作ってもたいした回路にはなりませんから、雑誌やWeb上でたくさん見つけられます。ところが、プログラミングは、たいていアセンブラなので、ほとんど使う気になりません。
そこで、コンパイラが簡単に使えるCPUとなると、68k系、80x86、PowerPC、ARM、SH、H8など、ポピュラーなCPUってことになります。特殊なものとして、PIC、8051、などもコンパイラが用意されていますが、こちらはほとんどC言語とは呼べないしろものです。ここで、Z80という選択はかなり魅力がありますが、回路が思ったより規模が大きくなり、そのくせ64kBの壁は、昨今の大量のメモリを扱う用途には力不足です。32ビットを直接扱えるCPUで、しかもRISCタイプということで、MicroBlaze がターゲットになりました。

EDK10の資料から、MicroBlazeの命令セットを調査
MicroBlazeの命令セットをを見ると、PowerPCと似ていることが解りますが、PowerPCと比較するとはるかに命令数が少なく、バイナリコードを見ると、空きエリアが多いのが目立ちます。主な特徴を列挙すると、
  1. 汎用レジスタは32個あるが、ハードウエア的に、またはソフトウエアであらかじめ機能が決まっているレジスタがある。
    1. レジスタ、r0 は、読み出すとき、常に0
    2. レジスタ、r15 は、サブルーチンからのリターンアドレスに使われる。これはハードウエアではなくコンパイラによる。
    3. レジスタ、r14 は、割り込み発生時に、プログラムカウンタ(PC)の退避として、ハードウエア的に使われる。
    4. レジスタ、r16、r17は、ブレークや、例外処理のときのPCの値を記憶する。
    5. レジスタ、r1 は、ソフト(コンパイラ)で指定されたスタックポインタとなる。
  2. 命令は、3オペランドのものがある。つまり、レジスタr0、r1、r2などが、3個同時にアクセスされる。
  3. サブルーチンコールでは、ハード的にスタックは使われず、戻り番地格納やスタックフレームはソフトで操作する。
  4. 同じく、サブルーチンからの戻りは、戻り番地が格納されたレジスタからPCに読み出される。
  5. いわゆる、<MOV>命令はなく、たとえば、r4をr5にコピーするとき、r5=r4+r0となり、加算命令で実現している。
  6. PowerPCでの32ビット即値は、16ビットを2回に分けて実現していたが、MicroBlazeでは、32ビット命令を2個使って、不可分の命令として実行し、ちょうど64ビット命令のように振舞う。PowerPCでは、1回の16ビット即値は、MSBの16ビットにロードされ、1回だけで使えるようになっているが、MicroBlazeではそれができない。

掛け算や、割り算、バレルシフタなどは実装せず、基本命令をピックアップして黄色くハイライトさせた命令表が、こちらです。inst_mb_ref_guide.pdf元の資料は、mb_ref_guide.pdf というEDK10のMicroBlazeのドキュメントです。黄色くハイライトしている命令が、実装した基本命令です。MicroBlaze用のCygwinコンパイラが生成するコードを抜き出しています。中には、アセンブラでしか(?)使えない命令も実装していますが、その命令を完全に実行できるわけではありません。たとえば、msr (マシンステータスレジスタ)に実装したフラグは、キャリーと、割り込み許可フラグだけです。ゼロフラグとか、サイン(負)フラグとかは、 MicroBlaze にはありませんので、フラグ類は少なくて済みました。無論、Cのソースに、浮動少数点などは使えませんし、関連する printf() 関数も使えません。デバッグ目的では printf() が無いと不便なので、整数と文字列さえ扱えればよいので、簡単なものを作って対応します。

とにかくGCCが吐き出したコードで動作するものを目標とする

パフォーマンスはその次ということで、パイプラインは2段(厳密に、2段か否かは疑問)となり、とりあえず1命令1クロックのRISC風のものができ、回路のデバッグ用として、2007年ごろから、いろいろと使ってきて、ほぼ問題がないので、近々に公開します。(ソースはとても公開できるような記述でないので、Xilinx のネットリスト、risc2s.ngc となります)
カスタム設計の MicroBlaze、 risc2s.ngc を含むソース一式。XC3S200 で動作します追加 2011.3.26

スペックは以下の通り。
  1. ほとんどの命令で、1命令1クロック。ブランチ命令、32ビット即値命令などは2クロック。
  2. メモリは、命令、データが共通。シングルポート接続。ハーバード形式は最小構成でメモリを多く使うのでやめる。
  3. SPARTAN3で、最高50MHz、Virtex4で66MHzぐらい。無論、実装回路が70%に増えるとスピードは、40MHz、50MHzが無難。SPARTAN6では、ゲート使用率10%で、66MHzを確認。( SPARTAN6 Evaluation kit SP605 XC6SLX45T )
  4. 3オぺランドのレジスタは、RAM16X1D を並べて2系統実装して、3アドレス対応。
  5. 乗算、除算、バレルシフトなどの命令、MMU、キャッシュ機能などなし。割り込みは可能。
  6. CPUコア部分には、UART、32ビットフリーカウンタ1個を内臓。
  7. GCCでコンパイルしたコードを実行できる。メモリや、周辺レジスタの内容の書き換え、読み出しが行える簡単なモニタを用意。
  8. スライス数は、約1350。これは、SPARTAN3の、XC3S200で75%ほど使う。(SPARTAN3 Starter kit で動作)
  9. メインメモリは、ブロックRAM ( RAMB16_S9 ) を最低4個で動作するが、メモリの初期化データ作成ツールでは、4個、8個、16個、32個を使うものを用意。
  10. 外部バスのスピードは、最低4クロック必要だが、SDRAMや、フラッシュメモリを接続してプログラムを動作させることができる。←訂正 2012.1.5
  11. 外部メモリでは、プログラムを走らせることはできません。I/O、データメモリのみ使えます
  12. ALTERAのCycloneでも動作を確認。快調に動く。XILINXよりクロック数を上げられるのではないか?。LE数は、約4200個 LE数が多いのは、Xilinxのように、レジスタを分散メモリで作れなかった為と思われる。reg 宣言で、1024個のフリップフロップと、デコーダ、マルチプレクサで、CPUコアの40%を占める!!

簡単なアセンブラプログラムでシミュレーションしてみる
最近、ISEでは、ModelSim(Xilinx Edition)が使えなくなり、代わりに ISE同梱のISimとなっています。ISEとの統合ができていて、ALTERAのQuartus2と連動する、ModelSimのような、いろいろな設定は不要です。

簡単なプログラムは、以下のような、0x100番地に0x12345678を書いて、それを読み出し、7を加算して0x100番地に書き、そのあと、0x104番地と0x100番地を読むものです。使ってる命令は4種類しかなく、しかもその中の brid はダイナミックストップの為のもので、シミュレーションの主な目的ではありません。アセンブラは、Cygwin の mb-as.exe を使って、リストを出力しています。ソースは、 cmbasm.s です。URLの関係上、テキストファイル名としています。
$ mb-as -ahls=cmbasm.lst cmbasm.s ( enter ) で作ります
リストファイル、cmbasm.lst
Xilinx MicroBlaze GAS Version 2.9.4 cmbasm.s 			page 1


   1              	/*
   2              		Custom Micro Blaze test asm
   3              	*/
   4              		.globl _start
   5              	        .section .text
   6              		.align 2
   7              	_start:
   8 0000 B0001234 	        addik	r3,r0,0x12345678	# 32ビット即値を r3 に設定
   8      30605678 
   9 0008 30800100 		addik	r4,r0,0x100		# アドレス0x100を、 r4 に設定
  10 000c F8640000 		swi	r3,r4,0			# r4 のアドレスに、r3 を書く
  11 0010 E8A40000 		lwi	r5,r4,0			# r4 のアドレスから32ビットデータを r5 に読む
  12 0014 30A50007 		addik	r5,r5,7			# r5 に 7 を加算する 0x1234567f になる
  13 0018 F8A40000 		swi	r5,r4,0			# r5 を、r4 のアドレスに書く
  14 001c E8C40004 		lwi	r6,r4,4			# r4 + 4 のアドレスから32ビットを r6 に読む。0x0
  15 0020 E8C40000 		lwi	r6,r4,0			# r4 のアドレスから32ビットを r6 に読む 0x1234567f
  16 0024 30C60001 	loop:	addik	r6,r6,1			# r6 に1を加算
  17 0028 B810FFFC 		brid	loop			# 繰り返し
  18 002c 30E70001 		addik	r7,r7,1			# r7 に1を加算
  19              		.func
  20              		.end
  21              	
Xilinx MicroBlaze GAS Version 2.9.4 cmbasm.s 			page 2


DEFINED SYMBOLS
            cmbasm.s:7      .text:00000000 _start
            cmbasm.s:16     .text:00000024 loop

NO UNDEFINED SYMBOLS
このリストから、同じ命令でも、最初の addik のようにコードの長いものがあり、32ビット即値のための、IMM 命令が自動的に追加されています。アセンブラレベルでは記述が同じでも、出来上がったバイナリコードでは、IMM 命令が追加されたことになっています。ここで、よく観察すると、IMM 命令は、ブランチ命令、brid と、よく似ていて、MSB4ビットが同じ、0xB となっています。内部の動作でも2命令を不可分に実行するシーケンスとなります。ブランチ命令 brid では、loop に戻るけれども、その次の命令、addik r7,r7,1 も実行してしまいます。こういうのを、遅延分岐と呼ぶらしいですが、ルネサスのSHシリーズマイコンでも同じですね。内部のパイプラインに取り込まれた命令を捨てずに実行して、効率をあげる手法です。

この簡単な命令を、ISim でシミュレーションしたスクリーンショットが、以下の2画像です。文字が小さいですが、Name 欄の maddr がメモリのアドレス、mdb が、データバスの状態です。extwd が、MicroBlazeがメモリにライトするデータを示し、extwe がHighでメモリにライトすることを示しています。ifen は、その時点の maddr が示すアドレスに対する、インストラクションフェッチが有効であることを示しています。有効な命令はその次のクロックでの、mdb の内容が、フェッチする命令コードを示しています。




外部メモリや、I/Oのアクセスタイミング

内部のブロックRAM( mainmem.v )でプログラム実行やデータアクセスをする場合は、アクセスタイムは1クロックですが、外部では、アドレスデコードを含めて通常5クロックかかります。その場合の典型的なタイミングです。

プログラムメモリの初期化、defparam の256ビット初期化データの怪

EDKを使っている限り、プログラムメモリの初期化は、出来上がった .bit ファイルを、data2mem コマンドでブロックRAMのデータ部分だけ変更しているので、ソフトが変更になっても、配置配線を始めからやる必要がありません。しかし、この data2mem コマンドを使うには、あらかじめブロックRAMの位置情報(X8Y12などと指定する)を、UCFで指定しておくのと、BMM ファイルを用意しておかないといけません。この方法は、また別の機会にやってみようと思います。回路規模が大きくなると、ちょっとしたソフトの変更でも配置配線に時間がかかって、とても高率が悪いからです。
ここでは、とりあえず、defparam ......... などと書く、verilog の文法に従った方法で、プログラムメモリの初期化を行います。

とは言うものの、この defparam で初期化するデータは256ビット単位となっており、しかも、256ビットのバス幅のメモリに対して初期化データを設定するような構造のようです。256ビットの値は、アドレス上位が左になり、0番地は一番右の32ビット部分になっているからです。通常、インテルとか、モトローラのHEXデータフォーマットのデータの並び順では、左の方がアドレスの小さい側なので、逆に並んでいます。

例として、XilinxのブロックRAMプリミティブである、RAMB16_S36 を以下のように使ったとし、メモリの0番地に32ビットデータ、0x12345678を、その次に、0x9ABCDEF0を初期化したいとすると、

module mainmem( addr,wdata,rdata,clk,we
);
input	[15:2] addr;
input	[31:0] wdata;
output	[31:0] rdata;
input	clk;
input	[3:0] we;
wire	[3:0] dop;
RAMB16_S36 ram0(.DO(rdata[31:0]), .DOP(dop[3:0]), .ADDR(addr[10:2]), .CLK(clk), 
	.DI(wdata[31:0]), .DIP(4'h0),. EN(1'b1), .SSR(1'b0), .WE(we[3:0] != 0));

 defparam ram0.INIT_00 = 256'h0000000000000000000000000000000000000000000000009ABCDEF012345678;

endmodule
という記述になります。0番地が0x12345678ですが、データのLSBがそのまま、defparam の256ビットデータの右端になっていて、いわゆる、インテルプロセッサのメモリへのバイトオーダーである、little endian の並びであることが判ります。RAMB16_S1_S36 を使ったとして、1ビット側から順に読み出すと、0,0,0,1となります。ともあれ、これは Xilinxの特性 ではなく、verilog の記述規則なのでそのまま使うしかありません。
上記に示したテストプログラムを、RAMB16_S36 に設定するには、
 defparam ram0.INIT_00 = 256'hE8C40004F8A4000030A50007E8A40000F86400003080010030605678B0001234;
 defparam ram0.INIT_01 = 256'h0000000000000000000000000000000030E70001B810FFFC30C60001E8C40000;

となります。初期化データは、アセンブラのリストから、エディタを使ってコピー&ペーストで比較的簡単に作れます。

短いテストプログラムとか、ソフトで扱うデータを、32ビットに限定するなら、バス幅32ビットのブロックRAMをそのまま使えますが、8ビットや16ビットの書き換えではそのまま対応できないので、(外部メモリへのアクセスのように、バイト単位に書き換える機能があれば、ブロックRAMを32ビット幅1個でもメインメモリとして使えますが、1クロックでのアクセスでは不可能)最低4個の8ビット幅のメモリを並列に接続して、32ビットのメモリにします。
4個のメモリを使って、初期化すると、以下のようになります。ライト時のバイト指定は、we[3:0] と4本必要です。
module mainmem( addr,wdata,rdata,clk,we
);
input	[15:2] addr;
input	[31:0] wdata;
output	[31:0] rdata;
input	clk;
input	[3:0] we;
wire	[3:0] dop;
RAMB16_S9 ram0(.DO(rdata[31:24]), .DOP(dop[3]), .ADDR(addr[12:2]), .CLK(clk), .DI(wdata[31:24]),
	.DIP(1'b0),. EN(1'b1), .SSR(1'b0), .WE(we[3]));
RAMB16_S9 ram1(.DO(rdata[23:16]), .DOP(dop[2]), .ADDR(addr[12:2]), .CLK(clk), .DI(wdata[23:16]),
	.DIP(1'b0),. EN(1'b1), .SSR(1'b0), .WE(we[2]));
RAMB16_S9 ram2(.DO(rdata[15:8]), .DOP(dop[1]), .ADDR(addr[12:2]), .CLK(clk), .DI(wdata[15:8]),
	.DIP(1'b0),. EN(1'b1), .SSR(1'b0), .WE(we[1]));
RAMB16_S9 ram3(.DO(rdata[7:0]), .DOP(dop[0]), .ADDR(addr[12:2]), .CLK(clk), .DI(wdata[7:0]),
	.DIP(1'b0),. EN(1'b1), .SSR(1'b0), .WE(we[0]));

 defparam ram0.INIT_00=256'h000000000000000000000000000000000000000030B830E8E8F830E8F83030B0;
 defparam ram1.INIT_00=256'h0000000000000000000000000000000000000000E710C6C4C4A4A5A464806000;
 defparam ram2.INIT_00=256'h000000000000000000000000000000000000000000FF00000000000000015612;
 defparam ram3.INIT_00=256'h000000000000000000000000000000000000000001FC01000400070000007834;

endmodule

メモリ初期化 defparam は、32ビットの命令を、各メモリに1バイトづつ分割して、ram0 ---> ram3 のLSBから順に左に書いていきます。これを手作業でするには、短いプログラムでも大変な作業になってしまいます。動作確認のごく初期の段階では、このように手動変換でもいいですが、コンパイラで作ったヘキサのデータから、defparam への変換プログラムを作ることにしました。インテルヘキサからモトローラSレコードへの変換とか、バイナリにも相互に変換できるものは、フリーでいくつも見つけられますが、このような特殊なものは簡単には見つかりません。表計算ソフトでも可能なようですが、なにぶん表計算はあまり使ったことがないので、Visual Studio 2005 で作ることにしました。実は、Visual Studio 2005 は以前から入手していたのですが、こういう簡単なツールを作るのに、ずっと VC++6.0 を使っていたので、ほとんど使わないままでした。たしかMSDN会員付きで、10万円以上したと思います。C++のコンパイラですが、多くは C のまま、且つ、ウィンドウズ対応は、Win32 API を直接呼び出す古典的なものがほとんどです。半分以上は、コンソールプログラムで用が足ります。VC++なら、無償のエクスプレス版でも十分だと、3年ほど前に知って、えらく高い買い物をしたと思ったこともありますが、MSDNはそれなりに有用で、Windowsの最新OSを10台まで使え、且つ認証期限まで60日もあるので、自作パソコンを作るには重宝しました。

どうせ作るなら、defparam だけでなく、インテル、モトローラ、CSV、単純HEXのみ、バイナリ(txt などもそのままバイナリ扱い)などが読め、出力は、defparam .hex .mot .csv dump .mif( QuartusUで使うメモリ初期化データ ) .hex( QuartusU と、ModelSim で使えるメモリ初期化データ。インテル形式とは8ビット以外ではアドレス表記が異なる。ワードアドレスとなっている)、そしてバイナリデータを出力できるものにします。

defparam のデータにも変換できる、多機能な HEXutils のスクリーンショットです。

おもな機能は以下の通り。
  1. ソース対応は、モトローラS、インテルHEX、CSV、単純HEXの羅列、バイナリ(bin)、すべて(バイナリ扱い)
  2. 出力形式は、defparam、mif、CSV、モトローラS、インテルHEX、QuartusUHEX、バイナリ、メモリダンプ。
  3. defparam の場合は、Xilinx の BRAM を、バス幅1,2,4,8,16,32ビットを指定できます。ただし出来上がるメモリパックは32ビットのメモリのみ。
  4. 内部バッファーは16MB。これ以上のバイナリでの長さには未対応。読み込み時には、アドレス情報を0x00FFFFFFでマスク。
  5. インテルHEX、モトローラSの場合は、出力時に、アドレス移動が可能。
  6. defparam mif csv Quartus2hex bin などでは、出力時に元の先頭アドレスは、0番地とみなします。
  7. 読み込み時に、バッファーを、指定データ(バイトのみ)で満たす機能があります。またそれをしない選択もあるので、2個のファイルをマージすることができます。オーバーラップしても警告はでません。
  8. モトローラS、インテルHEX、CSV、mif などで、バイトオーダーを指定できます。つまり、エンディアン変換機能。だだし、16、32ビット単位のみ。

現在まだデバッグ中、機能追加中ですが、defparam など作成する 旧β版はこちら。v0.1  旧β版0.11はこちら。v0.11  旧β版はこちら。v0.12
新β版はこちら。v0.13
  解凍して hexutils.exe をダブルクリック。インストーラなどは無く、そのまま動作します。defparam 出力に関しては、RAMB16_S1,RAMB16_S2,RAMB16_S4,RAMB16_S9 を使う回路で、で約7KBのモニタソフトの実機動作確認をしています。
ヘキサファイルなどの相互変換ツールとしては、かなり高機能だと思います。( 特にFPGA用HEXファイル変換 )
いままで作った単機能のコマンドライン変換ツールを集大成しています。
主な使い方
  1. 主な仕様。最大ソースサイズ:32MB、最大内部データバッファー:16MB、最大出力サイズ:256MB。
  2. アドレス付きHEXデータは、内部に読むとき、アドレス値を、0x00FFFFFFでANDしています。
  3. 右上の選択コンボボックスで、ソースのファイルタイプを指定します。
  4. そのすぐ左が、ブラウザ。ブラウザでもファイルタイプを選択できますが、コンボボックスが優先します。
  5. ファイルが存在すれば、ファイル名の絶対パスが表示されます。
  6. 左上の、Read ボタンで、ファイルを読みます。ファイルタイプで指定した方法で、内部のバッファーに読み、最小アドレス、などに報告します。
  7. ブランクは、途中でアドレスが増加して、データ指定の無かった部分のバイト数を示します。fill で指定された値のままです。
  8. fill チェックボタンが有効だと、ファイルを読む前にバッファーを右の値で満たします。値は2桁のヘキサで指定します。
  9. fill チェックボタンが無効だと、バッファーをそのままで、別のファイルを読み足すことができます。
  10. Display ボタンで、ソースファイルを別ウインドウに表示します。ソースがバイナリ指定の場合は、表示しません。
  11. 開始 は、バッファーに読まれた先頭アドレスで、ここは変更することができます。
  12. 終了+1 は、バッファーに読まれた最終アドレス+1で、ここは変更可能です。
  13. 作成時 offset は、出力が、インテルHEX、モトローラSのときのみ有効で、アドレス情報を変更できます。
  14. Big endian は、QuartusU.mif, QuartusU hex, Excel ファイルなどに出力するときに有効で、バイトオーダーを変換します。
  15. 横個数は、Excel .CSVファイル, 0xHEX, HEX, などで有効で、1行のデータ個数を指定します。
  16. S1-S3 は、モトローラSレコードで出力すのときのみ有効で、アドレス幅を指定しますが、アドレス情報が大きい場合は、S2、S3になります。
  17. data size (byte) は、defparam の場合は、ブロックRAM1個のバス幅を指定し、32ビット幅メモリの初期化データにします。
  18. data size (byte) は、mif, QuartusU hex, .CSV, 0xHEX, HEX, の場合で、1個のデータのバス幅を指定します。8,16,32のみ有効です。
  19. 出力形式の コンボボックスは、出力のファイルタイプを指定し、その下のブラウザでファイル名を指定します。
  20. 変換は、内部に読まれたバッファーから、出力ファイルを作成します。表示で、確認でき、保存でファイルに書きます。

割り込み要求、割り込み応答のシミュレーション波形


この図は、割り込みタイマーで、Custom MicroBlaze に割り込み要求を出し、0x10番地にジャンプしている様子です。
  1. 信号名、intreq が、タイマーで発生させた、外部からの割り込み要求信号。Highへの変化で有効。
  2. 黄色の縦カーソルの位置で、信号名 intreqr が1になっていますが、これがCPU内部で割り込み要求の立ち上がりエッジを検出したフラグです。この信号は、Custom MicroBlaze の risc2s.ngc の出力ポートで参照できる、testout[4] ( intreqr ) です。
  3. intreqr の1クロック後の信号、intseq が、CPUが、割り込みシーケンスに移行したことを示します。このタイミングで、iff、ifen がLow(無効)になっていて、メモリには、次の実行アドレスが出されていて、命令も読み出されていても( 命令は、0x30C00008 addik r6,r0,8 )、捨ててしまうことを示しています。
  4. 次のクロックで、CPUのプログラムカウンタが0x10となって、maddr に0x10が出され、ifen が有効となり、命令フェッチステートに移っています。
  5. 次のクロックで、メモリの0x10番地の命令、0xB0000000が読み出されて、iff 有効で、命令を実行していることを示しています。
実機、Digilent Spartan-3 Starter kit での割り込みテスト
Digilentは、Xilinxの教育用評価基板のメーカーで、数年前に以下の基板を出していました。当時、15,000円ほどで、かなり安かったと思います。この基板を持っている人はかなりいるのではないかと思います。使っているICは、XC3S200FT256 で、裏に16ビット幅のSRAMを2個実装されていて、オリジナルのデモ回路では、VGAに文字を出し、操作は、 Pico Blaze でした。MicroBlaze を入れるには、ロジック数が足らなかったのだと思います。

この基板に、Custom MicroBlaze を入れて、簡単なアプリを動かしてみます。モニタだけなら8kバイトに収まりますが、いろいろ評価するため、12個あるBRAMの内、8個を使って、メインメモリを16kBとします。割り込みタイマーとか、SRAMインターフェイスを入れると、使用ロジック数は、87%にもなってしまいました。この使用率で、Custom MicroBlaze は、40MHzで動作します。容量の小さなFPGAなので、40MHzでも若干余裕があります(50Mでは、なんとなく動くが操作ができなかった)。これがXC3S1500−676ピンとかだと、87%も使うと、40MHzはだめだったと記憶しています。33MHzぐらいにしたようです。
この基板で動く、回路一式がこちらです。CPUは、risc2s.ngc です(´∀`;;) 解説はまだありません。
この中で、risc2s.ngc は、ISEのプロジェクトファイルがある、同じフォルダに移すか、以下のように、Translate Properties で risc2s.ngc の所在を指示しておきます。TOPのRTLは sktcmbdemo1t.v で、ここから、 Custom MicroBlaze 本体の risc2s.ngc 用ラッパー( risc2s.v ) と、mainmem.v を呼び出します。


基板左のRS232Cコネクタとパソコンを接続し、ターミナルソフトを115200ボーで開いておいてJTAGでコンフィグすると、以下のように起動プロンプトが出ます。

プロンプト、CMB-Bug> が出ている状態で、i1 <enter> とコマンドを与えると、左下のLEDに、カウントアップ表示が出ます。LEDの点灯内容は、FPGAのハードウエアによる表示ではなく、Custom MicroBlaze にインターバル割り込みを与えて、割り込み処理の中で変数をカウントアップして、LED表示ポートに出力した結果です。i0 <enter> で、カウントが停止します。

また、CMB-Bug>S <enter> とコマンドを与えると、エラトステネスの篩いを実行して、約3秒後に結果が出ます。

モニタでは、メモリのダンプ、変更、任意番地からの実行、メモリのコピー、メモリの比較、パソコンからモトローラSレコード形式のファイルを送って、メモリにロードする機能があります。操作は、SH2用モニタとほとんど同じです。


Xilinx Spartan-6 FPGA SP605 Evaluation kit での動作テスト、同じ risc2s.ngc, mainmem.v を使っています

SPARTAN6のEvaluation Kitは、パソコンのPCIeスロットに入れて、PCIe のテストができたり、1Gのイーサネットが使えたり、盛りだくさんな評価ボードですが、ユーザーに開放している汎用ピンが、写真の上の横長い黒いコネクタとなっており、このコネクタに集められています。これでは簡単には利用できません。せめてコネクタの相手側ぐらいおまけに付けてほしいところです。

このボードですが、12Vから各電源を作っていますが、ほとんどが電源モジュールになっており、変換効率が悪いらしく、かなり発熱して触れなくなります。同期整流タイプのステップダウンDCDCコンバーターなら、もっと効率がいいはずで、95%ほどになるはずです。この基板の電源設計はかなり手抜きですね。

写真の下、PCIeコネクタのすぐ右の緑LEDが、ユーザーLEDで、4個使えるので、割り込みでカウントした8ビットのカウンタの、上位4ビットを出力しています。

ISE13.1 でのプロジェクトファイル一式はこちらです。 sp605cmbiof1.lzh  ←アクセスできない場合は日をあらためてください。


準備中

Xilinx Virtex4 ML403 Evaluation Platformでの動作テスト、同じ risc2s.ngc, mainmem.v を使っています

Virtex4 の Evaluation Platform は、ハードマクロのPowerPCを内臓したFPGAの評価ボードです。付属するCFカードに評価プログラムが書かれており、PowerPCでLinuxが走っているようです。電源ONで、テストプログラムが走り、いくつかの動作テストが選択できます。
このボードを使って、カスタム設計の MicroBlaze を走らせてみました。回路は、XC3S200 Starter kit と同じ、risc2s.gnc と、mainmem.v です。無論、TOPのボード固有の回路や、 ucf はボードに合わせてあります。以下は、同じように、割り込みでカウンタを操作して、LEDで表示しています。(右下の緑LED)
ISE13.1 でのプロジェクトファイル一式はこちらです。 ml403cmbiof.lzh  ←アクセスできない場合は日をあらためてください。

準備中

ALTERA、Cyclone1 ( EP1C12Q240C8 ) で動作させたスクリーンショットです


MicroBlaze のコンパイラ

Xilinxの組み込み開発環境、EDKには、MicroBlazeと、PowerPCのクロスコンパイラが付属しています。どちらもGNUで作成されており、実体は、Cygwinですから、もし、Cygwinの環境がセットアップされているなら、EDKからコンパイラツールをフォルダごとコピーして、パスを通すと、Cygwin環境でソフトを開発することができます。EDKには、いわゆるWebパックがないので、無償評価版をインストールしても、期限が来ると使えなくなりますが、コンパイラツールは、そのままCygwin環境があれば使うことができます。最近のISEでは(ISE v13.1で確認)、WebPackをインストールすると、EDKフォルダも作成され、その中に gnu フォルダもあり、microblaze\nt フォルダ以下にそれらしいコンパイラツールがありますが、この nt フォルダ以下を Cygwin の、usr\local フォルダ以下にコピーして、パスを通しても、使えないようです。その代わり、SDKのみをインストールして、gnu フォルダ以下に展開される、microblaze\nt フォルダをコピーすると、使えるようです。またこのツールは、Cygwin 環境が無くても使えるものです。ただ、make.exe などを使うには、gnuwin\bin フォルダにパスを通す必要があるようです。

コンパイラツールの場所は、EDKの、EDK(フォルダ)¥gnu¥microblaze¥nt¥ 以下にあり(EDK10.1の場合)、nt をフォルダごとCygwin¥usr¥local¥ 以下にコピーして、Cygwinの起動時に、

PATH=/usr/local/nt/bin:$PATH

の1行でパスのセットアップをしておくとコンパイラツールを使えます。

Cygwin環境が無い場合は、WindowsのDOSプロンプトでも使うことができます。その場合は、EDKフォルダに、cygwin¥bin があるので、Cygwinフォルダごと、どこかのドライブのルートディレクトリ(ここでは G:¥ とする)にコピーします。そのあと、Cygwinフォルダに、usr フォルダを作成して、その下に、local フォルダを作り、そのフォルダ以下に、上記の nt フォルダをコピーします。このようにしておいて、DOSプロンプトを起動し、次のような1行のBATでパスを設定します。

set path=g:\cygwin\bin;g:\cygwin\usr\local\bin;%PATH% ( setmbpath.bat )

設定したあとのフォルダの、G:\cygwin\usr\local\bin を見ると以下のようになります。この例は、EDK10.1をコピーしたものです。



MicroBlaze のコンパイラをDOSプロンプトで操作してみる

Cygwinのクロスコンパイラを動作させる環境が整ったところで、以下のようなファイルを作成します。
  1. makefile コンパイラやアセンブラ、その他のユーティリティーを制御する、メイクファイル。
  2. cmbmon.c MicroBlaze用のモニタ。メモリダンプやメモリ変更などを行うプログラム。
  3. siocrt0.s フレームポインタや、スタックポインタを設定する、電源ON後に実行されるプログラム
  4. crtinit.s 変数初期設定や、クリアを行うサブルーチン。
  5. cmbmon.x リンカースクリプト。各セクションを指定する。
ここで、cmbmon.c 以外は、一度作成すると、あまり変更する必要がなく、また、かなり汎用的なものなので、以下にその例を出しておきます。
makefile の例


電源ON後のスタートアップ、siocrt0.s の例。このソースは、EDK8.2のサンプルは、crt0.s を元に変更して作成しています


変数領域クリア、設定の、crtinit.s の例


リンカースクリプト、cmbmon.x の例。ここで、_stack を0x100ほど確保するような記述がありますが、siocrt0.s で、0x3FF0に設定しているので無効になります。この結果、セクションの指定は何もしていないことになり、0番地から順番に割り付けられます。プログラムは0番地からスタートします。このスクリプトは、EDK10.1の elf32microblaze.xr を元に作成しています。



以下は、DOSプロンプトで、make ( enter ) を実行したときのスクリーンショットです。


XilinxのFPGAソフトマクロ、MicroBlaze を verilog で作成

準備中


準備するもの

  1. Windows 上でLinux 環境を作る。 Cygwin
  2. MicroBlaze のコンパイラソース Xilinx 常に最新。EDKを使わない場合どれでもいい。
  3. EDKのV8.2のソースはすでに公開を停止していますが、古い fullsrc.tar.gz はここに残しています。

Cygwin のダウンロード

Cygwin は、ダウンロードしながらインストールできますが、全部ダウンロードしてから、ディスク上のデータからインストールするほうが問題が発生しにくいので、まずダウンロードのみ先に行います。これは、Cygwin のダウンロードは、途中でパッケージを読み飛ばしてしまって、必要なファイルを全部ダウンロードできないことがあるからです。そして抜けたファイルがあっても、インストール中に警告が出ないことがあるので、インストールが終っても正常に動作しないことがあります。特にクロスコンパイラをビルドするときには、多くのパッケージソフトを使うので、file not found とかのメッセージが出て、途中でエラーで止まってしまうことがあります。無論、クロスコンパイラをビルドするには、 configure のオプション設定 を間違えてエラーで止まることもしばしばなので、エラーの原因がパッケージ不足によるものなのか、configure の設定不足や指示間違いなのか、エラーメッセージから判読するのは、慣れてこないと簡単にできません。

Cygwin のセットアップ

 Cygwin は、開発環境にするので、 図 Devel 選択 をクリックして Install に変え、次へをクリック。
Cygwin は、ダウンロード


MicroBlazeは、Xilinx, Inc.の商標または登録商標です。

FPGAのCPU関連

例1:シリコンデザインテクノロジー デザインウエーブマガジン2005年1月号掲載記事がある。C1601 CPU
例2:HDL Simulator Veritak verilogシミュレータ、VHDL --> verilog 変換ツールの販売


ホームに戻る



inserted by FC2 system