「LatticeMico8 v3.15チュートリアル」の編集履歴(バックアップ)一覧はこちら

LatticeMico8 v3.15チュートリアル」(2012/03/05 (月) 23:54:15) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

*LatticeMico8 v3.15チュートリアル **LatticeMico8とは [[LatticeMico8>http://www.latticesemi.co.jp/products/intellectualproperty/ipcores/mico8.cfm]]は[[Lattice Semiconductior>http://www.latticesemi.co.jp/]]社(以下Lattice)が公開している8bitソフトコアCPUです。オープンソースなのでLattice以外のFPGAでも使うこともできます。 同じようなFPGAメーカーが公開している8bitCPUにXilinxのPicoBlazeがありますが、あちらはアセンブラのみしか使えなませんが LatticeMico8は開発ツールとしてGCCが提供されてるのでC言語が使えるのが強みです。 Latticeが公開している32bitソフトCPUコアにLatticeMico32がありますが、こちらは最小構成でも2000LUT以上リソースを消費します。 LatticeMico8の場合は250LUT程度のリソース消費量で済みますので8bit CPUでも十分な処理の場合はMico8の方が良いでしょう。 最新のバージョンは3.3ですが3.2以降は開発環境がLatticeMico32と同じMicoSystemBuilderに統合され Eclipleベースのグラフィカルな環境で開発できますが、CPUアーキテクチャがMachXO2に最適化されてしまったのでそれ以外のデバイスでは使えません。 ここではLatticeXP2に組み込むことを目標に解説しますのでMicoSystemBuilderに統合される前の最後のバージョンであるバージョン3.15の解説をします。 **このチュートリアルの目標 Diamond 1.4の環境でCQ-FRK-LXP2ボード上のLatticeXP2にLatticeMico8を組み込むことが目標です。 LatticeMico8のアーキテクチャの解説や詳しいツールの説明とかはすっ飛ばしてまくってますので、詳しいことはLatticeで公開されてるマニュアルを参照お願いします。 とりあえず開発環境をインストール。C言語のソースコードをコンパイル。CPUの出力信号をVeritakで確認する所まで解説します。 **開発環境のインストール まず[[LatticeMico8 Archive>http://www.latticesemi.com/products/intellectualproperty/ipcores/mico8/mico8archive.cfm]]←のリンク先のページに移動します。 そこのリンク先からSDKとCPU本体のVerilogソースファイルをダウンロードします。 「LatticeMico8 Core Source Code Revision 3.15 Verilog Only」 ← CPU本体のVerilogソースファイルです 「NEW - LatticeMico8 Development Tools Installer for Windows - LatticeMico8 Core Revision 3.15」 ← SDKのインストーラです 上記のサイト内のリンクから2つのファイルをダウンロードしたら、インストーラを起動して適当なフォルダにインストールします。 この解説では「c:\lm8」というフォルダにインストールしたことにしておきます。 インストールする時にチェックボックスが出るのでCygwinをインストールするようにチェックを入れましょう。 **テストコードのコンパイルとメモリファイルの作成 テストに使うプログラムのCソースコードを書きます。 #highlight(c){{ // test.c int main(){ while(1){ __builtin_export(0x00,0); __builtin_export(0xff,0); } } }} 上記のプログラムでやってることは__builtin_export関数を使ってポート"ext_addr"に0を出力、"ext_dout"を0x00,0xff 交互に切り替えるだけです。 次にソースコードをコンパイルします。 LatticeMico8のツールのユーザーガイドにはmakeを使った方法が紹介されてますが、Makefileの書き方がわからないのと、 コマンドプロンプト起動するのは面倒くさいので、ソースコードのフォルダに下記の.batファイルを作ってそれでコンパイルします。 #highlight(txt){ :: make.bat del test.elf prom_init.mem scratchpad_init.mem lm8-elf-gcc -Wall -Os -o test.elf test.c perl c:\lm8\scripts\lm8-deployer.pl c:\lm8\gtools\bin test.elf pause } このバッチファイルを実行して"test.elf"、"prom_init.mem"、"scratchpad_init.mem"という3つのファイルが生成されたらコンパイル成功です。 **シミュレーションの下準備 シミュレーションに使うテストベンチを示します #highlight(txt){{ // tb_test.v `timescale 10ns/10ps module t; //////////////////////////////////////////////////// //Parameters parameter sim_time = 500; //////////////////////////////////////////////////// //Registers reg Clock = 1'b0; reg Reset = 1'b0; //////////////////////////////////////////////////// //Net wire [7:0] ext_addr,ext_io_din,ext_dout,ext_mem_din; wire [4:0] addr_sp = ext_addr[4:0]; assign ext_io_din = 8'b0; //////////////////////////////////////////////////// //Instansiation isp8_core #( .FAMILY_NAME("XP2"), .PROM_FILE("prom_init.mem"), .PORT_AW(8), .EXT_AW(8), .PROM_AW(9), .PROM_AD(512), .REGISTERS_16(0), .PGM_STACK_AW(4), .PGM_STACK_AD(16)) mico8( //input .clk(Clock), .rst_n(~Reset), .ext_mem_din(ext_mem_din), //w:8 .ext_mem_ready(1'b1), .ext_io_din(ext_io_din), //w:8 .intr(1'b0), //output .ext_addr(ext_addr), //w:EXT_AW .ext_addr_cyc(ext_addr_cyc), .ext_dout(ext_dout), //w:8 .ext_mem_wr(ext_mem_wr), .ext_mem_rd(ext_mem_rd), .ext_io_wr(ext_io_wr), .ext_io_rd(ext_io_rd), .intr_ack(intr_ack) ); pmi_distributed_spram #( .pmi_addr_depth(32), .pmi_addr_width(5), .pmi_data_width(8), .pmi_regmode("noreg"), .pmi_init_file("none"), .pmi_init_file_format("scratchpad_init.mem"), .pmi_family("XP2") ) scratch_pad( .Address(addr_sp), .Data (ext_dout), .Clock (Clock), .ClockEn(1'b1), .WE (ext_mem_wr), .Reset (Reset), .Q (ext_mem_din) ); initial begin #0.5 Reset = 1'b1; #0.5 Reset = 1'b0; fork forever #0.5 Clock = ~Clock; do; join end task do; begin #sim_time; $finish; end endtask endmodule }} Veritakのプロジェクトファイルの作成 #image(vtak_win.png) LatticeMico8_v3_15_Verilog.zipを解凍した後にできる下記のフォルダから上の画像に表示されているファイルを抜き出しておきましょう。 >LatticeMico8_v3_15_Verilog\source\ >LatticeMico8_v3_15_Verilog\models\pmi\ 沢山ファイルが入ってますが実際使うのは上の画像で表示されてるファイルだけなので、 分けておくと後々論理合成するときプロジェクトにファイルを追加する際に余計な手間が省けます。 抜き出したファイルをプロジェクトに追加したら、PROMのメモリファイルを作成したフォルダをインクルードディレクトリに指定しておきましょう、 またはプロジェクトファイルと同じフォルダにメモリファイルをコピーしてしまってもOKです。 **シミュレーション実行 #image(Wave.png) 上記のようにext_doutがext_addr_cycがHIになるたびffと00の変化を繰り返していれば成功です。 **論理合成用のCソースコードの作成 CQ-FRK-LXP2上のLEDをチカチカさせるためのソースコードを作ります。いわゆるLチカです。 LatticeMico8がFPGA上で動作していることが確認できれば何でもいいのですが、やはりこれが一番簡単そうです。 論理合成用のCソースコードを示します。 #highlight(c){{ // syn_test.c int main(){ unsigned char dout = 0; unsigned char i; for(;;){ for(i=0;i<0xffff;i++){ // wait asm("nop"); } __builtin_export(dout,0); dout = ~dout; } } }} 上記プログラムでやってることはfor文で時間稼ぎして、ext_doutをffと00を交互に繰り返すだけです。 要するにさっきのテストベンチでやったことをゆっくりやっているだけです。 for文の中にインラインアセンブラでnop命令を入れたのはGCCで最適化されてしまうのを避けるためです。 ファイルを作成したら先ほどののmake.batの記述を"test"の部分を"syn_test"変えてソースをコンパイルします。 ソースをコンパイルしたら論理合成用のトップモジュールファイルを作成します。 #highlight(txt){ // top.v module top( input Clock, output reg LEDOUT ); wire Reset = 1'b0; wire [7:0] ext_addr,ext_io_din,ext_dout,ext_mem_din; wire [4:0] addr_sp = ext_addr[4:0]; assign ext_io_din = 8'b0; //////////////////////////////////////////////////// //Instansiation isp8_core #( .FAMILY_NAME("XP2"), .PROM_FILE("prom_init.mem"), .PORT_AW(8), .EXT_AW(8), .PROM_AW(9), .PROM_AD(512), .REGISTERS_16(0), .PGM_STACK_AW(4), .PGM_STACK_AD(16)) mico8( //input .clk(Clock), .rst_n(~Reset), .ext_mem_din(ext_mem_din), //w:8 .ext_mem_ready(1'b1), .ext_io_din(ext_io_din), //w:8 .intr(1'b0), //output .ext_addr(ext_addr), //w:EXT_AW .ext_addr_cyc(ext_addr_cyc), .ext_dout(ext_dout), //w:8 .ext_mem_wr(ext_mem_wr), .ext_mem_rd(ext_mem_rd), .ext_io_wr(ext_io_wr), .ext_io_rd(ext_io_rd), .intr_ack(intr_ack) ); always@(posedge Clock or posedge Reset) begin if(Reset) begin LEDOUT <= 1'b0; end else begin if(ext_addr_cyc) LEDOUT <= ext_dout[0]; end end pmi_distributed_spram #( .pmi_addr_depth(32), .pmi_addr_width(5), .pmi_data_width(8), .pmi_regmode("noreg"), .pmi_init_file("none"), .pmi_init_file_format("scratchpad_init.mem"), .pmi_family("XP2") ) scratch_pad( .Address(addr_sp), .Data (ext_dout), .Clock (Clock), .ClockEn(1'b1), .WE (ext_mem_wr), .Reset (Reset), .Q (ext_mem_din) ); endmodule } ext_addr_cycがHIの時、出力ポートレジスタLEDOUTにext_dout[0]を取り込むようにしています。 **Diamondプロジェクトの作成 トップモジュールファイルを作成したら、Diamondを立ち上げてLFXP2-5E-5TN144C向けのプロジェクト新規作成します。 ここでは「LM8TEST」という名前で作成します。 次にFile ListのInput Filesに先ほどのトップモジュールファイルとシミュレーションで使ったLatticeMico8本体ファイル一式、 プリミティブモジュールをドラッグ&ドロップで追加します。 #image(filelist.png) ファイルを追加したら、上のメニューの Project -> Set Top Level Unit で Set Top Level Unitの項目に「top」と入力して module topをトップレベルユニットを設定します。 その後、プロジェクトファイル本体があるフォルダにプログラムファイルをコンパイル後にできた"prom_init.mem"と"scratchpad_init.mem"をコピーしておきます。 File ListのタブをProcessに切り替えてMap Designをクリックして、論理合成を行います。 論理合成が終了したらSpread Sheet Viewを開いてピンアサインと制約を追加します。 #image(spread.png) CQ-FRK-LXP2のDL3を点灯させますので LEDOUTに74、Clockに65を割り当てます。 出力レベルはLVCMOS33でPULLMODEはNONEに設定します。クロックピンに制約の追加も忘れずに。 FPGAに書き込んだ後目視でLEDがチカチカしていることが確認できたら成功です。 クロック速度10MHzぐらいを想定していますがそれ以上の場合は分周器CLKDIVBなどを使って下げると良いでしょう。 2012/01/18 update

表示オプション

横に並べて表示:
変化行の前後のみ表示:
目安箱バナー