Sim's blog

電子工作はじめてみました

NIOSを使ってみました(2)

2009-11-05 22:49:19 | FPGA
NIOSを使ってみました(1)の続きになります。

NIOS IIのトリビアルな実装をしています。

(5) NIOS II eds(エンベデッド・デザイン・スイート)を起動してCのプログラムを作って、FPGAボードにダウンロード&実行する

いよいよ最後のステップです。

NIOS II edsを立ち上げると最初にworkspaceをどこにするかを聞いてきます。

Quartusのプロジェクトフォルダと一緒にするのがてっとりばやいです。一段階Softwareというフォルダを掘ってくれるので、ファイルが混ざったりすることもありません。

Fileメニュー → New → NIOS II Aplication and BSP from Templateを選びます。

SOPC Information File Nameの欄にはQuartusのプロジェクトのフォルダにあるnios.sopcinfoを選びます。niosの部分はSOPC Builderの一番最初で決めたシステム名になります。
Project名を決めてやります。niostest3にしました。
左下のテンプレートはHello World Smallを選びました。このテンプレートは使用メモリが少ないのでブロックRAM上でも動作します。
Finishボタンを押します。


左のProject Explorerツリービューのプロジェクト名(今回はniostest3)をクリックして灰色に変えてから、Projectメニュー → Build Projectでプロジェクトをビルドします。

Runメニュー → Runを選びます。

Run Asというダイアログが出るのでNIOS II Hardwareを選んで(クリックして灰色に変えて)、OKを押します。


下のNios II Consoleに実行結果が出ます。今回は"Hello from Nios II!"というメッセージを表示します。中のプログラムは以下のようなものです。
#include "sys/alt_stdio.h"
int main()
{
  alt_putstr("Hello from Nios II!¥n");
  while(1) ;
}

ペリフェラルはsystem.hにメモリの番地が書いてあったりしますが、今回は何もないのでincludeしなくても平気です。
リセット(ボタン2)を押すともう一度"Hello from Nios II!"を表示してくれます。
このプログラムは無限ループなのでNios II Consoleの右上にある赤い四角を押してプログラムを終了してやります。

さて、以上で駆け足でしたがQuartusのプロジェクト作成から始まってNIOS II eds上での実行まで眺めてきました。結構、長いですね。

FPGAの部屋さんのまとめサイトを見ながら、独自ペリフェラル(Avalon-MMのスレーブ)を作ってみたりしました。

これからやりたいのは、DE0に搭載されているSDRAMをNiosから使うことです。

分かっていないのは、Nios II上で開発したソフトをROM化する方法です。PCと通信しなくても電源オンですぐ動き出すようにしたいです。ブロックRAMと同じ名前の.hexファイルがあって、これがブロックRAMの初期値になるんじゃないかと思います。.elfファイルを.hexに変換するツールとかがあるのかもしれません。

それにしても、1週間たらずのうちに2度もQuartusをインストールすることになるとは思ってませんでした。


おまけです。


NIOS II edsをインストールしたフォルダの下のbinというフォルダにnios2-terminal.exeというプログラムがあります。このプログラムを使うとNIOS II edsを使わなくてもDE0ボードと通信できます。TeraTermのJTAG UART版みたいなプログラムです。

NIOSを使ってみました(1)

2009-11-04 23:05:04 | FPGA
Altera DE0のJTAG通信?の続きになります。

AlteraのQuartusは9.1から一番小さなNIOS/eが無料で使えるようになりました(marseeさん情報ありがとうございます)。9.0まではどうだったかというと、FPGAボードにsofファイルをダウンロードすると、Quartusからダイアログボックスが出て、ボタンを押すまでは使えるという変則時限使用が可能でした。

やたら手順は長いですが、覚書きがわりに手順を追っかけてみます。
おおざっぱな流れは、

(1) Quartusで新規プロジェクトを作る
(2) デバイスの設定をする
(3) SOPC Builderを起動してCPU(NIOS II)やメモリ、ペリフェラルの設定をしてシステムをGenerateする
(4) Quratusに戻って、トップモジュールやペリフェラルのRTLを作ってFPGAボードにダウンロードする
(5) NIOS II eds(エンベデッド・デザイン・スイート)を起動してCのプログラムを作って、FPGAボードにダウンロード&実行する

くらいになります。FPGAの部屋さんのまとめサイトを参考にしました。


(0) インストール
Quartus II web editionとNiosNios II エンベデッド・デザイン・スイートをAlteraのダウンロードページからダウンロードしてインストールします。昔と違ってライセンスを取得する必要はなくなりました。

(1) Quartus IIの新規プロジェクトを作る

Create a New Projectを押します。
次の画面はNextを押します。

プロジェクトのディレクトリ(d:¥design2009¥niostest3)、プロジェクト名(niostest3)、トップモジュール名(main)を入力してNextを押します。
次の画面はNextを押します。

デバイスを選択します。DE0ボードは、FamilyがCyclone III、Speed gradeが6、デバイス名はEP3C16F484C6です。Nextを押します。
次の画面はNext、その次の画面はFinishを押します。

これでprojectができました。

(2) デバイスの設定
後でやってもいいのですが、忘れないように、まずはsettingで、デバイス関連の設定をしておきます。

settingボタンを押します。もしくはメニューのAssignments→Settingを選びます。もしくはctrl+shift+Eを押します。

左側のCategoryというツリービューのDeviceをクリックします。
次にDevice and Pin Options...というボタンを押します。

Configurationというタブを選んでUse configuration deviceというチェックボックスをチェックしてから右のドロップメニューからEPCS4を選びます。こうすることでeeprom用の書き込みファイル(.pof)を生成してくれるようになります。

他にUnused Pinsというタブで未使用ピンのデフォルトの入出力を決めてやります。
またVoltageというタブでデフォルトのI/Oを選びます(3.3V LVTTL)。
OKを押してDevice and Pin Optionsのダイアログを閉じます。

OKを押してSettingsのダイアログを閉じます。

(3) SOPC BuilderでNIOSを設定する

右上のSOPC Builderのボタンを押して、SOPC Builderを起動します。もしくはToolsメニューのSOPC Builderメニューで起動します。


一番最初のダイアログでシステム名(nios)の入力、HDLの選択(Verilog)をしてからOKを押します。

今回は、システムを動かす最低限の設定だけをすることにします。


まずは左側のLibraryというツリービューのProssorsを開いてNios II ProcessorをダブルクリックしてシステムにNiosを追加します。もしくはAddボタンを押します。
ここのところは9.0と違っています。9.0ではNiosはLibraryの中にはありませんでした。


Nios II/eを選んでFinishを押します。
この画面には後で戻ってきてMemoryのプルダウンメニューを選びます。今はまだメモリーがないのでFinishにしておきます。Nextを進んでいくとデバッグのレベルを選べます。


LibraryツリービューのMemories and Memory Controllers → On-Chip → On-Chip MemoryをダブルクリックしてFPGA上のメモリを追加します。もしくはAddボタンを押します。


メモリーサイズを入力します。とりあえず32768バイトにしてみました。たぶん、もっと増やせます。Finishボタンを押します。


ここでエラーが出ます。32kバイトにしたときはメモリの開始番地を0x0または0x8000にしろというエラーです。現在の値は0x2000になっています。それとしなければいけないこと(To Do)としてcpu_0のリセットベクトルと例外ベクトルを指定しろと出てきます。

まずはonchip_memory2_0の右側の0x00002000をダブルクリックして編集します。0x00008000に変更すると、エラーが消えます。

次にcpu_0をダブルクリックしてNiosの設定に戻ります

Reset VectorのところとException Vectorのところのプルダウンメニューからonchip_memory2_0を選びます。Finishボタンを押して戻ります。
To Doも消えています。
方針としてエラーとかTo doが出たら、とりあえず消すようにするのがいいみたいです。

次にJTAG UARTを追加します。JTAG UARTは左側のLibraryツリービューのInterface Protocols → Serial → JTAG UARTにあります。ダブクリまたはAddボタンでJTAG UARTのダイアログを出してからFinishを押して、システムに追加します。

最後はSystem IDを追加します。System IDは左側のLibraryツリービューのPeripherals → Debug and Performance → System ID Peripheralsにあります。これもダブクリまたはAddボタンでSystem ID Peripheralのダイアログを出してからFinishを押してシステムに追加します。


ここでwarningが出ます。
System IDは追加するだけでは駄目でモジュール名をsysid_0からsysidに変更する必要があります。
sysid_0のところをクリックしてから、右クリックメニューでRenameを選ぶか、ctrl+Rを押すことで名前を変更できます。sysidに変更するとwarningが消えます。

今回はしませんが、この段階で考慮しておくべきこととして、クロックやモジュールの名前を分かりやすいものに変更しておくことがあります。また、複数のクロックがある場合には各モジュールに供給するクロックを選択する必要があります。

ここまでくると、後はシステムを生成(Generate)します。Saveするか聞いてくるのでSaveボタンを押します。しばらく時間はかかりますが、正常に生成し終わると次のような画面が出てきます。

一番下にはSUCCESS: SYSTEM GENERATION COMPLETEDというメッセージが出ています。
EXITボタンを押してSOPC Builderを終了します。


(4) Quartusで論理合成

とりあえず、ここまでで、5段階のうち3段階が終わりました。
(2)は、先にやっておかなくても、(4)のときに一緒にしてもいいです。
どどっと疲れてきたので、(4)は手抜きします。
まずは、main.vを作ります。mainという名前は(1)のときにトップモジュールとしてmainにしたからです。今回は何もペリフェラルの追加を行っていないので、mainはniosを呼び出すだけのモジュールになります。ここのniosというのは、(3)でシステム名をniosにしたからです。他の名前にしたときは、その名前になります。niosの呼び出し方はSOPC Generatorがnios_inst.vというファイルを作ってくれるので、これをコピペします。

nios_inst.vの中身です。
  //Example instantiation for system 'nios'
  nios nios_inst
    (
      .clk_0   (clk_0),
      .reset_n (reset_n)
    );

リセットとクロックしかいません。
コピペして作ったmain.vです。
`default_nettype none
module main(
    input rst_x,
    input clk);

    //Example instantiation for system 'nios'
    nios nios_inst (
        .clk_0   (clk),
        .reset_n (rst_x)
    );

endmodule

クロックをclk、リセットをrst_xという名前にしています。

main.vを追加するには、Quartusの外でテキストエディタを使ってmain.vを作ってからシステムに追加(Projectメニュー → Add/Remove files in Project)したり、Fileメニュー → New → Verilog HDL Fileを選んでから、中身を作ってFileメニュー → Save Asでmain.vと名前をつけてセーブする方法があります。

Pin Plannerを使って、ピン配置を決めます。clkはPIN_G21、rst_xはPIN_F1(ボタン2)にしました。

タイミング制約をつけてやります。50MHzです。

ようやっと論理合成できます。

warningが55個も出ています。
ロジックエレメント(LE)は1379 / 15408 (9%)でした。
Timing Analyzerを見てもfailしているパスはなく全てmetしています。
118MHzで動作する回路ができたようです。

Programmerを起動して、回路を書き込みます。
LEDがうっすらとついています。未使用ピンをハイインピーダンスにしたせいです。


というわけで、疲れてきたので続きます。

Cyclone IV

2009-11-03 17:17:08 | FPGA
アルテラがCyclone IVシリーズを出したそうです。

アルテラのニュースリリース
マイコミジャーナルの記事
アルテラのCyclone IVのページ

Xilinxは、ハイエンドがVirtexでローエンドがSpartan。アルテラはハイエンドがStratix、ミドルエンドがArria、ローエンドがCycloneということのようです。
Quartusもバージョンが9.1になるそうです。

Altera DE0のJTAG通信?

2009-11-01 19:17:06 | FPGA
Altera DE0で使えそうなLCDを探してみましたの続きになります。

Altera DE0がきましたのコメントでnsxさんから、USBを使ってPCアプリと通信できるんでしょうか、というコメントを頂きました。付属CD-ROMにある回路図を見てJTAGしかつながってないから駄目っぽいという返事をしました。でもでも、よく考えてみると付属アプリであるDE0_ControlPanelを使ってPC側からLEDを点けたりVGAの出力を変えるというデモがあります。

これがDE0_ControlPanelの画面です。チェックボタンでLEDを点けたり消すことができます。


DE0_ControlPanelが動作している最中にXPのデバイスマネージャを見てもCOMとかはいません。Altera USB-Blasterがいるだけです。

DE0_ControlPanel.exeのいるフォルダには他に3つのdllがいます。
- TERASIC_DOWNLOAD.dll
- TERASIC_JTAG.dll
- TERASIC_JTAG_DRIVE.dll
このdllが怪しげです。JTAGの通信にまぎれて、アプリ間通信をするような機能がいるような雰囲気です。dumpbin.exeを使って中身を調べてみました。

TERASIC_DOWNLOAD.dllがexportしているAPIです。
    ordinal hint RVA      name
          2    0 00006108 @@Download@Finalize
          1    1 000060F0 @@Download@Initialize
         15    2 000063E4 @@Ftdicontrol@Finalize
         14    3 000063D4 @@Ftdicontrol@Initialize
         10    4 00006350 TERASIC_AsDownload
          3    5 00006120 TERASIC_DownloadEEPROMByByteBlaster
          7    6 00006284 TERASIC_DownloadNios2
          9    7 000062F4 TERASIC_FlashProgrammer
         12    8 000063BC TERASIC_GetQuatusVersion
         11    9 000063A8 TERASIC_IsUsbBlasterDriverReady
          5    A 000061CC TERASIC_JtagDownload
          4    B 00006174 TERASIC_JtagDownloadByteBlaster
          6    C 0000622C TERASIC_JtagDownloadChain
          8    D 000062DC TERASIC_Nios2Terminal
         13    E 000063C4 TERASIC_SetQuartusProgrammerPath
         16    F 0006A0F8 ___CPPdebugHook

いかにもダウンロード用といった感じのAPIが並んでいます。

TERASIC_JTAG.dllがexportしているAPIです。
    ordinal hint RVA      name
          2    0 000018B0 @@Jtagport@Finalize
          1    1 000018A0 @@Jtagport@Initialize
          4    2 00001938 TERASIC_JtagClose
          7    3 000019F0 TERASIC_JtagGetInfo
          3    4 000018C0 TERASIC_JtagOpen
          6    5 000019B8 TERASIC_JtagRead
          5    6 00001980 TERASIC_JtagWrite
          8    7 0000A0F8 ___CPPdebugHook

ReadとかWriteがあって、いかにも通信用って感じです。

TERASIC_JTAG_DRIVE.dllがexportしているAPIです。
    ordinal hint RVA      name
          1    0 00001E94 jtag_atlantic_clearstall
          2    1 00001B9C jtag_atlantic_get_offset
          3    2 00001B70 jtag_atlantic_init
          4    3 00001DEE jtag_atlantic_read
          5    4 00001D56 jtag_atlantic_status
          6    5 00001E39 jtag_atlantic_transfer
          7    6 00001DA3 jtag_atlantic_write
          8    7 00002889 jtag_avalon_address
          9    8 00002773 jtag_avalon_get_offset
         10    9 00002745 jtag_avalon_init
         11    A 000028AC jtag_avalon_mode
         12    B 00002912 jtag_avalon_read
         13    C 0000282A jtag_avalon_status
         14    D 000028CF jtag_avalon_write
         15    E 0000192A jtag_close
         16    F 00001963 jtag_command
         17   10 00001000 jtag_init
         18   11 00002671 jtag_pio_init
         19   12 000026FF jtag_pio_read_outputs
         20   13 00002678 jtag_pio_status
         21   14 00002722 jtag_pio_write_inputs

avalonとかatlanticって何なんでしょう?

デバッガを使ってDE0_ControlPanel.exeを追いかけてみるとTERASIC_JTAG.dllが通信用でした。Openは2つのパラメータ、ReadとWriteは3つのパラメータ、Closeは1つのパラメータを使っています。送っているデータを覗いてみると、次のような形式になっていました。

先頭の1バイト 0xaa 固定
2バイト目 コマンド (LED関連は0x02、VGA関連は0x0d等)
3バイト目 送信するデータのバイト数をnとすると n - 6
4バイト目 0x00 固定 (用途不明)
5バイト目から 送信データ
...
n-1バイト目 チェックサム (2バイト目からn-2バイト目までの総和 mod 256)
nバイト目 0x55固定

LED点灯コマンドのときは5バイト目がLED7~LED0、6バイト目がLED9,LED8の点灯パターンを送っています。全部点灯するときは5バイト目が0xff、6バイト目が0x03になります。全点灯するときに送信するデータです。
aa 02 02 00 ff 03 06 55
初期化のときに送っているデータです。
aa 00 00 00 55
VGAのパターンを選択するときに送っているデータです。
aa 0d 01 00 00 0e 55
受信するデータも同じ形式です。内部処理では最初に先頭の4バイトを読み込みます。続きの長さが分かるので、続きを読むという感じで2回に分けて可変長のデータを受信しています。

ソースとかドキュメントといった情報が全然見つかっていないので、無理矢理リバースエンジニアリングしてしまいました。JTAGラインを使ってデータを送受信していることくらいまでは分かりましたが、そこから先はさっぱりです。そもそもFPGA側にどんな回路を作ればいいのかも分かりません。Terasicが情報を公開しないかぎりは、これ以上は難しそうです。


なんてことを↑で書きましたが、NIOS IIとかAvaronでぐぐってみると、Avaron BUSとかJTAG UARTみたいなキーになりそうな言葉がひっかかってきます。自分で使うときはTERASIC_JTAG_DRIVE.DLLを直接叩くのかもしれません。