60
1 MAX ® 10 FPGAで学ぶ FPGA開発入門

FPGA開発入門 - intel.co.jp · fpga の場合、cpuコアとfpga ファブリックの連携が高速に 行えるので、トータルとしての性能も上げやすい。 低価格化

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

1

MAX® 10 FPGAで学ぶFPGA開発入門

2

MAX 10 FPGAで学ぶ FPGA開発入門(1) (2015年 8月10日)

なぜ FPGAが注目されるのか、開発ボードに触れて確認するhttp://monoist.atmarkit.co.jp/mn/articles/1508/10/news012.html

3

MAX 10 FPGAで学ぶ FPGA開発入門(5) (2015年 12月11日)

よろしいならばダイナミック点灯だ――FPGAで LEDをダイナミックに Lチカさせるhttp://monoist.atmarkit.co.jp/mn/articles/1512/11/news015.html

20

MAX 10 FPGAで学ぶ FPGA開発入門(3) (2015年 10月13日)

FPGAでの LチカをVerilog HDLで理解するhttp://monoist.atmarkit.co.jp/mn/articles/1510/13/news023.html

13

MAX 10 FPGAで学ぶ FPGA開発入門(7) (2016年 2月16日)

FPGAのソフトコア CPUをベンチマークで測定するhttp://monoist.atmarkit.co.jp/mn/articles/1602/16/news034.html

31

MAX 10 FPGAで学ぶ FPGA開発入門(10) (2016年 5月19日)

「MAX 10 NEEK」に搭載されたDDR3メモリを使うhttp://monoist.atmarkit.co.jp/mn/articles/1605/19/news021.html

46

MAX 10 FPGAで学ぶ FPGA開発入門(2) (2015年 9月10日)

「MAX 10 FPGA」のテスト環境を構築するhttp://monoist.atmarkit.co.jp/mn/articles/1509/10/news002.html

6

MAX 10 FPGAで学ぶ FPGA開発入門(6) (2016年 1月 26日)

FPGA上でソフトコア CPUを動かす手引きhttp://monoist.atmarkit.co.jp/mn/articles/1601/26/news007.html

24

MAX 10 FPGAで学ぶ FPGA開発入門(9) (2016年 4月12日)

「MAX 10 NEEK」へソフトコア CPUを組み込むhttp://monoist.atmarkit.co.jp/mn/articles/1604/12/news085.html

40

MAX 10 FPGAで学ぶ FPGA開発入門(4) (2015年 11月13日)

FPGAの LED制御プログラムを深く理解するhttp://monoist.atmarkit.co.jp/mn/articles/1511/13/news007.html

16

MAX 10 FPGAで学ぶ FPGA開発入門(8) (2016年 3月10日)

周辺機器の充実した「MAX 10 NEEK」で本格的な開発を目指すhttp://monoist.atmarkit.co.jp/mn/articles/1603/10/news058.html

35

MAX 10 FPGAで学ぶ FPGA開発入門(11) (2016年 6月14日)

「MAX 10 NEEK」でストップウォッチを開発し、内蔵メモリから起動するhttp://monoist.atmarkit.co.jp/mn/articles/1606/14/news111.html

53

著者 大原 雄介

※ すべての商標および登録商標はそれぞれの所有者に帰属します。※ 記事は執筆時の情報に基づいており、現在では異なる場合があります。

3

MAX 10 FPGAで学ぶ FPGA開発入門(1)

なぜ FPGAが注目されるのか、開発ボードに触れて確認する最近では「FPGAの重要性」について語られる機会が増え、適用事例も増加している。ではなぜ今 FPGAなのか。実際の開発ボードで FPGAを学びながら、FPGAへの理解を深めよう。

なぜ今、FPGAが注目されているのか

 個人的な感想で恐縮だが、2012~ 2013年あたりから急速にFPGAの適用事例が増えてきている気がする。 これは 2010年前後から、いわゆるASICの開発コストが急速に高騰化し始め、おいそれとASICを作れなくなったことに加え、汎用MPUあるいはあまり特定用途に特化しすぎていないASSP(モバイル機器向けSoCなどこの好例であろう)の性能が急速に改善したと、加えて FPGAそのものが 45nm~ 28nm世代に移行することで高性能が進んだことも無縁ではないはずだ。 この結果、従来だとASICで済ませていたシステムを、ASSP+FPGAなどの構成で済ませることが可能になってきた。部品原価の面で言えばまだ ASICに分のあることもあるが、ASICの開発コストまで勘案するとペイしなくなりつつある。であれば、多少部品原価が上がっても、FPGAをシステムの中核に組み入れた方が開発コストの低減や開発期間の短縮化、機能の充実や構成の柔軟な変更などメリットが上回る事になる。 こうした理由で FPGAを利用したシステムデザインの増え始めたのが 2009~ 2010年ごろ、それが最終製品として世の中に出始めたのが 2012年あたりからということになる。昨今では随分FPGAを組み込んだ最終製品が増えてきたように思う。

FPGAのトレンド こうした市場の活性化や拡大に伴い、各社がさまざまな製品を頻繁にリリースしている。MONOistのFPGAコーナーを見ていただければ、そうした状況の一端もお分かりかと思う。ここ数年のトレンドで言えば、

FPGAの高集積化 28nmに続き、20nmプロセスを利用した製品出荷や 16/14nmプロセス向けの開発ツールのリリースなど、先端製品はどんどん微細化を進めている。FPGAの場合、いろいろ新技術や新機能は入っているものの基本的には SRAMの塊であって、SRAMの容量はつまるところプロセスを微細化するほど増える結果、利用できるゲート数がどんどん増える事になった。

CPUの搭載 以前からMPUあるいはMCUを内蔵した製品は存在していたが、昨今はCortex-A9コアを内蔵したものが幅広く利用されており、これまで SoC+ FPGAの形で構成されていたシステムをFPGA1個で済ませられる様になった。またこうしたCPU内蔵FPGAの場合、CPUコアとFPGA ファブリックの連携が高速に行えるので、トータルとしての性能も上げやすい。

低価格化 高集積化の逆説的な効果でもあるが、ハイエンド FPGAは相変わらず高価なままである。ところが一番広く使われるミドルレンジや、さらにその下に位置する製品についてはどんどんコストが下がっている。その結果、FPGAとは思えないような金額で入手する事も可能になってきた。

 例えば Lattice Semiconductorの提供する「iCE40ファミリー」の場合、ゲート数(同社の用語ではロジックセル数)が 384~ 7680と小規模だが、その代わり一番安いものはデジキーあたりで 1個単位で買っても 300~ 400円、ある程度の数量(1万個程度)だと 1個 100円を切る金額で入手できる。 同規模製品だとMicrosemiの「IGLOOシリーズ」がやはり同程度の価格帯であるし、もう少し回路規模の大きいAlteraの「MAX 10」やXilinxの「Artix」、あるいは前世代製品の「Spartan」などは数千円のオーダーで購入できる(調べてみたら、3840ゲートのSpartan 6 LXがデジキーでは 1個 1595円で購入可能だった)。 こうしたローエンド製品の低価格化に加え、FPGAのマーケットが広がった事で各社開発ボードや評価ボードを充実させてきた事により、「FPGAを使ってみよう」という際の敷居が急激に下がってきた感がある。なにより開発キットの値段が急激に下がった。 *ちょっと古い話だが、MONOistでも 2007年から「触って学ぼうFPGA開発入門」という連載があり、連載で利用されていたのはヒューマンデータの「EDX-002」だった。ただこの製品そのものがもう通常販売が終了しており、現在は処分特価という名前の在庫処分が行われている状況だし、搭載されている FPGAはXilinxの Spartan-IIで、これもまたちょっと古すぎる。

※ すべての商標および登録商標はそれぞれの所有者に帰属します。※ 記事は執筆時の情報に基づいており、現在では異なる場合があります。

4

「MAX 10」でFPGA開発の基礎を学ぼう

 ということで、いよいよ本題。 FPGAベンダーは各社とも新製品が出るたびに、これを利用できる開発キットや開発ボードをリリースしているが、通常は汎用の開発ボードの上に、FPGAの乗ったドーターボードを積むという形態が多く、ちょっと試してみようといった用途にはコストの面から適切とは言いにくいものだった。 ところが Alteraが 2014年 10月に発表した「MAX 10」の場合、当初から自社でも低価格な評価キットが用意された上、早期からパートナーによるやはり低価格な開発キットが提供された。 Alteraはさらに「MAX 10 NEEK」と呼ばれる開発キットを発表している。こちらはMAX 10の上で「Nios II」というソフトウェアCPUを駆動し、この上でさまざまな機器を開発するためのリファレンスデザインとなっており、この結果、単にチップだけではなく7インチ/ 5点タッチ認識の液晶ディスプレイと 8Mピクセルのカメラ、HDMI出力、温度/湿度センサー、3軸加速度センサー、マイクなどを搭載した、充実したキットとなっている。その分、お値段もそれなりで直販価格は 375 USDとなっているから、ちょっと触ってみたいという用途にはやや不適当ではある。 さて、その代わりといっては何だが、MAX 10の発売当初から予告されていた「MAX 10 FPGA 評価キット」を使って、FPGAで遊んでみたいと思う。 このキットを選んだ理由は幾つかある。まずは価格。$49.95というのは、FPGA評価キットとしては飛びぬけて安い。購入はAlteraの直販サイトからもできるし、代理店(筆者はMouser Electronicsから購入した)から入手も可能だ。

 さらに安価な製品としては、Arrowが提供する「BeMicro MAX 10評価キット」が $30.00だが、こちらは最近でこそ供給体制が整ったようだが当初はちょっと入手が難しかったのでパスした。 2つ目が拡張性。Photo01を見てもらえれば分かるが、ボードの上にArduinoと互換のピンヘッダが用意されており、実際にArduinoのシールドが流用可能となっている。これについては、そもそも 2014年 9月に国内でMAX 10に関する説明会が開催された折、同社のPartic Dorsey氏(Senior Director of Product Marketing)が、まさにこの評価キットの上にArduino用の LCDシールドを搭載して動作させるというデモを行っており(Photo02)、このあたりはArduinoの I/Oに慣れている筆者としては有難いものと判断したからだ。

 Arduino互換のシールドは多用多種存在しており、これらを使う事で容易にデバイスを使える事になる。ピン数が足りなければ、ボード上に用意されているピン経由で、Arduino用に割り当てられた以外のMAX 10のピンを利用できる(ただ当初はとりあえず使うというレベルだから、そこまでの拡張性は必要ないだろうという気もするが)。 3つ目が、FPGA自身の拡張性である。この評価キットに搭載されているのは 10M08という製品で、ゲート(Alteraの用語ではロジックエレメント LE:Logic Element)数が 8K、Block Memoryが 378Kbit、User Flashが 32~ 172KB、18×18のMultiplierが 24個と、ローエンドにしてはなかなかな充実振りとなっている。 何をやらせるかによって 8K LEで足りる場合もあれば全然足りない場合もあるが、取りあえず多すぎるほどの規模である。 加えて言うなら、これだけの規模があると、同社のNios IIプロセッサも動作する。Nios IIは同社が提供するEmbedded CPUのIPであるが、最小構成ならば 600LEでNios IIが構築可能である。絶対性能そのもので言えば Cortex-M4あたりのプロセッサコアを搭載した方がはるかに高速であるが、構成を変えて試すには最適であるし、FPGAとプログラムの協調動作なんてことをさせるには

Photo01:ボード上のロゴから分かる通り、ボード設計そのものが aXelsysが行った模様。パッケージはこの基板とUSBケーブル、それと (平置き用の )ゴム足のみのシンプルな構成

Photo02:このデモでは、評価ボードにマイクが接続され(ボードから下にぶら下ってる赤 /黄 /黒の線の先にマイクがつながっている)、ここで捕らえた音量を測定してLCDに棒グラフで表示するという簡易騒音計の実装を行ったデモである。ちなみにUSBケーブルは電源供給のためだけに使われている

5

Nios IIは非常に便利である。 ということで、次回からこのMAX 10評価キットを使って色 と々

遊んでみた様をご紹介してゆきたいと思う。

MAX 10 FPGA 評価ボードとブロック図

6

Photo01:米オフィシャルサイトの「MAX 10 FPGA 評価キット」購入ページ。日本語の評価キットの購入ページはこのページに飛ばされる Photo02:米 Alteraから購入するとUSB Blasterが 56.67ドルで購入できるが、評

価キットとのまとめ買いは「自分で」との断り書きが

MAX 10 FPGAで学ぶ FPGA開発入門(2)

「MAX 10 FPGA」のテスト環境を構築する今回から実際に「MAX 10 FPGA評価キット」を利用しての開発に着手する。まずは環境構築だ。キット以外に必要なモノもあるので注意して欲しい。

評価キット以外に入手すべき2アイテム

 前回(MAX 10 FPGAで学ぶ FPGA開発入門(1))でご説明したようこの連載では Altera「MAX 10 FPGA 評価キット」を利用するが、キット以外にも必要なものがある。入手すべきものは「MAX 10 FPGA 評価キット」の他、「USB Blaster」「Quartus II Web Edition」である。 評価キットについては前回紹介したので詳細は省くが、入手方法としては、Alteraのショッピングサイト(Photo01)の他、Digi-Key、Mouser Electronics、Terasicなど販売代理店からの購入も可能である。

 筆者はMouserから購入したが特に深い意味がある訳ではない(というか、列挙した販売代理店は全て使った事があり、どこからも問題なく製品が届いている)。購入の際は在庫とか送料などで決めてしまって良いと思う。Mouserにオーダーした時も、確か数日で到着したと記憶している。 さてそのMAX 10 FPGA評価キットだが、オンボードのMicro USBコネクタは電源を取る事にしか利用できない。というのはUSBコネクタからの配線は Enpirionという PMIC(Power Management IC)に直結しており、実はこのコネクタを経由してのUSBとしての動作はもちろん、FPGAのプログラミングも不可能である。

 では FPGAへのプログラミングをどうやって行うかというと、基板上に用意された JTAGピンから行う事になる。この JTAGピン経由でプログラミングを行うためのツール(というかケーブル)が「USB Blaster」と呼ばれる製品である。これは「MAX 10 FPGA 評価キット」とは別に用意する必要がある。

 ちなみにこのUSB Blaster、Alteraのサイトでは 1個 300ドルと正規品はあまり安くないが、Digi-KeyではMAX 10 FPGA評価キットとのセットで 1万 4812円付けている他、米 Alteraでは56.67ドルで販売しているがまだちょっと高い(Photo02)。 幸いUBS Blasterに関しては互換品が大量に出回っているし、自作している方もいらっしゃる。筆者は TerasicのUSB Blaster互換品「Terasic Blaster」を利用した。 「Quartus II Web Edition」は、FPGAのプログラミングを行うための開発環境である。Quartus II自体はSubscription EditionとWeb Editionがあり、前者は有償(契約ベース)、後者は無償で入手

7

できる。両者の違いはこちら(リンク先 PDF) で確認できるが「MAX 10を使って遊ぼう」というレベルであれば無償版で十分である。 まず「MAX 10 FPGA 評価キット」から話をしよう。評価キットのパッケージに入っているのはこれだけ(Photo03)で、これ単体でたいしたことはできないが動作確認はできる。 方法は簡単。USBケーブルを評価キットにつなぎ、適当なUSBポートから給電すると、基板上の LED 1~ 5が 1秒間隔で点滅(正確には 0.5秒点灯、0.5秒消灯)する(Movie01※)。 これは評価ボード上のMAX 10に初期状態で書き込まれているプログラムによるもので、点滅していれば正常である。逆にここで点滅しないようであれば初期不良の可能性がある。まずはこれを確認しよう。

 次はUSB Blasterである。前ページで説明した通り、今回はTerasicのUSB Blasterを利用した(Photo04)。内蔵されているのはUSB Blaster本体とUSBケーブルのみである。このケーブルを評価キットのJTAGポートに装着すれば準備OKである。ち

なみにまだUSB Blaster本体をUSBケーブルで PCと接続してはいけない(ドライバのインストールが必要)。これはQuartus IIのインストールの際にあわせて行うことになる。

Quartus II Web Editionのインストール その次がQuartus II Web Editionである。最新のダウンロードページはこちらである(Photo06)。ここから必要なファイルをダウンロードできる。

 最低限必要なのは「Quartus II Software (includes Nios II EDS)」「ModelSim-Altera Edition (includes Starter Edition)」「MAX 10 FPGA device support」だが、他にもQuartus IIのHelpやらSoftware updateやら、別途落とした方が良いものもあるので、「一式ファイル」での入手が楽だ。 問題はこのファイルサイズが約 5.5Gバイトもあることで、光接続環境でも 30分ほど必要とした。ダウンロード時の回線には気を付けて欲しい。

Quartus IIの環境構築 さて、実際にダウンロードしようとすると、その前に「myAltera」への登録が要求されるので、ここで登録を行ってからダウンロードを行う。ダウンロードが終わったら展開して(なぜかWindows向けも tarファイルで提供されるので、ツールで適当なディレクトリに展開、setup.batを起動するとインストールが開始される。 インストールそのものはごく普通だが、インストールディレクトリ

Photo03:パッケージ内容はボードとケーブル、平置き用のゴム足×4のみ

Photo04:Terasic「USB Blaster」謎のパッケージ。そういえばちょっと前からAtmelがこうした謎のロボットのパッケージを利用していたが、それにならったのだろうか?

Photo06:「個別ファイル」Tabで必要なものをきちんと選択しても良いが、面倒なら「一式ファイル」Tabでまとめて落とすほうが楽。ただし、ファイルサイズが 5G超とデカイ

※このページのムービーはこちら → https://www.youtube.com/watch?v=tLT-f7S_oC8

8

がちょっと変(Photo08)とか、インストール時のチェックに注意(Photo09)といったあたりが要注意だ。またインストールが終わった際には、USB Blasterのドライバのインストールを行うかどうかのチェックを入れておこう(Photo10)。問題なければ普通にドライバがインストールされるはずだ(Photo11)。 以上が完了したら、USB BlasterをPCのUSBポートに接続する。するとドライバの検索が始まるが、基本ここでは発見できないと思った方がいい。そこで「コンピューターを参照してドライバーソフトウェアを検索します」を行う必要がある。 ここでドライバが入っているディレクトリ(今回の例だと “C:\altera\15.0\quartus”を指定し、“サブディレクトリも検索する ”を有効にする)と、ドライバが発見され、インストールが終了(Photo13)。USB Blaster経由での FPGAへのプログラミングが可能になった。 以上で一応の環境は整ったが、せっかくなのでプログラミングできる事を確認してみよう。

Photo08:説明の関係で一応このデフォルトのままインストールした

Photo09:一番下の “ModelSim-Altera Edition” は有償のソフトウェアなので、インストールしても意味が無い。またデバイスは使うもの(今回なら "MAX 10 FPGA")のみにチェックをつけておく

Photo10:一番上の "Launch USB Blaster II driver installation"にチェックが入っている事を確認しておく

Photo11:なぜ “Delaware Altera Corporation” かといえば、同社が米 Delaware州の会社だから

Photo12:待っていても見つからないので、“Windows Updateからのドライバーソフトウェアの取得をスキップする”をクリックするのが吉

Photo13:インストール完了。ちなみに今回は Terasic USB Blasterでの例だが、Alteraの純正USB Blasterやその他の互換USB Blasterも手順は同じだと思われる

9

 Quartus IIを起動すると最初にダイアログが出て、その次にQuartus IIの画面が出現する(Photo14)(Photo15)。ただここでいきなりデザインを入力、というのもハードルが高いので、まずはありモノをちょっとモディファイしてみることにしたい。 Quartus IIをインストールしても、いわゆるサンプルプログラムのたぐいは一切入っていないのでWebから入手する。MAX 10向けの場合、Alteraの「Design Store」にいろいろ置かれている(Photo16)。今回はこの中から「Restore Factory Settings LED Flash」を選んでみる(Photo17)。ここで「Download」を選ぶと、「LED_Flash.par」というファイルがダウンロードされるはずだ。 この .parファイルの取り込みは、以下の流れで行う。

Photo14:初回起動時の画面。ここでは真ん中の “Run the Quartus II software"をチェックしてOKを押す

Photo15:Quartus IIの初期画面はこんな感じ。これは Projectも何もない、まっさらな段階

Photo16:さまざま開発キット向けの Sampleが混在しているので、ちょっと分かりにくい (1) "File"→ "New Project Wizard"を選択(Photo18)

Photo17:「Restore Factory Settings LED Flash」は要するにMovie01の動作の、0.5秒毎に LEDの点滅を繰り返すという奴である

10

(2) 適当な名前で Projectを作成(Photo19)

(3) Project Typeで "Project template"を選択(Photo20)

(5) Template指定で、先ほどダウンロードした .parファイルを指定(Photo22)

(6) 一覧に追加された "Restore Factory Settings LED Flash"を選択(Photo23)

(4) Template一覧で、"Install the design templates."をクリック(Photo21)

 ここまで終了した段階で、左側の「Entity」の下にある「LED_Flash_all」をクリックすると、ソースコードが表示されるはずだ。 ちなみに、これで生成されたソースコードは以下「List1※」になる。 ソースコードの説明はまた次回以降に説明するとして、これをこのままコンパイルしてファイルを生成、ダウンロードしても LEDに変化はない。

(7) Templateを利用して新規プロジェクトが生成(Photo24)

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news001.html

11

 そこで最後の 5行を書き換えてみた。

assign LED1 = dec_cntr ;assign LED2 = dec_cntr ;assign LED3 = dec_cntr ;assign LED4 = dec_cntr;assign LED5 = dec_cntr ;

 から

assign LED1 = dec_cntr ;assign LED2 = !dec_cntr ;assign LED3 = dec_cntr ;assign LED4 = !dec_cntr;assign LED5 = dec_cntr ;

 に変更してみた。 dec_cntrは 0か 1の値を取り、0なら LEDが消灯、1なら点灯する。そこで LED 1/ 3/ 5とLED 2/ 4に与える値を反転させることで、互い違いに点滅させようというものだ。この変更をQuartus IIの画面上で行ったら、やはり左側、Entityの下にある“Tasks” 画面で “Compile Design”をクリックすると、問題がなければ数分(環境による:2回目以降は 1分かからなかった)後にコンパイルが完了するはずだ(Photo25)。

USB Blasterでの書き込み これまで完了したら、その下にある “Program Device”をクリックするとProgrammerが起動する(Photo26)。 初期状態では USB Blasterを認識していないので、左上の

Photo25:赤枠で囲った部分をクリックするとコンパイル開始。Warningが 16個ほど出ているが、今は無視してよい。利用している LEは 45個、レジスタは 28個で、ほとんど使ってないと言ってい。

Photo26:Modeは JTAGのままで構わない

Photo27:もし一覧になければ、"Add Hareware..."ボタンを押して USB Blasterを登録しておく。逆に一覧にあれば、それ以上追加する必要はない

Photo28:"output_�les"というサブディレクトリは自動で生成されるが、指定は手動で行う必要がある

“Hardware Setup...”を押してHardware Setup画面を出す。 ドライバが正しくインストールされていれば USB-Blasterが一覧にあるはずなので、“Currently selected hardware”を “USB-Blaster”に設定する(Photo27)。

12

 次に programmerの “Add File”ボタンを押し、プロジェクトディレクトリの下の “output_files”ディレクトリに生成した「LED_Flash.pof」を指定する(Photo28)。すると書き込み画面に戻るので、“Program/Configure”にチェックを入れて “Start”ボタンを押すと、MAX 10への書き込みが始まる(Photo29)。 書き込み時間は 1分よりはかかるかな?という感じ。無事に書き込みが終わると、すぐに起動し、狙い通り、互い通りに LEDが点滅することが確認できた(Movie02※)。 だいぶ長くなってしまったが、今回は入手から環境整備、書き込みの検証までが行えた形だ。次回は FPGAの記述言語(という言い方はちょっと妙なのだが)である「Verilog」の話なども交えて、もう少し具体的なことをやってみたいと思う。

Photo29:"Veryfy"あるいは "Blank-Check"は別にチェックをつける必要はない(この画面ではチェックを入れて実施したが、すると書き込みに加えて検証も行われるので 10分近く必要になる)

※このページのムービーはこちら → https://www.youtube.com/watch?v=hPOdpEnhTX8

「MAX 10 FPGA」のテスト環境を構築する

13

MAX 10 FPGAで学ぶ FPGA開発入門(3)

FPGAでのLチカをVerilog HDLで理解する今回は FPGAでの Lチカを例に、FPGA開発に必要なハードウェア記述言語の解説をしたい。用いる「Verilog HDL」はArduinoや Cの経験がある方なら、理解そのものはそう難しくないと思う。

 前回(「MAX 10 FPGA」のテスト環境を構築する)はではMAX 10 FPGAとQuartus II、それにUSB Blasterを使って簡単にソースコードを書き換えるところまでご紹介した。今回はもう少し中身を説明したいと思う。 下のリスト※が前回も説明した、Lチカのソースコードとなる。記述はQuartus IIがサポートするVerilog HDLでのものだ。 まず冒頭の "`timescale 1ns / 1ps"は、実は Lチカの動作とは全く無関係である。これはQuartus IIから呼び出されるシミュレータで利用されるもので、意味としては ns単位の割り込み(例えば開始後 12.5142ns後に入るとする)を ps単位に丸める(開始後12514psに割り込みが入る)という意味である。ということで無視してもらいその後に来るのがコメントだが、これも見れば分かると思うので説明は割愛する。

module宣言 さて、ソースの最初に出てくるのがmodule宣言である。この場合は LED_Flash_allというモジュール名をつけている(ユニークであればなんでもいい)のだが、ここで入出力は clkという input、それと LED1~ 5という outputがあることを示している。

module LED_Flash_all( input clk, output LED1, output LED2, output LED3, output LED4, output LED5 );

 つまりFPGAには(電源以外だと)Clock信号のみが入力され、LED駆動出力 5本が出てくるという仕組みだ。このmodule宣言と対をなすのが、リストの最後にある endmoduleで、この間に挟まれたブロックは全て、ここで宣言した inputと outputしか(外部に出す信号としては)使えないことになる。 余談になるが、きちんと文法的に正しく書くのであれば

module LED_Flash_all( input wire clk, output wire LED1, output wire LED2, output wire LED3, output wire LED4, output wire LED5 );

 とした方が良い。input/outputは入出力だが、次の "wire"は配線を示す。つまり信号線の形でつながっている事を明示的に示すもので、これに対比されるのが "reg"(レジスタ)である(Quartus IIではここでwireを省いても問題はないのだが)。ちなみに当然ながら clkや LED1~ 5は何れも 1bitの変数として扱われ、保持できる値としては 0か 1ということになる。

レジスタ定義 さて、これに続いてレジスタ定義部が来る。

reg[15:0] div_cntr1; reg[9:0] div_cntr2; reg dec_cntr; reg half_sec_pulse;

 これは内部でカウンタを使う際に利用するもので、物理的な実体は内部のラッチである。レジスタも当然黙っていると 1bit幅になるので、もっと幅が欲しい場合には、例えば div_cntrl1の様に

reg[15:0] div_cntrl1;

 といった指定を行うことになる。こうするとMSBが 15、LSBが 0となる 16bit幅のレジスタが確保される(要するにラッチが 16個並ぶ)事になる。これもまた変数として扱える事になる。

組み合わせ回路の記述 いよいよメインとなる組み合わせ回路の記述部である。組み合わ

Module入出力宣言

レジスタ定義

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news002.html

14

せ回路は実際には幾つかあり、後述する assign以外にもあるが、ここではベーシックな initialとalwaysである。ここで initialは「電源投入時、もしくはリセット後に一度だけ実行される回路」、alwaysは「常に動いている回路」となる。arduino的に言えば前者が void init()、後者が void loop()にあたると理解していただくと早い。今回の回路では、initialは 3種類のカウンタを 0クリアするのだけに使っている。

initial begin div_cntr1 = 0; div_cntr2 = 0; dec_cntr = 0; end

always@(posedge clk) begin div_cntr1 <= div_cntr1 + 1; if (div_cntr1 == 0)   if (div_cntr2 == 762) begin div_cntr2 <= 0; half_sec_pulse <= 1; end   else     div_cntr2 <= div_cntr2 + 1; else   half_sec_pulse <= 0; if (half_sec_pulse == 1) dec_cntr <= !dec_cntr; end

 さて、メインとなる部分は alwaysからだ。最初の

always@(posedge clk)

 はクロック信号を取り込み、この信号の正の立ち上がりのタイミングで begin以下を実行するという意味である。コメントにもあるようにクロック信号は 50MHzが供給されるので、always以下のbegin~ endのブロックは毎秒 50M回実行されることになる。 ただ目的は 1秒単位の LEDのOn/Offなので、これはあまりに高速すぎる。そこでまずdiv_cntr1を使ってこれを分周する。initialのところで div_cntl1は 0に初期化し、で alwaysの begin直下

でいきなりdiv_ctrl1に 1を追加してる( <=は代入の意味なので、C風に書けば div_cntrl++; ということになる)。そのあとで div_cntl1が 0かどうかチェックしてるのは誤解を招きそうだが、要するにdiv_cntl1は毎秒 50M回加算をされることになる。ただしdiv_cntl1は 16bitのレジスタなので、65535の後で 0に戻る事になる。要するに

begindiv_cntr1 <= div_cntr1 + 1;if (div_cntr1 == 0) : : : :else half_sec_pulse <= 0;

 とすることで、"…………"の部分が呼ばれる頻度は毎秒 50M÷65536= 762.939……で毎秒 763回になるわけだ。で、呼ばれていない間は常に half_sec_pulseというカウンタを 0にしているだけである。 さて、では "…………"の中身は?というと、こちらの中ではさらにdiv_cntl2というカウンタを回している。こちらは10bitのカウンタなので、1024まで達すると0に戻るが、1秒にするためには 763にしておかないと都合が悪いので、明示的に 762になったかどうかを判断して、762に達したらhalf_sec_pulseを1にセットし、div_cntl2を 0に戻す。そうでなければ div_cntl2を 1増やすというシンプルなものだ。この結果、if(div_cntr1 == 0)...から始まる ifブロックが終了するとき、約 1秒に 1回だけ half_sec_pulseが 1になり、他の時には 0になるというわけだ。 dec_cntrは純粋にLEDのOn/Offの状態を保持するもので、見て分かる通り、half_sec_pulseが 1の時だけ値をひっくり返すという処理になる。 最後が assignで記述した部分である。便宜的に「出力割り当て宣言」と書いたが、実は必ずしも出力でなくても良い。assingは「配線の割り当て」を定義するもので、この例で言えば LED1/3/5には dec_cntrの値をそのまま流し、LED2/4には値を反転して流す事を指定している。ここで注意されたいのは、assignの動作は「同時」であることだ。

assign LED1 = dec_cntr ; assign LED2 = !dec_cntr ; assign LED3 = dec_cntr ; assign LED4 = !dec_cntr; assign LED5 = dec_cntr ;

初期手続き部

手続き部(メイン)

15

 先の div_cntr2の部分であるが、以下のブロックでもし div_cntr2が 762だった場合、(1)div_cntr2に 0を代入する、(2)half_sec_pulseに1を代入するという順番で処理は進む。 ところが assignは処理ではなく接続なので、動き出すタイミングで既に配線が済んでおり、同時に行われる事になる。

if (div_cntr2 == 762) begin div_cntr2 <= 0; half_sec_pulse <= 1; end

 これはブロック図で見た方が分かりやすいかもしれない。Photo01はこのプログラムのコンパイル後にブロックのマッピングを表示させたものだ。dec_cntrという緑のブロックは、要するにdec_cntrの値を保持する 1bitのラッチであるが、その出力がLED1~ outputから LED5~ outputの 5つのバッファに直接つながっている。ただし LED2と LED4には、論理反転を示す○がついているのがお分かりかと思う。なので LED1~ 5の出力は、dec_cntrのラッチの出力が変化した瞬間、同時に変化することがお分かり頂けるかと思う。 ということで、文章で書くと案外に長くなるが、ArduinoあるいはC/C++のプログラミング経験がある方なら、所々作法に違いがあるとはいえ、理解そのものはそう難しくないと思う。もちろん、これは Verilog HDLの文法の一部の話であって、C/C++系とは異なる概念なども少なくないのだが、この連載はそうした部分を網羅

的にカバーするのが目的ではないので、この先も新しい概念なり何なりが出てきたらその都度説明する形で進めてゆく予定だ。 網羅的に知りたい、という方は検索エンジンで「Verilog HDL 文法」などと検索すれば日本語での解説を探すことができるし、Altera自身もサンプルを公開している(英語なので読み解くのが手間かもしれないが)。 最後に今回紹介した回路全体のマッピングを示したのがこちら(Photo02)である。ラッチの数がかなりあるのは仕方ないが、それよりも異様に長いのは二重ループの上に LED制御をちょっと面倒な形でやっている部分もあるためである。次回はこのあたりにちょっと手をいれてみたい。

Photo01:緑色がラッチ、紫のものが論理回路 (加算器やセレクタなど )を示す。

Photo02:これは「Technology Map Viewer」というQuartus II標準のツールで、回路の割り当てが終わったあとの状況を示したものである。このままだとなんだかよく分からないが、拡大すると Photo01の様に細かく表示される。

FPGAでの LチカをVerilog HDLで理解する

16

MAX 10 FPGAで学ぶ FPGA開発入門(4)

FPGAのLED制御プログラムを深く理解するFPGA開発に必要な HDLへの理解を深めるため、MAX 10に用意されているArduino I/Oを利用しての Lチカを行い、多灯 LEDの制御を含めたプログラミングも解説する。

Arduino I/OでのLチカ

 前回(FPGAでの Lチカを Verilog HDLで理解する)では「MAX 10 FPGA」を利用した Lチカ動作を細かく紹介したので、もうちょっとここから先に進めてみたい。前回はオンボードの LEDを使って行ったが、今回からは Arduino I/Oを利用してみたい。 といってもそう難しい話ではない。連載の第 2回(「MAX 10 FPGA」のテスト環境を構築する)で「Design Template」に“Restore Factory Settings LED Flash”を使ったが、今回は“MAX 10 Evaluation Kit Baseline Desing”を選べばよい(Photo01)。これで適当な名前を選んでプロジェクトを作成する。

 作成後のテンプレートファイルはList 1※の様になっている。プログラムで利用できる I/Oの一覧が全部module宣言の中に含まれている「だけ」である。まずはオンボードの LEDの代わりに、Arduino互換の I/Oピンに LEDをさして、これを Lチカさせてみることにしたい。 ちょっとマニュアルが分かりにくいのだが、Arduinoは本来 4組のコネクタピンを持っている。このうちMAX10 Evaluation Boardが互換なのは 3組だけである。Photo02で言えば、右上の J3と左下の J4(の一部)、それと右下の J5が Arduino互換の信号が「一部」出ている。J3コネクタの場合、上が J3.1、下が J3.8となっており

 と規定されている。今回は J3.3(ARDUINO_IO13)とGNDに LEDをさして、これで Lチカをやってみた。

出力をArduino I/Oとしたプログラム プログラムそのものは前回利用した Lチカプログラムをそのまま流用して、List 2※の様にしてみた。修正点は「クロック信号の表記を clkからClockに変更」「出力をArduino_IO13のみにする」の 2点である。間違いがなければ、あっさり動作するハズだ(Movie01※)。 さて、この状態で点灯間隔はどの程度になるかをオシロスコープ

Photo01:この Design ExampleはQuatus IIに標準で用意されている

Photo02:赤枠で囲った部分が J3 Connector

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news003.html      ムービーはこちら → https://www.youtube.com/watch?v=ZG7MSXOv26o

17

でちょっと確認してみた。前回で説明した通り、On/Offの周期は厳密には65536×763=500173968サイクルとなる。クロックは50MHzなので、周期は 1.000348秒という事になる。 1周期の波形を見てみるとこんな感じ(Photo03)で、ほぼ 1秒っぽく見えるが、これは解像度不足というか、1周期分で判断するのは無理っぽい。そこで 150周期分を一気に表示してみたのが下の画像だ(Photo04)。150周期で 150.125秒ほどになり、1サイクルあたり1.0008333……秒となる。本来の周期より若干長

い理由は、1つはオシロスコープの精度の問題だが、もう 1つ別の理由もある。これは後述することにしたい。

正確に1秒間隔とするために

 若干長い理由はともかくとして、正確に 1秒にならないのは、そもそも正確に 50Mサイクルを数えるのではなく、65536×763サイクルを数えているためである。では正確に50Mサイクル数えたらどうなるか? というのが下の「List 3※」である。List 2と見比べてもらってもループの数が 1個減って分かりやすくなったと思う。 カウンタは 26bitになったが、これは 50,000,000まで数えるには 25.58bitが必要なためである。ただ List 2では div_cntr1が16bit、div_cntr2が 10bitで結局 26bit分を使っているので、実はここで差は無い。このやり方の場合、カウンターの周期をオシロスコープで見てみると 148周期で 147.962secほどになり(Photo05)、1周期の時間は 0.9997秒と 1秒を切ってしまったのだが、これはオシロスコープ側の精度の限界(カーソル機能の精度が足りない)であり、実際は 148secに非常に近いと思われる。 ただし、当然ながらその代償もある。Photo06はこのケースでの回路全体のマップをQuartus IIのツール「Technology Map Viewer」で表示したものだ。前回に比較すると、相当長くなっているのが分かる。 要するにカウンタのデコードが、前回のケースだと65536はシンプル

なデコーダ(16bitが全部 1になっていればいい)で済み、763のみ

Photo03:横軸は 200msecで、ほぼ 1秒ごとにOn/Offを繰り返している様に見える

Photo04:ここまで縮小すると、カーソルを 1ピクセル移動するだけで数十ミリ秒の変化になるので、精度はあまりよろしくない

Photo06:「無駄に長い構成」(筆者談)

こちらは前回の単純な Lチカ回路

Photo05:一応 147.962secということになっているが、有効数字は小数以下 1桁程度と思われる

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news003.html

18

“1011111011”のデコードが必要になるのでちょっと複雑、というものだったのが、今回は 50000000=“10111110101111000010000000”のデコードが必要になり、これによって回路が大規模化しているという訳だ。 リソースの比較をして見るとこれは分かりやすい。Photo07がもとの LED Flashにおける構成でのリソース利用率、Photo08がList 3でのリソース利用率で、ロジックエレメントを 5つほど余分に消費している。これが大問題か?といわれると、全体で 8064個もロジックエレメントがあるうちの 45個と 50個だから、大きな違いではないのだが。

7セグメントLEDの制御 さて、次にここからもう一歩進めて 7セグメント LEDの Lチカに話を進めてみたい。 7セグメントの LEDも、1桁でやる分にはただの Lチカの延長でしかない。面倒なのは 1個の LEDなら単にOn/Offで済むのが、7セグメントだと 7つ(実際には小数点まで含めると 8つ)の LEDのOn/Offを 10進数にあわせて切り替える必要があり、何かしらのテーブルを持たないと大変ということだ。加えて言えば配線も若

干面倒である(Photo09)。 さて、まずは回路図であるが、図 1の様な構造である。今回は手元に 2 桁の 7セグメント LED(Avago Technologiesの「HDSP-K211」)しかなかったので、この下一桁のみを利用している。このHDSP-K211の内部はPhoto10の様になっているが、問題は見てお分かりの通りアノードコモン(プラス極が共有)である。なので、13番ピンにまとめて電源を供給してやる必要がある。 ところがMAX10 Evaluation Boardの Arduinoピンには、実は電源が出ていない。先に互換の信号が「一部」出ていると書いたのはこの事で、例えばArduinoならJ2.3にあたるピンには3.3Vが出ているのだが、MAX10 Evaluation Boardにはこれが出ていない。 なので、どこかから 3.3Vの出力を取らないといけない。幸いな事にマニュアルによれば EP5388QI(オンボードの PMIC)の出力が TP6に出ている。これは本来は消費電力測定用のパッドなのだから、ここから 3.3V出力が問題なく取れるので、HDSP-K211の 13番ピンをここに接続。後は 5~ 12番のピンをそのまま J3.3~ J3.8と J5.1/5.2に割り振った形だ。 ソースは List 4※だ。以前との違いは、まず 0~ 9まで 10秒の

Photo07:まだまだゆとりはある

Photo08:ちょっとだけ無駄づかい

Photo09:ブレッドボードを利用して実装。黒い配線が 3.3Vラインへのもの

図 1 回路図

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news003.html

19

カウンタとなるので、dec_cntrを 4bitに増やした事。それと、新しく7bitの seg_cntrというレジスタを追加したが、これは 7セグメント LEDのそれぞれに対応する形だ。具体的な処理はソースを見てもらえれば分かる程度で、dec_cntrの値の 0~ 9にあわせてseg_cntrの値をbit単位で操作し、その結果をそのままArduino_IOに出力するだけである。 注意点はアノードコモン方式であること。5~ 12番ピンをHiにすると消灯、Loにすると点灯という負論理になっているので、これにあわせてseg_cntrに設定するあたりは本来の逆となっている。また小数点(HDSP-K211の 9番ピン)は 1秒おきに点滅ということにしたので、dec_cntrの LSBの値をそのまま assignしている。これを動かすと、Movie02の様にちゃんと動作するはずだ。 ということで 7セグメント LEDの 1桁駆動は比較的簡単だった

が、この桁数を増やそうとするとやや面倒である。桁数を増やすためにはダイナミック駆動をするのが一般的だが、アノードコモンでこれをやるにはちょっと回路に細工が必要である。 もう 1つの問題が処理の遅延である。Photo11はこの 7セグメント LEDの Technology Mapだが、Photo06と比べてもさらに回路が延びており、どうみても 1サイクルで処理が終わるようには思えない。実はこれ、全ての回路をシーケンシャルで動かしているのが問題で、この結果として、1秒毎に表示処理を行っている時は、何サイクルかクロックの割り込みを取り逃している。 冒頭で「本来の周期よりも若干長い」と書いたのはこれが理由である。解決は簡単で、クロック信号を数えて 1秒を割り出す部分と、そのあとの表示処理を分離すれば良い。次回はこのあたりを説明したい。

Photo11:「Technology Map Viewer」での表示。右端が急に複雑化しているのが分かる

FPGAの LED制御プログラムを深く理解する

20

MAX 10 FPGAで学ぶ FPGA開発入門(5)

よろしいならばダイナミック点灯だ――FPGAでLEDをダイナミックにLチカさせる単純な Lチカならば FPGAでもそう難しくない。ただ、ダイナミック点灯やそれに伴うソースの最適化については “ならでは ”のポイントが散見される。

 アルテラ「MAX 10 FPGA」を利用してFPGA開発の基礎を学ぶこの連載、前回(FPGAの LED制御プログラムを深く理解する)は Arduino I/Oを利用し、7セグメント LED1桁でのカウントアップを実装してみたが、今回はこれをもう少し展開してみたい。まずはダイナミック点灯への変更を行う。

 前回の配線図(Photo00)はアノードコモンをオンボードのPMIC 3.3V出力につなぐ形で、後はそれ以外のピンを制御する形で実装してみた。この方式の場合、LEDは常時点灯する形になる。1桁だけを表示するならこれでもいいのだが、桁数を増やそうとすると途端にピン数が足りなくなる。 利用した 7セグメント LED「HDSP-K211」の場合、点灯時は平均 37mWほど消費するので、全桁+小数点を表示させると約300mWほど消費する形になる。この状態で桁を増やすと、4桁なら最大で 1.2Wほど消費することになり、PMICの最大定格(連続出力最大 800mW)を超えてしまう(実際はその前にピンが足りなくなるが)。これは賢明とは言いにくい。

ダイナミック点灯を実現する回路とプログラム ということでダイナミック点灯である。これは要するに同時に発光する LEDは 1本に留めるが、発光させる LEDを高速に切り替える事で、あたかも同時に LEDが発光しているように見せかけるという手法。多桁の表示などではごく一般的に用いられている手法

である。 List 1※はこれを強引に実装してみたものだ。ちなみに配線も少し変更している(Photo00_1)。ダイナミック点灯の場合、一度に表示されている LEDは 1つだけなので、無理にPMICから電源を取らなくても、MAX 10の I/O pinの出力(最大 25mA)でもそれなりに明るく光る。このため、7セグメント LEDの 13番 pinを、J5.3(Arduinoの I/O 5番に相当)に切り替えている。

プログラム解説 さてプログラムだが、1msごとに点灯させる LEDを切り替える事にした(最初は 10msで組んでみたら遅すぎてちらつきが酷かったので 1msに減らした)。 まず div_cntr1で 5万回(= 1ms)のカウンタを作り、この中で 1000回の div_cntr2のカウンタを回す形で、毎秒 1000回のループを回している。その 1000回のループで、最初の 1回だけは表示すべき数字(dec_cntr)の更新と、その数字にあわせた 7セグメント LEDの点滅パターンの更新(seg_cntr)を行っており、残りの 999回はダイナミック点灯の更新を行っている。 ダイナミック点灯といっても難しい処理をしているわけではなく、7セグメント LEDは小数点を含めて 8つのセグメントを持つので、これにあわせて 8回の小ループ(pos_cntr)を内部で回し、そのたびに表示する LEDの場所(disp_cntr)を更新する形だ。表示しない場所はHi(1)にしている。

Photo00 前回の 7セグメント LED 配線図

Photo00_1 ダイナミック点灯に対応すべく配線も変更した

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news004.html

21

 実際にこれを起動すると、きちんと表示されるのが分かる(Movie01※)。良く見ると微妙に LEDの表示がチラついているが、これはダイナミック点灯の周期がちょっと長すぎるためで、もう少し周期を短くすれば解決する。

2桁のダイナミック点灯に挑戦 1桁がうまく行ったので、ではこれを 2桁にしてみよう。 今度は 0.1秒周期で 0.0~ 9.9秒まで順にカウントアップである。まず配線は図 2の様に変更した。ダイナミック点灯を利用したので、今度はアノードコモンにあたる13・14番ピンは本体のJ5.3とJ5.4の 2つに接続され、これを切り替える事でどちらの 7セグメントが点灯するかが切り替わる。一方、各セグメントにつなぐ配線は 2つの 7セグメントで共通という形だ(Photo02)。

 配線はそれでいいのだが、問題はプログラムの方である。以下のList 2※は List 1をさらに力技で拡張したものである。基本は同じなのだが、 ・ 表示すべき数字(dec_cntr)が 2桁(dec_cntr1, dec_cntr2)になり、これにあわせて処理も 2倍に

・ LEDの表示パターン(seg_cntr)も 2つに(seg_cntr1, seg_cntr2)に。

・ disp_cntrそのものは変わらないが、小ループが 8回から 16回に更新。これにあわせて、disp_cntrが seg_cntr1/seg_cntr2のどちらを反映するかで場合分けが必要になった結果、case文が長大に。

といった弊害が出ている。 他に変更点としてはリフレッシュ頻度が挙げられる。1桁だとダイナミック点灯は 1ms間隔の更新で間に合ったが、2桁になるとさすがに間に合わない。そこで更新頻度は 0.5msに高速化した。また、今度は 10分の 1秒単位での表示となるので、div_cntr2は 1秒ごとに 1回ではなく、0.1秒ごとに 1回カウントアップしている。

長大なリストをスマートにする で、動く動かないでいえばこれできちんと動いたのだが、もう少しスマートに記述したいところ。そこで List 2を Function文と条件演算子を使ってもう少し短くに書き換えたのが List 3※となる。 最初の Seg_DisplayというFunctionは、pos_cntrにあわせて seg_cntr1/seg_cntr2のどのセグメントを点灯するかを割り当てるもので、Functionの戻り値でこれを反映することになる。ちなみにここでは条件演算子を使うことで、長大な case文からは逃れられるようになった。 2つ目のMap_DisplayというFunctionは、表示したい数字にあわせて実際の LEDの点灯パターンを返すものだ。1桁だとわざわざ Functionにする必要はないのだが、複数桁ある場合は桁の数回分だけこれを繰り返す事になるので、ここを Functionでまとめた形だ。

オシロでタイミング測定 さて、これでプログラム的には動いたのだが、タイミング的にはどうだろう(普通はまず設計段階でタイミングを見るわけだが、あえて逆にまず実際の動作の状況を見ることにする)。 下の Photo03は LEDの 4・9番ピン(小数点)の信号をオシ

Photo02 配線はやや複雑化した。LEDの裏にも 1本配線を通している

図 2 2桁のダイナミック点灯を行う配線図

Photo03:ちなみにオシロスコープ本体の方で細かく情報を表示させると、信号がOffになっている期間は平均 0.496msということで、きっちり0.5msにはならない模様。とはいえ、ぎりぎりまで発光していることが分かる

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news004.html      ムービーはこちら → https://www.youtube.com/watch?v=pWcXy8u6eSc

22

ロスコープで見てみたところ。トリガーは信号の立下りである(アノードコモンなので、Levelが 0になると LEDが電流に流れるため)。右下にあるように、Periodは 4.000msとなっている。8つのセグメントを 4.000msごとに更新するということは、1つのセグメントあたり0.500msごとに更新しているということで、これはプログラム通りの結果になっていることが分かる。 この工作程度だと「これでOK、万々歳」ということになるのだが、複雑なロジックを組んでいると、そもそも「全部作ってから動かしてみる」のではなく、部分的に作りこんで動作を確認してから

次の部分に、という作り方をするのが一般的である。また、今回は最終的に外部に出てきている信号で成否を判断したが、内部ロジックの検証などでは外部の信号が使えない場合も珍しくない。 こうした場合に利用できるのがシミュレーションである。幸いに

Photo06 rtl_workの下の "top"(これはプロジェクトによって名前が違う。今回筆者は起動するmodule名を "top"のままにしたからこの名前になる)をダブルクリックする

Photo04 利用しているVersion 15.0の場合、Tools → Run Simulation Tool → RTL Simulationで起動できる。

Photo05 一番左が用意されているさまざまモデリングツール。今作業している内容は上から 2つ目の "rtl_work"に含まれている。

Photo08 Clock信号を右クリック→ "Clock..."を選択

Photo09 この状態だと周期 100cycle(=100ps=10GHz)での動作になるので、Periodを 20000(=50MHz)に指定する

Photo07 Objectsから表示させたい信号を選んで右クリック→ "Add Wave"である

23

もQuartus IIには無償版ながらシミュレーションツールが利用可能である。起動するとこんな画面になるので(Photo04、05)、作業中のプロジェクトを選ぶと、実際にデザインの中身が見える(Photo06)。今回はClock信号とArduino_IO4~ 13を表示させてみる(Photo07)。ただこの状態だと /top/ClockがHi-Z状態で進まないので、ここにClock信号を入力する(Photo08、09)。 ついでにメニューから「Simulate」→「Runtime Option」を選んで、1回に実行される時間を 100psから 100msまで増やしておく。これが終わったら、メニューの「Simulate」 → 「Run」 → 「Run 100」を選ぶと、Waveがこんな風になるはずだ(Photo10)。 このままだとちょっと見にくいので、上の縮小ボタンなどを使って、先頭から 2msほどを表示させたのがこちら(Photo11)。カーソルの位置からも分かる通り、キチンと 0.5msごとに出力信号が変化していることが分かる。今回は省くが内部レジスタやWireの値などを同様に表示することも可能であり、シミュレーション上も正しく動作することが検証された形だ。 次回はちょっと別のことをご紹介したい。

Photo10 真ん中の "Default Run"が標準だと 100psなのでここを書き換える

Photo11 最初の 0.5msに信号が表示されないのは、disp_cntlに値を初めて設定するのが最初の 0.5ms目だからで、それまでは Hi-Z扱いになる。本当はちゃんと初期化していればいいのだが

よろしいならばダイナミック点灯だ

24

MAX 10 FPGAで学ぶ FPGA開発入門(6)

FPGA上でソフトコアCPUを動かす手引きこれまで FPGAの開発基礎として Lチカなどを紹介してきたが、今回はちょっと目先を変えて FPGA上での CPUコア動作に取り組む。

 アルテラの開発ボード「MAX 10 FPGA」を利用して FPGA開発の基礎を学ぶこの連載、これまでには Lチカやダイナミック点灯などを紹介してきたが、今回はちょっと目先を変えて、FPGAの上で CPUコアを動かしてみたいと思う。 アルテラのFPGAには同社より「NIOS II」と呼ばれるソフト IPコア(FPGAのゲートを利用して動作する 32bit CPU)が提供されており、これを利用すると外部にMCUなどを用意しなくても、C/C++のプログラムを実行させることができる。もちろん、これはMAX 10でも利用可能である。 さて、こちらについてもさまざまなサンプルプログラムが用意されている。一番シンプルなのは「Nios II + Qsys "Hello World" Lab」だが、あいにくこのサンプルは「MAX 10 Development Board」向けなのでそのままでは使えない。MAX 10 Evaluation Boardで動作する Nios IIの一番簡単なものは、「Nios II On-die Temperature Sensor Design Example 2」なので、これを使ってみることにしたい。

インストールパッケージの入手と展開 最初のステップは、Installation Packageのダウンロードである。こちらページの中ほどにある「Download」をクリックして、「evalkit_temp_sensor_console.par」ファイルをダウンロードしておく(Photo01)。 これが終わったらQuartus IIを起動して、「File」→「New Project Wizard」を選択し、まずは適当な名前で新規プロジェクトを作る(Photo02)。次にProject Typeは「Project Template」を選び(Photo03)、Template一覧から「Nios II On-dir Temperature Sensor」を選択する(Photo04)。 最初、この選択肢は出てこないハズである。ここで一覧の下にある「Install the design template」をクリックし、先ほどダウンロードした「evalkit_temp_sensor_console.par」を指定すると、

一覧に出現して選択できる。選択して「Next」を押すとサマリーが出てくる(Photo05)ので、「Finish」を押すとウィザードは完了である。

 さてQuartus IIに戻るとこんなメッセージが出ているはずだ(Photo06)。左上のファイル一覧を見ると、platform/nios_setup/simulation/nios_setup.sipとplatform/nios_setup/synthesis/nios_setup.qipの 2つが確認できるはずだが、この時点でそのファイルは存在していない。これは後で生成されるのだが、生成さ

Photo01:ダウンロードするファイルはQuartus IIのバージョン(15.0.0か 15.1.0)で異なるので、自分の利用しているQuartus IIのバージョンにあわせた方をダウンロードする必要がある

アルテラの開発ボード「MAX 10 FPGA」

Photo02:名前は自分が分かればなんでもいい

25

Photo06:画面下のステータス表示に注目。nios_setup.sip/nios_setup.qipが無いと表示されている

Photo07:ファイル名を右クリックしてコンテクストメニューで "Remove File from Project"を選ぶと削除できる

Photo03:Empty Projectを選ぶとちょっと後が大変

Photo04:"Nios II On-dir Temperature Sensor"が 2つあるのは、最初間違ってQuartus II 15.1.0をインストールしてしまったから(Software Versionの欄を見ると分かる)

れる場所は異なるので、取りあえずこのファイルは削除しておく(Photo07)。

Photo05:実際はこの画面から、Quartus IIに戻るまでの間、いろいろなファイルのビルドが行われるのでちょっと時間がかかる

Nios IIの組み込み さて、それでは実際にNios IIの組み込みである。これを行うのはQsysというユーティリティーなので「Tools」メニューから起動する(Photo08)。 Qsysが起動すると、まずは設定ファイルの指定になる(Photo09)。ここで指定するものだが、先に TemplateからProjectを生成した際に nios_setup.qsysというファイルが生成されているのでこれを指定すると、しばらく処理を行った後、最終的にこんな情報を示して(Photo10)Qsysが立ち上がる(Photo11)。

26

Photo08:スタートメニューからも呼び出せる

Photo14:削除はファイル一覧からできるが、追加が出来ないあたりがちょっと使いにくさを感じる

Photo13:今回はシミュレーションモデルは生成していないので、実際には .sipの方は作成されていない

Photo12:確認ダイアログ

Photo11:この画面で、IPの形で提供される回路ブロックを追加 /削除したり、構成を変更したりといった事も可能

Photo10:もともとのQsysのファイルは全てQuartus 14.1ベースで生成されたようで、必要な IPが全て 15.0にUpdateされた事がここで示される

Photo09:ここで取り消しを押して真っ更な状態から構築もできるが、面倒なので既存の設定を読み込む

 この画面を注意深く見てもらうと分かるが、一番上がクロックモジュール、次がNios IIのコア、その下がオンチップの SRAM、という具合にモジュールが並び、さらにモジュール間でどの信号がどこに接続されるかがここで指定される。 他にもアドレスマップや割り込みなども全部ここで設定されので、いろいろ設定を変えてみてもいいのだが、今のところは特に変更をせずに、右下の「Generate HD」ボタンを押すと、こんな確認が出る(Photo12)ので「Generate」を押す。しばらく処理が行われた後に、最終的にこんなダイアログが出てくる(Photo13)はずだ。これで、先に行方不明だった nios_setup.qipファイルが生成された事になる。

27

Photo17:左下のウィンドウにWarningがいろいろ出ているが、取りあえず無視して構わない

Photo18:初回はこの後 "Auto Detect"を押してUSB Blasterを認識させる必要がある

Photo19:生成したイメージは output_�lesフォルダに生成されている。ちなみに .sofは RAMに書き込むイメージ、.pofはフラッシュメモリに書き込むイメージだが、今回は RAMに直接書き込みということで .sofの方を選択する

Photo16:一番上に nios_setup.qipが追加されているのが分かる

Photo15:ちなみに標準だと右下にあるファイル名のフィルターが "Design Files"(.tdf/.vhd/.v/...)になっているので、ここを "IP Variation Files"に切り替えないと見つからない

 これでQsysの設定は完了。再びQuartus IIに戻る。 まずは生成された nios_setup.qipをプロジェクトに追加してやる必要がある。これは「Project」→「Add/Remove Files in Project..."で nios_setup.qipを指定してやると(Photo15)、ファイル一覧に追加されたのが確認できる(Photo16)。

 以上で、Quartus II側の作業は(おおむね)終了である。後は「Processing」→「Start Compilation」を選んで、FPGA側の全コンパイルをかける。問題がなければ正常にコンパイルが完了した旨が表示されるので(Photo17)、「Tool」→「Programmer」で Programmerを起動し(Photo18)、「Add File...」で作成した sofファイルを指定して(Photo19)から「Start」ボタンを押す。手順を間違えてなければ、無事に完了するはずだ(Photo20)。

Nios IIで動作するプログラムの記述 さて、ここまでの作業でMAX 10上にて動作するプロセッサが構築され、さらにメモリとADC(A/D Converter)、GPIOがこのプロセッサから利用可能な状態になっている。ただし、プログラムを何も書き込んでいないので、この時点ではまだ何も動かない。

28

そこでここからはNios II上で動作するプログラムを記述し、Nios IIにロードしてやる必要がある。 まずQuartus IIの「Tool」→「Nios II Software Build Tools for Eclipse」を選択し、Eclipseを立ち上げる(Photo21)。この Eclipseで「New」→「Nios II Application and BSP from Template」を選択して Templateファイルの選択画面を表示させる(Photo22)。

Photo20:書き込みが終了すると右上の Progress Barが緑で示される

Photo21:初回はこんな具合にブランクだが、基本的には直前の作業状態を記憶しているので、次回からは直前の状況から再開できる。正直なトコロ、このバージョンはちょくちょくEclipseそのものが落ちるのだが、再起動すると直前の状況から作業を再開できるので大きなハンディにはならないだろう(ただし Saveは小まめに)。

Photo24:TempSensorはプログラムそのもの、TempSensor_bspは BSP(Board Support Package)で、要するにランタイムである

Photo23:Hello Worldを選ばない理由は、printf()を含む Cのライブラリが結構メモリを専有する(40KB以上)ので、SRAMを大容量に設定しないと、そもそも動作しないため

Photo22:簡単なプログラムのテンプレートも用意されている

 この画面で ・ SOPC Information File name:プロジェクトディレクトリのトップに、nios_setup.sopcinfoというファイルが生成されているので、これを指定する

・ CPU name: nios_gen_2_0(自動的にこれが選択される ) ・ Project name:適当に自分でつける ・ Project template:"Hello World Small"を選択と作業する。 完了すると、こんな具合になるはずだ(Photo23)。

 設定が終わったら右下の「Finish」ボタンを押すとしばらくの後、今回の例なら「TempSensor」と「TempSensor_bsp」の 2つのプロジェクトが自動生成されている(Photo24)。ここでいきなりビルドをする前に、設定が 1つ必要である。

29

 左ペインのプロジェクト名(TempSensor)を右クリックし、プロパティを表示させる(Photo25)。ここで「Nios II Application Properties」を選ぶと、標準ではOptimization levelが「Size」になっているので、これを「Off」にする(Photo26)。同様に、TempSensor_bspの方もやはりOptimization levelを「Off」にする。

 次はソフトウェアの設定である。Project Templateは「Hello world small」を選んだので自動的に "hello_world_small.c"が生成される(Photo27)。このままだと「Hello from Nios II!」と表示して終わってしまうのだが、これを置き換えるソースコード(ondie_temp.c)が softwareフォルダの中に用意されている(List 1※)。これをエディタなどで開き、コピーして hello_world_small.cにペーストする形でプログラムを入れ替える(Photo28)。

いよいよビルドへ これが終わったら、左ペインのProject ExplolerのTempSensor

を右クリックして、コンテクストメニューから「Build Project」を選択するとプログラムのビルドが始まる。問題なければ数十秒で終了する(Photo29)はずで、これにてプログラムの開発は完了である。 最後に、プログラムをNios IIにロードする作業である。まずEclipseの「Run」→「Run Configuration」を選び、Project名に「TempSensor」を選ぶ(Photo30)。次にTarget Connectionタブを開く(Photo31)と、USB-Blasterが見えているはずだ。 ここで「System ID checks」にある「Ignore mismatched system ID」と「Ignore mismatched system timestamp」の両方にチェックを入れると、「Target Connection」タブの赤い ×印が消える(Photo32)。これを確認して、まず右下の「Apply」ボタンを押した後で、さらに右下の「Run」ボタンを押すと、USB-

Photo25:これは最適化の設定のためであるが、なぜか最適化オプションは "Nios II Application Properties"に用意されている

Photo28:ondie_temp.cをファイルとして追加する方法も何度か試したのだが上手くいかなかった

Photo27:何というか、説明の必要はまぁないだろう

Photo26:この目的はAlteraによれば "compiler optimization may cause some problems while running the program."との事。

Photo29:経過時間は利用するマシンによって当然変わる

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news005.html

30

Blaster経由でNios IIの SRAMにプログラムがロードされ、すぐにNios IIが実行を開始する。ちなみにSTDOUTに相当するものは、USB-Blaster経由のNios II Consoleになり、ここにメッセージが表示される仕組みだ(Photo33)。 さて、本当ならこのサンプルは 1秒おきに温度を表示する他、基板上のディップスイッチにあわせて基板のLEDのOn/Offが操作可能な「はず」なのだが、実は上手く動かない。調べてみたところ、デバイスから本来入るべき割り込みが上手く拾えておらず、割り込

Photo31:もしUSB-Blasterが一覧にない場合、右の Refresh Connectionsを押して再検索する

Photo30:Project名を選ぶと自動的に Elf �le nameも選択される Photo32:「Target Connection」タブの赤い×印が消えている。Photo31に比較してもらうと分かりやすい

Photo33:これで動作した

み待ちのままずーっと無限ループに陥っている模様だ。 なんとなく、Photo10にあるように IPの形で提供されるデバイスが 14.1→ 15にVersion upされた際に何か仕様が変わっており、それを上手くフォローアップできていない感じがする。ただ逆にADCからの温度測定やDIPスイッチの設定取り込み /LEDの表示などを省くとちゃんと動作しているので、Nios IIそのものが正しく動作している事は間違いないようだ。次回はこのあたりを来月はもう少し追及してみたいと思う。

FPGA上でソフトコアCPUを動かす手引き

31

MAX 10 FPGAで学ぶ FPGA開発入門(7)

FPGA上でソフトコアCPUを動かす手引きこれまで FPGAの開発基礎として Lチカなどを紹介してきたが、今回はちょっと目先を変えて FPGA上での CPUコア動作に取り組む。

 この連載ではアルテラの開発ボード「MAX 10 FPGA」を用いた FPGA開発を紹介しているが、今回は「FPGA上でソフトコアCPUを動かす手引き」の続きである。 FPGA上で「NIOS II」と呼ばれるソフト IPコアを利用し、サンプルプログラム「Nios II On-die Temperature Sensor Design Example 2」をビルドして動かすまでを紹介したのだが、実はうまく動かなかった。このサンプルプログラムは 1秒おきに温度を表示する他、基板上のディップスイッチにあわせて基板の LEDのOn/Offが操作可能な「はず」だったのだ。 前回の最後で「IPの形で提供されるデバイスが 14.1→ 15にVersion upされた際に何か仕様が変わっており、それを上手くフォローアップできていない感じがする」と書いたが、その後にアレコレ試行錯誤した結果、どうも当たりだったらしい。 しばらくの間「Quartus II 15.0」と格闘したものの状況は変わらず。その後、「Quartus Prime 15.1 Lite Edition」にバージョンアップしても状況が変わらなかった。 そこで試しに「Quartus II Web Edition 14.1」を入手してインストール、アップデートをかけて(これもアップデータは同じURLから入手できる)Version 14.1.1.190となったQuartus IIで前回

と同じ手順で行ったところ、あっさり動作してしまったからだ(Photo01)。温度表示だけではなく、スイッチを参照しての LEDの点灯もきちんと動作した(Movie01※)。ということで、やっと前回の目的が実現された形だ。 ちなみに似たような現象に陥っている人は他にも見かけたが(Altera Forum:nios-i i-on-die-temperature-sensor example)、決定的な解決策は特に見つかっていない模様。「俺は15.0で動作した」という人も居るので、原因は完全につかみきれないのだが。 スクラッチから作る場合はともかく、既存のデザインファイルをベースにいろいろ遊んでみる場合、こと「Nios II On-die Temperature Sensor Design Example」に関しては古いバージョンのQuartus IIを利用するのが無難そうである。 余談であるが、Quartus II/Quatus Primeは複数バージョンを混在してインストールできる。インストールディレクトリさえ分けていれば別に問題はない。ということで現在筆者の環境には 3種類(Quartus II 14.1/15.0、Quartus Prime 15.1)が混在している状況である。

NIOS IIの処理能力をベンチマークで測定する ということで無難にNIOS IIが利用可能になったところで、もう少し遊んでみることにする。取りあえず知りたいのは「NIOS IIがどの程度の処理性能を持つか」である。こういう場合、何かしらのベンチマークを走らせてみるのが一番手っ取り早い。ということで、Dhrystoneを走らせてみた。 Dhrystoneそのものはいまさら説明は要らないと思うが、非常に古くから使われている整数演算用ベンチマークである。幸いな事に、現在でもベンチマークは探せば入手できる(ここなど)ので、まずは入手して適当に展開しよう。必要なファイルは dhry.h(ヘッダファイル)、dhry_1.c(メインルーティン)、dhry_2.c(サブルーティン)の 3つである。 さて、まずハードウェア(つまりQuartus IIで直接記述する方)はそのままにして、まずはソフトウェアだけ入れ替えてみる。まずはここと同じ手順で、別の名前で新しいプロジェクトを立ち上げる(Photo02)。 次に、Project Explolerのウィンドウに、先ほどダウンロードした dhry.hと drhy_2.cをドラッグアンドドロップで投入する。すると「コピーかリンクか」を聞いてくる(Photo03)ので、どちらか

Photo01:下の NIOS II Consoleを参照。ちゃんと温度が順次、表示されているのが分かる

アルテラの開発ボード「MAX 10 FPGA」

※このページのムービーはこちら → https://www.youtube.com/watch?v=fEwWo_a6hko

32

好きなほうを選択(筆者はコピーを選んだ)すると、Project Explolerにこれが追加される(Photo04)。ちなみに dhry_1.cであるが、こちらは中身をコピーして、自動生成される hello_world_small.cにそのまま貼り付けた。 さて、これをコンパイル……してもさすがにそのままでは通らない。そこで、最低限の変更をする。変更は dhry_1.c(の中身をコピーした hello_world_small.c)だけである。List 1※がオリジナルの dhry_1.cであるが

・ 経過時間の計算やDhrystoneスコア計算のために float型を使っている

・ 何回ループを回すかをSTDINから入力する ・ 出力結果をファイルに出力するといったコードが入っており、このあたりはテストをするのに不要なのでまるまる削除した。ちなみにループ回数は

/* printf ("Please give the number of runs through the benchmark: ");

{ int n; scanf ("%d", &n); Number_Of_Runs = n; } printf ("\n"); printf ("Execution starts, %d runs through Dhrystone\n",Number_Of_Runs);*/ Number_Of_Runs = 100000;

 という具合に 10万回の決め打ちにしている。性能を比較するだけだからこれで十分であろうという判断だ。 もう 1つの変更は時間測定である。もともとのコードでは、ベンチマーク開始直前と終了直後にclock()という関数で現在のシステム時間をmsec単位で取得してここから性能を測定しているが、NIOS IIの環境ではこれが利用できない。そこで代わりにNIOS IIのHAL APIの Timestamp機能を利用した。 具体的にはまず alt_timestamp_start()を呼んで初期化した後、ベンチマークの前後でalt_timestamp()を呼び出してタイムスタンプ値を取得、後でこれを引き算して経過時間を取得して表示する形にした。ちなみにこのalt_timestamp_start()やalt_timestamp()を利用するためには、冒頭に

#include "sys/alt_timestamp.h"#include "alt_types.h"

 を追加する必要があり、また alt_timestamp()の戻り値は alt_u32型なので、これにあわせて変数宣言を変更している。List 2※

Photo02:名前は自分が分かればなんでもいい

Photo03:「コピーかリンクか」を選ぶ。「Link to �le」を選ぶと、現在展開した場所から読み込むことになりちょっと不便なので、プロジェクトディレクトリにコピーするほうを選んだ

Photo04:よく見るとdhry21a.c(上の説明で言うところの dhry_1.c)も入っているが、これは後で外して hello_world_small.cに上書きの形にした

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news006.html

33

がこれらの変更を行ったソースコードである。

ビルドしてDhrystoneを実行 さて、これをビルドして実行であるが、Run Configurationの前に実行するプロジェクトをキチンと切り替えておくことを忘れずに(Photo05)。切り替えて実行したところ、見事にDhrystoneが完走した(Photo06)。 ただ、走った事はいいのだが、肝心の時間測定ができていない。実は alt_timestamp()はシステム・クロック(の Timestamp Timer)が利用できないと戻り値が 0になる仕様なので、これの対応を追加してやる必要がある。 ということで、再びQSYSに戻る。QSYSは現状この状態になっていて、よく見ると「one_sec_timer」なる Interval Timerが既に存在しているのだが、こちらは 1秒単位での測定しかしないものなので、もう少し細かい精度がほしい。 そこで左上からProcessors and Peripherals → Peripherals→ Interval Timer と選び、もう1つ Interval Timerを追加した(Photo06)。こちらは右ペインにあるように、Periodを1μsとしたの

で、かなり細かく数字が取れるはずだ。 ちなみに配線として clk/reset/s1/irqの各配線は one_sec_timerと同じようにつないでおく。以上が完了したら右下の「Generate HDL」ボタンを押して設定ファイルを生成、ついでQuartus IIの画面に戻ってビルドをやり直し、最後にProgrammerを使ってMAX 10に書き込むところまでを繰り返す。

ソフトウェアを対応させる 次はソフトウェア側の対応である。ここでは追加した「sys_clk_timer」をシステムタイマーとして利用する事を教えてやらなければいけない。 Eclipseの画面で「NIOS II」→「BSP Editor」を呼び出し(Photo08)、「Dhrystone_bsp」の下にある settings.bspを読み込むと、「timestamp_timer」の値が「none」になっているはずなので(Photo09)、これを「sys_clk_timer」とする。これが終わったら右下のGenerateボタンを押してBSPを生成し直す。 次にこれをプロジェクトに反映する。Eclipseで BSP側を右クリックし、「NIOS II」→「Generate BSP」を選択した後にビルドしなおすと、今度はシステムクロックがちゃんと存在する状態でプログラムが構築される。そこで実行するとPhoto12の様に、キチンと所要時間が表示されるようになった。 さて、この所要時間は、実際には Tics(何 Clock経過したか)な

Photo05:プロジェクト切り替えを忘れると、Dhrystoneを走らせるハズが、延々と温度を表示し続ける

Phoot06:この表示は「正しくDhrystoneが実際されたか」を確認するもので、結果は全て正しいことが分かる。問題は Elapsedが 0な事だけだ

Photo08:ディレクトリはプロジェクト名がDhrystoneの場合にはプロジェクトディレクトリの下の "software\Dhrystone_bsp"の下になる

Photo07:Interval Timerを追加。名前は後で右クリック→ "rename"で変更できる

34

Photo12:これが出てきたときには思わず安堵(あんど)のため息が (笑 )

Photo09:ちなみに今回は timestamp系の HAL APIを使ったので timestamp_timerを有効にしたが、逆に sys_clk_timer系の APIを使いたければこちらを有効にする

ので、実際には 50MHz駆動で 8億 5300万 173clockということで、17.06秒ほどの時間となる。10万回で 17.06秒なので性能は大体 5861.7 Dhrystone/secという数値になる。基準となるVAX11/780のスコア(1757.0 Dhrystone/sec)と比較すると3.34 DMIPSという計算である。 これが速いか遅いかはどう使うか次第ではあるが、こちらのページに記載されている値に比べると、MAXQよりやや遅い程度で Texas InstrumentsのMSP430F149よりは高速、というのはそう悪くないのではと思う。 ちなみにQSYSでプロセッサの設定を見ていただく(Photo13~ 15)と分かるのだが、今回はリソース最適化でプロセッサを構成しているので、このあたりを変更すればもっと性能は上がる可能

Photo13:CPUコアを「Nios II/e」にするとリソース最適モードとなり余分なオプションは一切使えず性能も低い。これを「Nios II/f」にするといろいろなオプションが使えるようになる

Photo14:「Nios II/f」にすると、ここでキャッシュの有無やサイズなどを選べるようになる

Photo15:乗除算性能が必要な場合はNios II/fではこれらをハードウェアで実行させることも可能。デフォルトはソフトウェアエミュレーションなので遅い

性がある。興味のある方はぜひ、いろいろと設定を変えてみていただきたい。 ということでプロセッサが実用に耐えることが分かったので、次はもう少しデバイスと組み合わせてみたい。

FPGAのソフトコアCPUをベンチマークで測定する

35

MAX 10 FPGAで学ぶ FPGA開発入門(8)

周辺機器の充実した「MAX 10 NEEK」で本格的な開発を目指すこれまで FPGAの開発基礎として Lチカなどを紹介してきたが、今回はちょっと目先を変えて FPGA上での CPUコア動作に取り組む。

 アルテラの開発ボード「MAX 10 FPGA」でソフトコアCPUを構築し、ベンチマークの Dhrystoneも動いた。ではいよいよCPUとFPGAに周辺回路を組み合わせて、I/Oのハンドリングを試してみる事にしよう……と思っていた矢先、アルテラから「よければMAX 10 NEEKを使ってみませんか?」という申し出を頂いた。 この「MAX 10 NEEK」は台湾 Terasicが製造し、アルテラも販売するMAX 10評価ボードの 1つだが、なにしろ周辺回路がてんこ盛りなのが特徴。5タッチセンサー付き LCDモニター(800×480Pixel)、カメラ、オーディオ入出力、温度/湿度/照度/加速度センサー、パワーモニター、ADC入力/ DAC出力、スイッチ/ポテンショメータ/ LED/ 7セグ LEDなど搭載されており、DDR3メモリ(合計 256KB)、512Mbit Flash、MicroSDカードなども搭載されている。おまけにギガビットイーサネットやUART to USB、PS/2キーボード・マウスなどのインタフェース、更にTMD(Terasic Mini Digital)拡張コネクタも用意され、USB Blaster IIまで実装されているから、本当にUSBケーブルをつなぐだけで開発が行えるという優れものである。 難点はお値段で、Terasicの直販では $359、販売代理店経由だと、例えばMOUSER Electronicsだと \47,185.9と表示されている。昨今の円高を考えるとUSDで決済したほうが多分安いとは思うのだが、それにしても $359はちょっとお高めということで当初は見送った開発キットである。 ただし念のために言っておけば、これまで使ってきた「MAX 10 Evaluation Kit」は本当にMAX 10に習熟するためのトレーニングキットであって、これを本格的な開発に使うのはちょっと無理がある。一方、MAX 10 NEEKはもう製品開発を指向したものであって、最終製品に近いレベルのプロトタイプまで作れる。これが$359というのは相場で考えてもかなりお安い部類に入る。まぁそうは言っても遊びで入手するのにはちょっと、二の足を踏んでいたのだが、使わせて頂けるならこれ幸いと 1台手配していただいた。

「MAX 10 NEEK」

 さてMAX 10 NEEKはちょっと大きめの箱で届いた(Photo01)。内部はMAX 10 NEEK本体と付属品のみであり、ソフトウェア類はTerasicのサイトからダウンロードする形になっている(Photo02)。LCDの裏には基板が実装されている(Photo03)が、細かなチップの説明はMAX 10 NEEKの紹介ページ写真に詳しいので割愛する。

Photo02:さすがにUSB給電では足りないようで、5V/3A出力の ACアダプターが付属する。他にUSB Blaster IIと接続用の USBケーブル、Quick Stard Guide、それとここには見えていない(NEEK本体に既に装着されている)MicroSDカードが付属する

Photo03:基板を写真と比べると、若干の仕様変更(MIPI I/Fの端子がなくなり、LCDコネクタ下の穴のサイズが小さくなり、Lineae Technologyのロゴが入った)が見られる。アクリルカバー付き

Photo01:「MAX 10 NEEK」のパッケージ。パッケージサイズは 285mm×186mm×88mm(実測値)とやや大きめ

36

Photo07:「Painter」の画面。ちょっとタッチ感度がよすぎて、タッチ前に検出されることもあった

Photo04:まず画面全体がホワイトアウトして、しばらくしてからこの画面になる。MicroSD経由ということもあり、処理はややゆっくり

充実のビルドインプログラム さて、まずはビルドインのソフトウェア(アプリケーション)を簡単にご紹介したい。添付のMicroSDカードをスロットに装着した上でACアダプターをつなぎ、電源をONにする(Photo03で左上の赤いボタンを押す)と、スタートアップ画面(Photo04)の後でメニューが出てくる(Photo05、06)。

 ソフトは「painter」「spider」「camera」「g_sensor」「hdmi_rx」「humidility_temperature」「mic_adc」と用意されている。 ・ Painter(Photo07):マルチタッチスクリーンの動作サンプル。最大 5本までのタッチを検出して、それぞれ別の色でペイントする。

・ Spider(Photo08):Terasicがリリースしているクモ型の多脚ロボット「Treasic Spider Robot」のコントローラーとなる機能。ちなみにこれを利用するためには別売りとなる「Terasic BTS-TMD Bluetooth Adapter」を併用する必要がある。

・ camera(Photo09):フロントカメラの映像を画面に出力するだけの機能。ちなみに画面をタッチすると、そこを中心にフォーカスを合わせる機能(Photo10)も用意されている

Photo05:メニュー(1) 実は 2.の Spiderはマニュアルには記載されていなかったりする

Photo08:Bluetooth Adapterはちゃんと技適を通っているので国内でも利用可能。お値段は Terasicのサイトで 50$だそうである。ちなみに Spider Robotは $1200

Photo06:メニュー(2) 指で選んでから、左下の Loadボタンを押すとそれぞれスタートする。ちなみにそれぞれを起動した後で再びメニューに戻る方法は無いので、電源Off→電源Onで戻る

37

MAX 10 NEEKから操縦できる、クモ型の多脚ロボット「Treasic Spider Robot」

Photo09:あくまでカメラのデモなので、撮影して保存とかの機能は(もちろん)ない

Photo10:指で触ると、そこを中心にフォーカスを定める感じ

・ g_sensor(Photo11):加速度センサーと照度センサーのデモ。 ・ hdmi_rx(Photo12):HDMI入力のデモ。ちなみに画面だけでなく、HDMI経由の音声をデコードして出力する機能もある。

・ humidility_temperature(Photo13):温度 /湿度センサーのデモ

Photo11:これは斜めにした状態なので、上下方向が 24°と示されている。Brigthnessは表面と裏面のそれぞれの数値

・ mic_adc(Movie1※):ADCのデモ。マイクから入力した音声をADC経由で取り込んで、そのまま表示する。ちなみに映像の音源にはMisuc-Notes.jpのファンタジー系 BGM素材から「ルービックキューブ」を利用させていただいた。

Photo12:手近にHDMI出力できるプレーヤーがなかったので、取りあえず PCにつないで BIOS Setup画面を出してみた

Photo13:温度が異様に高いのは、NEEKボードを連続稼働させた結果ボード全体の温度が上がっているためで、室温ではない

※このページのムービーはこちら → https://www.youtube.com/watch?v=cXzQlqS-sUI

38

Photo17:ピンの名前とピン番号、入出力、信号レベルが一覧で示されるPhoto15:デフォルト状態ではこれだけ利用可能。「Ethernet」とか「DDR3」もおいおい試してみたいと思う

Photo14:ダウンロードには無料のユーザー登録が必要。筆者の場合、以前 TerasicからUSB Blasterを購入した際に登録済であるが、まだの人はダウンロードを選ぶと飛ばされるMemberページで “Join Now” を選んで登録してからダウンロードを行う形になる

MAX 10 NEEKでの開発

 デモで遊んでいても面白みは無いので、実際に簡単にいじるための方法を説明する。まず TerasicのサイトのMAX 10 NEEKの“Resource”ページに移動する。ここでMAX 10 NEEK CD-ROMをダウンロードする(Photo14)。今回入手したのは、執筆時点で最新版となる v1.0.7である。

 これをダウンロード後、適当なディレクトリに解凍する。このディレクトリの中の Tool \ SystemBuilderというフォルダの中に、MAX 10 NEEK専用のSystem Builderが含まれている。これを起動すると、MAX 10 NEEKのどの機能を利用したいかを選べる(Photo15)。 取りあえずは Lチカということで、Clockと 10個の LEDのみ有効にして、これをNEEK_LEDというプロジェクト名で生成することにする(Photo16)。プロジェクト名と必要な項目を選んで"Generate"ボタンを押すと、指定のディレクトリに以下の 5つのファイルが生成される。

 このうち htmはこんな感じ(Photo17)でビジュアル的な要素は少なく、必要な情報が一覧で示されるだけである。 これが生成されたら、この 5つのファイルを適当なフォルダに移動(今回は "C:\altera\15.1\Projects\NEEK_LED"というフォルダを作り、その下に移動した)してからQuartus IIを起動するわけだが、その前にMAX 10 NEEKの接続である。 Photo03で言えば左上、PS/2ポートの左にMini USBのコネクタがあるが、これがUSB Blasterとの接続用である。ここにUSBケーブルを装着し、PCと接続してからMAX 10 NEEKの電源スイッチをOnにする。ドライバはQuartus IIのインストール時、システムに入っているので自動認識されるはずだ。

39

「MAX 10 NEEK」のプログラミング

 ではサンプルコードを書いてみる。今回は「Quartus Prime 15.1 Lite」を使ってみた。まずはOpen Projectを選び、先ほど格納した(今回ならNEEK_LED.qpfを指定する、Photo19)。するとNEEK_LED.vが開かれるが、この状態では下の List 1※に示すように、中身は空っぽである。今回は、0.1秒間隔で LEDを順に光らせる、ということでこれを List 2※の様に書き換えてみた。書き換えたのは、REG/WIRE declarationsとStructural codingのみだ。

 おおむね昔の Lチカに近いが、一応意図を説明しておけば、外部からは 50MHzでクロックが入ってくるので、これを 50万回(つまり5M回)ごとにカウントし、内部の dec_cntrというレジスタ

Photo19:ここで Project Wizardを起動して新規にプロジェクトを生成すると、ピン配置とかを全部手動で設定せねばならないので結構面倒である

Photo20:搭載されるMAX 10は 10M50DAF484ESで、MAX 10 Evaluation Kitに搭載されていた 10M08SAR144ESと比較すると LE数は 8K→ 50Kに、Flash Memory は 144KB → 484KBに、 そ れ ぞ れ 強 化されて いる。 メモリも378Kbit→ 1638Kbitと4倍になっており、NIOS IIを使うにも支障はなさそう

をインクリメントするとともに、どの LEDを表示するかを定めるdisp_cntrというレジスタを書き換えるというものだ。 LEDは全部で 10個なので、dec_cntrが 10になったら 0に戻している。disp_cntrの方は、右から左に LEDが流れるようにシフト演算の形で 1の値の位置を移動している。これを assignでLEDR(LED出力)に割り当てて完了である。 これをコンパイルすると特に問題なく生成されるはず(筆者のマシンだと 46秒ほど要した)なので、Programmerを使って書き込んでやると完了である(Photo20)。プログラミングが終わると、こんな具合に LEDが流れるように点滅するはずだ(Movie02※)。 ということで今回はMAX 10 NEEKを紹介した。来月はここにNIOS IIも組み込んで、もう少し本格的に取り組んでみたい。

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news007.html     ムービーはこちら → https://www.youtube.com/watch?v=38zzNVggEyM

周辺機器の充実した「MAX 10 NEEK」で本格的な開発を目指す

40

MAX 10 FPGAで学ぶ FPGA開発入門(9)

「MAX 10 NEEK」へソフトコアCPUを組み込む周辺機器の充実したMAX10搭載開発ボード「MAX 10 NEEK」に、ソフトコア CPU「NIOS II」を組み込み、ソフトコア CPUからボード搭載 LEDの制御までを紹介する。

 前回より、周辺回路の充実した台湾 Terasic製MAX 10評価ボード「MAX 10 NEEK」を用いての本格的な開発に着手したのだが、NEEKの話を始める前にちょっと以前の補足を。 連載第6回にて、なぜかQuartus II 15.0を使うとTempSensorをビルドしても上手く動かないという話をご紹介した。また続く第 7回の冒頭で、Quartus Prime Liteでもうまく動かないが、Quartus II 14.1ならば普通に動作するという話も紹介した。 これに関しては「BSPの再構成も必要」であり、これが「マニュアルに記載がない」旨をアルテラよりご連絡いただいた。具体的にはこの画面で、左ペイン下側にある「TempSensor_bsp」についても再構築が必要、との事である。 ただ実はこれに沿って TempSensor_bspについてもClean Build → Buildを行ってみたものの、状況に変化は無かった。これはQuartus II 15.0でもQuartus Prime Liteも同じであった。現在もう少し詳細をアルテラに問い合わせ中なので、結果が分かり次第、お伝えしたいと思う。

NEEKへNIOS IIを組み込む さて、気を取り直して(?)NEEKである。 前回は取りあえず FPGAのみを使っての Lチカをやってみたので、今回はNIOS IIを組み込んでみたいと思う。まずはNEEKに付属のSystem Builderを起動して、必要なコンポーネントを組み込む(Photo01)。するとSystem Builderの下に "CodeGenerated\

MAX10\NEEK_NIOS2" というフォルダが生成されて、今生成され

たコードがおかれているので、これを適当なところ(筆者はC:\altera\15.0\Projects\の下にNEEK_NIOS2というフォルダを生成してここにコピーした)におく。 次にQuartus II(でもQuartus Prime Liteでもどちらでもいい。今回はQuartus II 15.0を選んだ)を起動し、既存の Projectのオープンを選んで、今生成されたNEEK_NIOS2.qpf(Project File)を選ぶとこんな具合(Photo02)になる。 さて、次はNIOS IIの組み込みである。これはSystem Builderでは行えないので、QSYSを起動してこれを行うことにする。起動直後は Clock Sourceしかないので(Photo03)、まずは"Processors and Peripherals"→ "Embedded Processors"→ "NIOS II Processor"をダブルクリックしてNIOS IIコアを登録する(Photo04)。 ちなみにMAX 10 NEEKに搭載されている10M50DAF484C6Gは LE(Logic Elements) が 50K、Block Memory も 1638Kbit(204.75KB)と最大規模のものなので、ついNios II/fを選択したくなるのだが、こちらは有償扱い(一応無償で利用できるOpenCore Plusベースのものが利用できるが、時間制限付き)なので、諦めてNios II/eを選択する(Photo05)。 設定画面に戻るとエラーが出ているが(Photo06)、それは気にせずに次は"Interface Protocols" → "Serial" → "JTAG UART"を追加する(Photo07)。その次は、"Basic Functions" → "On Chip Memory" → "On-Chip Memory (RAM or ROM)"でRAMを登録する(Photo08)。

Photo02:Photo01では指定していない PS2の信号線が定義されているのは、恐らくは System Builderのバグであろう。HEX0/HEX1は 7セグ LED

Photo01:プロジェクト名は「NEEK_NIOS2」とした。7セグメント LEDは今回利用を考えていないが、後で使うかと思って組み込んでみた

41

 ここで容量は 64KBを選んだが、これはまぁこの位あれば取りあえずいいだろうという事であって、デフォルトの 4KBのままでも今回の用途には十分である。むしろ注意点は、"Memory Initialization"の所にある "Initialize memory context"のチェックを外しておく事

Photo03:Clock Sourceは自動で登録される。これは特にいじる必要がない

Photo07:JTAG UARTは特に設定の必要はない

Photo06:エラーは後でまとめて解消する

Photo04:NIOS II(Classic)を選ばない様に注意

Photo08:エラーは更に増えているが気にしてはいけないPhoto05:NIOS II/f

だ(Photo09)。 最後に、10個の LEDの点滅用のParallel I/Oポートの指定である(Photo10)。"Processors and Peripherals" → "Peripherals" → PIO( Parallel I/O )"を指定する形だ。今回は LEDが 10個

42

Photo11:これはまだ 10と指定する前。デフォルトは 8

Photo12:Warningは大幅に減った。エラーはこの次に対処

Photo13:Address Mapのタブを見ると、全てのデバイスが似たようなアドレスをマッピングしようとしている。そりゃエラーにもなる

Photo10:IPの場所にいまいち一貫性がないのが困りモノ

Photo09:なぜか "Initialize memory context"はデフォルトでチェック「On」になっている

なので、Widthには 10を指定する(Photo11)。あと、デバイスの名前を "pio_0"に変更しておく。 次に、それぞれの IPの結合を行う。Photo12で赤丸をつけてある箇所をクリックして、黒丸(結合状態)にする形だ。例えば一番左側の線はクロックドライバから出力されるクロック信号なので、これをNIOS II、JTAG_UART、On Chip Memory、PIOの各デバイスに供給するための設定がこれである。同様にReset出力、JTAGからNIOS IIへの IRQ、データの送受信など必要な配線をつなぐ形だ。

メモリアドレスの重複解除 その次は、メモリアドレスの重複解除だ。それぞれのデバイスはメモリアドレスを専有するが、これの調整が必要である(Photo13)。対策は簡単で、"System"→ "Assing Base Addresses"を選ぶと自動調整してくれる(Photo14)。これでエラーはほとんどなくなるハ

43

ズだ。 残るエラーは、クロックドライバの「clk_in_reset」という信号に関係する部分だ。これは "Double-click-to-export"とグレーアウトされている部分をダブルクリックし、"reset"という信号名で

Photo14:全部エラーがなくなるわけではない

Photo16:Error/Warningともに 0になった

Photo15:これは resetの Exportを行ったあとの状況。最後は pio_0

exportするようにすれば良い。 すると pio_0の ExportのWarningが残っているだけになる(Photo15)ので、"led_pio"という名称でExportする(Photo16)。これで完了なので、ファイル名をつけて(Photo17)保存後にHDLの生成を行う(Photo18)。問題なければこのメッセージ(Photo19)が出てくるはずだ。

Quartus IIに戻って さて、ここからはQuartus IIに戻る。左の Files画面で、まず現在表示中のNEEK_NIOS2.v、それとQSYSで生成した qipファイル(今回だとNEEK_NIOS2_QSYS/synthesis/NEEK_NIOS2_QSYS.qip)をプロジェクトに追加する(Photo20)。

Photo17:ここでQSYSの出力はプロジェクト名 (今回だとNEEK_NIOS2)と同じにしてはいけない。あとでえらい目に合う (というか、合った )。

Photo18:これはおなじみの手順

Photo19:ちなみにこのメッセージ、QSYSを終了すると出たり、QSYSを終了させなくても出たり、とイマイチ状況をつかみきれない

44

Photo24:sopcinfoはQSYSが生成しているので、これを指定する (今回の場合だとNEEK_NIOS2_QSYS.sopcinfo)

Photo23:利用率を見るとまだほとんど余っている状況

Photo22:コメントとかは別にまねする必要はない(念のため)

Photo21:FileタブでNEEK_NIOS2_QSYS.qipを展開するとこれが出てくる

Photo20:ファイルの追加は、左上の Fileタブの中で、"Files"フォルダを右クリックして "Add/Remove Files in Project..."を呼び出して、そこで行う

 ここでNEEK_NIOS2_QSYS.vの中身を見ると、こんな宣言になっているハズ(Photo21)なので、この記述にあわせて、NEEK_NIOS2.vをこんな風に書き換える(Photo22)。List 1に書き換えた後のソースを示すが、要するにNEEK_NIOS_QSYSへ制御を移す宣言である。この際にクロックソースは、もともと供給される 50MHzのもの(MAX10_CLK1_50)を指定し、PIOポートにはLEDRを指定する。リセットは常時Offということで、1(True)を与えておく形だ。 ここまで終わったらVerilog側のプログラミングは完了である。あとはビルドし(Photo23)、問題が無ければ Programmerを利用して .sofファイルを書き込んで置く。 さて、今度はソフトウェアの方だ。Quartus IIから "Tools" → "Nios II Software Build Tools for Eclipse"を選び、Eclipseを立ち上げる。立ち上げたらまず "File" → "New" → "Nios II Application and BSP from Template"を選んでテンプレートから生成する(Photo24)。 今回はメモリもたっぷりあるので、Hello World Smallではなく、Hello Worldを選んでみた。あとは自動でHello WorldとそのBSPが生成されるので、以前と同じ手順でビルドして実行する。問

45

題がなければ、NIOS IIのConsoleに "Hello from Nios II!"が表示されるはずだ(Photo26)。

LチカをソフトコアCPUから操作する さて、ここまでできたので次は LチカをCPUから操作する方法である。コードをList 2※の様に書き換える(Photo27)。まずPIOの操作を行うAPI(というかマクロ)は、altera_avalon_pio_regs.h(これは BSPの方の drivers/incの下にある)に定義されている。IOWR_ALTERA_AVALON_PIO_DATA()がそれで、指定したアドレスに値を書き込むというものである。 今回だと値は cnt++の値にあわせて 0か 1なので、点滅が行われるというわけだ。続く forループは単なる delayである。ちなみ

Photo25:まぁこれに説明の必要はないだろう Photo26:コンソールは右ペインにある。Photo25と比較してもらえると分かりやすい

に指定したアドレスが PIO_0_BASEとなっているが、これはQSYSで指定した名前を大文字にして、最後に "_BASE"が付加されたものになる。これを実行すると、Movie01※の様に右端のLEDが一定間隔で点滅する。 では LED10個を全部点滅させるにはどうするか?であるが、PIOの場合、与える値のビットフィールドがそのままそれぞれの LEDのOn/Offとなる。つまり0bit目(LSB)が LED0、1bit目が LED1……となって、9bit目が LED9に相当する。というわけで、プログラムをList 3※の様に書き換えて実行した結果がこちら(Movie02※)である。ちゃんと全 LEDが正しく点滅するのがお分かりいただけるかと思う。 次回はもう少しいろいろな周辺回路をNIOS IIからアクセスしてみたい。

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news008.html     ムービーはこちら → https://www.youtube.com/watch?v=bSDt3ObjnAE

「MAX 10 NEEK」へソフトコアCPUを組み込む

46

MAX 10 FPGAで学ぶ FPGA開発入門(10)

「MAX 10 NEEK」に搭載されたDDR3メモリを使う 周辺機器の充実したMAX10搭載開発ボード「MAX 10 NEEK」に、ソフトコア CPU「NIOS II」を組み込み、ソフトコア CPUからボード搭載 LEDの制御までを紹介する。

Nios II On-die Temperature Sensor Design Example

 先月も触れた、MAX 10 Evaluation BoardとTempSensorの話であるが、やっと問題が解決したので最初にこちらの話をしておきたい。 経緯を説明すると、アルテラのWebサイトで提供されるMAX 10 Evaluation Board用のサンプルである「Nios II On-die Temperature Sensor Design Example」(現在は存在しない:理由は後述)をダウンロードし、マニュアルの手順に従って構築する際、Quartus II 14.1を使う限りにおいては正常に動作するのだが、Quartus II 15.0、あるいはQuartus Primeを利用するとNIOS IIコアが正常に動作しないという現象が出ていた。この件に関して、Alteraより正式に原因と対処に関しての連絡を頂いた。

 そもそも動かない原因は 2つあり、1つは BSPの再ビルドが必要だった事、もう 1つは ADCの初期化コードが含まれていなかった事だ。1つ目については前回紹介した通り、TempSensor_bspの再構築を実施すればよい。問題は 2つ目だ。 アルテラによれば、ADCに対してまず初期化の際に割り込み禁止を実施する必要があるとの事。ただしこれがAlteraのドキュメントから欠落しており、またサンプルコードにもこの割り込み禁止を行う処理が抜けていた。この結果、NIOS IIが起動してADCを有効にした途端、ADCからの割り込みが発生する事になる。悪い事に今回のサンプルでは割り込みハンドラが無いので、割り込みが発生してもユーザープログラムに制御が一切戻らないという事になっていた。 対策であるが、現在のサンプルでは初期化ルーティンが

//Starting the ADC sequencer IOWR(MODULAR_ADC_0_SEQUENCER_CSR_BASE, 0, 0); usleep(10); IOWR(MODULAR_ADC_0_SEQUENCER_CSR_BASE, 0, 1);

となっている。これを

//Starting the ADC sequencer IOWR(MODULAR_ADC_0_SEQUENCER_CSR_BASE, 0, 0); usleep(1000); IOWR(MODULAR_ADC_0_SAMPLE_STORE_CSR_BASE, 64, 0); IOWR(MODULAR_ADC_0_SEQUENCER_CSR_BASE, 0, 1);

 と変更する事で解決できるとの話であった。この 3行目に追加された "IOWR(MODULAR_ADC_0_SAMPLE_STORE_CSR_BASE, 64, 0);" が、ADCに割り込みの発生を禁止させる設定である。これを入れたところ、正常に動作するようになった(Photo01)。 ちなみになぜ Quartus II 14.1で動作したのかであるが、Quartus IIでは明示的に初期化していない設定値をどう扱うか、に関してバージョン毎に異なっているのだそうで、「たまたま」Quartus II 14.1ではADCの割り込みを無効化する初期値になっ

ていた。だが、Quartus II 15.0以降ではこれが変わってしまっていた、という事が真相の様だ。  既 に こ の Nios II On-die Temperature Sensor Design Example は “Nios II On-die Temperature Sensor Design Example 2”(15.0用、15.1用)としてアップデートされており、こちらでは問題は解決している。またADCのドキュメントへの反映を現在本国に依頼中との事で、新しくサンプルをダウンロードすれば問題は解決する筈だ。ということで、やっと一件落着である。

47

MAX 10 NEEKに搭載されたDDR3メモリを使う

 さて、今回はNEEKに搭載されたDDR3メモリを使ってみたい。MAX 10 NEEKには、FPGA内に内蔵されたSRAMとは別に、外部にDDR3メモリが搭載されている。DDR3/LPDDR2の I/FはMAX 10に標準搭載されており、なので基本 DDR3ないしLPDDR2を搭載すればMAX 10からこれを利用する事ができる。

もちろん、NIOS IIからの利用も可能だ。 MAX 10 NEEKのSystem CDを展開すると、Demonstrations\ddr3_niosの下に、NIOS IIからDDR3をアクセスするためのサンプルコードが用意されている。まずは手始めに、MAX 10 NEEKを起動してUSB Blaster IIを接続した状態で、Demonstrations\ddr3_nios\demo_batchの下にあるddr3_nios.batを起動すると、こんな

Photo01:一番右にNIOS IIのコンソールが開いており、正しく温度も取得できて居る事が分かる。ちなみにソースは最終版になる前の、暫定バージョンなので注意されたい

Photo02:ここで言う "KEY0"はNEEKのボード側の KEY0(スライドスイッチの左 )である

Photo04:このサンプルは Terasic製

Photo05:先頭は Timerとか LED、スイッチ類が大量に入っている。ddr3_status、というデバイスがあることに注意

Photo03:ちなみにテストを止める方法は無いので、放っておくと延々とテストが繰り返される。

Photo06:NIOS IIコアとかオンチップの SRAM、DDR3 I/Fなどは最後の方に

48

画面になるはずだ(Photo02)。KEY0を押すと、NIOS IIからDDR3メモリへの読み書きがテストが開始される(Photo03)。問題がなければ、test結果は “Pass”になる。 この demo_batchの下はバイナリの形で提供されているので、これを自分でビルドしなおしてみよう。 Demonstrations\ddr3_nios の下を丸ごと他のフォルダにコピーして、Quartus IIから "File" → "Open Project..."で ddr3_nios.qpfを選択してプロジェクトを開く(Photo04)。そのままコ

Photo07:オンチップメモリは 0x0~ 0x1f3ffまでにマッピングされている

Photo08:Speed Gradeは 6(DDR3/LPDDR2)固定。速度は今回 300MHzとなっている

Photo09:ここはメモリチップにあわせての設定となる。ちなみに Total Interface Widthが 24bitなのは、16bit接続と 8bit接続が混在しているから

Photo10:Memory Timingは、データシートの Typ値に準じる形で入力

49

Photo11:こちらはメモリというよりはボードの設計にあわせる

Photo13:ここはデフォルトのままで

Photo14:コアはNios II/fだが、オプションは最小限

Photo12:Memory Controllerの設定。バースト長 4というのは、DDR3というよりはメモリコントローラ側の設定

ンパイルしてもいいのだが、構成を確認するためにQSYSを開いてみる(Photo05,06)。 メモリマップはこんな感じ(Photo07)で、0x08000000~0xfffffffにDDR3メモリがマッピングされていることが分かる。マッピングを見る限り、スタックとかダイナミックな変数にDDR3の領域を使うのは、そのままでは無理(EclipseでC++のソースのビルドの際にリンクオプションで設定をしない限り自動では使ってくれない)だが、プログラム内からアドレスを指定して利用するのは問題なさそうだ。

50

 以下 Photo08~ Photo13が、その DDR3 I/Fまわりのパラメータとなる。今回はこれをいじる必要はないが、自分でDDR3を利用して何かやりたい、という場合にはこれに準じる形でパラメータの設定を行う事になる。また今回、デフォルトではCPUコアはNios II/fとなっている(Photo14)。これは TerasicがNios II/fのライセンスを保有しており、これを利用して開発を行った為だろう。これについては後でちょっといじって遊ぶが、取りあえずはこのままで行くことにしたい。

Generate HDLで構成を生成 もろもろ確認したら、Generate HDLを押して構成を生成する。この際にPhoto14にもあるようにWarningが出ているが、これはQuartus IIというかQSYSの既知の問題(pll_sharing Warning Message May Appear)なので、無視して差し支えない。 HDLの生成が終わったらQuartus IIに戻ってコンパイルを行う(Photo15)。その後にはプログラミングであるが、Programmerから "Add File..."を選ぶと見慣れないファイルがあるはずだ(Photo16)。これは第 9回(「MAX 10 NEEK」へソフトコアCPUを組み込む)でもちょっと触れたが、Nios II/fは有償であり、そのままでは利用できないためだ。

Photo15:DDR3回りの Timingで幾つかWarningが出ているが、無視して構わない

Photo16:このままだと _time_limited の有無のどちらが新しいのか分かりにくいので、ファイルの生成時刻も表示させるとよい

 開発用にはOpenCore Plusベースのものが利用できるが、こちらは時間制限付きとなっている。ファイル名に “time_limited”がついているのはこのためだ。この "_time_limited"付を選ぶと、こんな警告メッセージ(Photo17)が出てくるのでOKを押して、そのままMAX 10にロードする(Photo18)。 ロードが終わるとダイアログが表示される(Photo19)が、これがTime Limitedの制約である。今はUSB Blaster経由でロードしているから、このダイアログを表示させている間はずっとNios II/fを使い続けられるという意味で、ここでCancelを押すとNios II/fが利用できなくなる。なので、Cancelを押さずに次に移る。 次はソフトウェア側である。まずEclipseを立ち上げた後、"File" → "Import..." で Import Menuを表示させ、ここから "Import Nios II Software Build Tools Project"を選ぶ(Photo20)。 するとフォルダの参照になるので、先にコピーしたフォルダの下にある “ software\ddr3_nios ”を選ぶ(Photo21)び、Project名には “ddr3_nios”を選ぶ(Photo22)と、ちょっと時間を置い

Photo17:これが毎回出てくるのがちょっと面倒

Photo18:この状態で "Start"を押せばよい

Photo19:フラッシュメモリに書き込んで起動するような場合、OpenCore Plusでは確か 1時間の利用制限が付く(電源投入後、1時間だけNios II/fが動作する)

51

Photo20:この Import、意外に分かりにくい Photo22:指定を行うと、しばらくバックグラウンドでファイルの確認を行い、正常にImportできると判断されると "Next"と "Finish"ボタンが有効になる

Photo23:bspは自動では入らないので、こちらも同じように指定する

て「Finish」ボタンが有効になるので「Finish」を押して、プロジェクトを丸ごと Importする。同様に、ddr3_nios_bspも Importする(Photo23)。 2つの Projectの両方とも「Clean Project」を指定してクリアにした後で、ddr3_nios_bspのプロジェクトを右クリック、“ Nios II ” → “ Generate BSP”を指定して BSPの再構築を行う(Photo24)。 これが済んだらまず ddr3_nios_bspをビルドし、次に ddr3_niosをビルドする。完成するとWarningが 1つ出るが、これは無問題(Photo25)。Run Configurationで設定を行ったら実行す

Photo21:フォルダ指定は "software"ではなく、その下の "software\ddr3_nios"まで行う必要あり

る。問題なければこんな具合に実行が始まる(Photo26)。問題が無ければ、WriteとRead/Verifyが 21秒で完了するはずだ。 さて、ここまではサンプルにある「ddr3_test」そのままである。これをNiosII/eに切り替えるとどの位遅くなるか、をちょっと試してみた。

52

 手順は簡単で、QSYSのプロパティ画面(先の Photo14だ)でNios II/eに切り替え、QSYSでGenerate HDL → Quartus IIでコンパイル → Programmerで書き込み(今度は _time_limitedの付かない ddr3_nios.sofを指定する) → Eclipseで BSPの生

Photo24:これが必要ない場合もある。Importした場合、BSPをビルドしようとすると "BSPを作り直せ "と怒られるので、これをやっておくと無難

Photo26:一番右の NIOS II Consoleに、Photo03と同じような表示が出てくるはずだ

Photo27:Nios II/eに切り替えると目に見えて遅くなるPhoto25:Warningの内容は、alt_dcacche_�ash_all()の型指定が無いというもの

成 → プロジェクト再構築 → 実行、という流れである。 結果はご覧の通り(Photo27)で、60秒とNios II/fに比べて3倍近い時間がかかっている。次回はこのあたりをもう少し試してみたい。

53

Photo02:出力の場合、特にその他はいじる必要はない。初期値も特に設定しなくても今回は構わないPhoto01:DDR3メモリは今回はちょっとおいておく

MAX 10 FPGAで学ぶ FPGA開発入門(11)

「MAX 10 NEEK」でストップウォッチを開発し、内蔵メモリから起動するアルテラの FPGA「MAX 10」を搭載した開発ボード「MAX 10 NEEK」には LEDやフラッシュメモリなどの各周辺機器が備えられている。今回は LEDを使ったストップウォッチを開発し、内蔵メモリから起動する。

 この連載ではアルテラの FPGA「MAX 10」を題材にしているおり、ここ数回は各種周辺機器も備えたMAX10搭載開発ボード「MAX 10 NEEK」を使って周辺機器へのアクセス方法などを紹介している。 前回はDDR3を利用する方法を説明したが、今回は内蔵 Flashを使ってみたい。 もともとMAX 10の場合、内部に Flash Memoryを保持しており、ブート時にはここからConfigurationを読み出して即座に実行できるので、これを利用できるようにしてみたい。もちろん、ソフトコアCPUの「NIOS II」を含めて、である。

下準備 さてまずは前準備。今回は連載 第 9回(「MAX 10 NEEK」へソフトコアCPUを組み込む)で紹介した内容をもとに簡単なストップウォッチをNIOS IIベースで構築してみる。 第 9回ではNIOS IIの組み込みがメインであったので、LEDと7セグメントLEDはを組み込んだだけ(しかも実際には使わなかった)だったが、今回はこれを活用する。ついでにボタン ×5(実際

はうち 4つ)も活用する。ということで、最初は System Builderである(Photo01)。プロジェクト名はひねりがなくて恐縮だが「NEEK_LED3」だ。 ファイルが生成されたら、それをQuartus II(今回も 15.0を使った)のプロジェクトディレクトリにコピーしたのち、Quartus IIでそのプロジェクトを開く。次いでQSYSを立ち上げて、プロセッサコアと JTAG UART、オンチップメモリを組み込む手順までは第9回と同様だが、追加で作業を行う。 これらの手順を終えると、最終的にはこんな感じになる(Photo04)。

ポートの名前 ちなみに追加した 4つの PIOポートの名前だが、これはMAX 10 NEEKの System Builderの生成するソース(NEEK_LED3.

54

MAX 10に書き込む(Photo06)。記述を間違えなければ、ここで問題が出ることは無いはずだ。

NIOS IIで動作するストップウォッチをプログラム さて次はNIOS II上で動作するプログラムの方だ。まずは第 9回の手順と同じよう、" Nios II Application and BSP from Template "からHello Worldのテンプレートでアプリケーションを生成する(Photo07)。 このままでは文字通り、単なる「Hello World」なので、これを

List 3※のように書き換えた。 一応簡単に説明すると、LEDR_outは一列に並んだ LEDの指定桁(0~ 9)のみを光らせる関数、HEX_outは 7セグメントLEDを指定した値(0~ 9)に点滅させる関数である。 面白いのは、LEDRの方は指定した桁にあたる bitを立てると、それに対応する LEDが点滅する(例えば 0x3FFを指定すれば全部点灯する)のに対し、7セグメント LEDは対応する bitを落とすと、そのセグメントが点灯する方式になっていることだ。 ここに指定する bit fieldとセグメントの関係は

Photo04:これは結線が全部完了し、さらにQSYSの "System" → "Assign Base Address"を実施してアドレスの整合性を取った後の状況である

v)が List 1※の様になっている事を踏まえ、これと名前をあわせた形だ。また、4つの PIOについては、いずれもそれぞれの名前でExportを行っておく("Double-click to export"と書かれている部分をダブルクリックすると名前 +"_pio"で Exportされる指定となる)。Photo04で言えば、"ledr_pio"、"hex0_pio"、"hex1_pio"、"key_pio"がこれにあたる。 ここまで完了したら名前(今回は "NEEK_LED3_QSYS"とした)を付けて保存後に、Generate HDLで HDLを生成する(Photo05)。 ここまでできたら、次はQuartus IIに戻るわけだが、まずはNEEK_LED3.vを下の List 2※のように書き換える。 ここで「NEEK_LED3_QSYS」というmoduleを呼んでいるのだが、これはQSYSが生成したNEEK_LED3_QSYS.vというファイル(synthesisフォルダの中にある)に定義が入っているので、それを見ながら exportされたものをつなげる形だ。これを記述後にコンパイルし、問題がなければ普通にProgrammerで

Photo05:無事に生成

Photo07:アプリケーションプロジェクト名は "stopwatch"とした

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news009.html

55

 となっており、そこで最初にHEXtable[]でそれぞれの数字に対応した bit patternを保持しておき、これをまとめて出力する形になっている。HEX_out(0,xxx)で 1桁目を、HEX_out(1,xxx)で2桁目をそれぞれ表示する形だ。 一方、これを呼び出すmain()は、見ての通りで cntという変数で 0~ 9を繰り返しながら表示させるだけの、純粋にテストプログラムである。実行するとMovie01※の様に、7セグメントと 10個の LEDが連動しながらきちんと表示されているはずだ。

「光るLED」を「ストップウォッチ」に さて、これだけでは何の意味も無いので、これをストップウォッチに仕立ててみたい。0秒から 99.9秒まで測定できるものだ。 まずはタイマーを追加する必要がある。ということでQSYSに戻り、新たに "Processors and Peripherals" → "Peripherals" → "Interval Timer"を選んで追加する(Photo08)。この際に、irqの線をCPUとつなぐ事を忘れない様に。デバイスを追加するとアドレスが変わるので、再び "Assign Base Address"を呼んでアドレスを再配置してからGenerate HDLでHDLを再生成。その後にQuartus IIに戻り、コンパイルを行ってからProgrammerで書き込み直すところまでの手順は先ほどと同じである。 さて、次はNIOS IIのプログラムである。連載第 7回で既に言及したが、NIOS IIでは System Timer(Interval Timer)を追加することで、Alarm機能とTimeStamp機能を排他的に利用できる(FPGAのソフトコアCPUをベンチマークで測定する:タイマーの組み込み)。 第 7回で利用したのは TimeStampだが、今回は Alarmを利用してみたい。Alarmは名前の通り、指定した時間にCallback Routineの起動が可能である。要するに Timerを利用した割り込み機能だ。割り込みそのものは alt_irq系の関数が用意されているのだが、こちらはMicro C/OS-II環境(Photo07で、"Hello

World"の上にある選択肢)でないと利用できないので、今回は見送った。 さてそんなわけで、Alarmを使ってみることにする。まずはEclipseで stopwatch_bpsのコンテクストメニュー → "Nios II" → "BSP Editor..."を指定して BSP Editorを起動し、ここで"sys_clk_timer"に "One_ms_Timer"を選択する。これが終わったらGenerateを押してBSPを生成、stopwatch_bsp自身を再ビルドする。プログラムは、以下 List 4※の様に書き換えた。

List 4解説 List 3からの変更点は、alt_alarm関数への対応、それとキー入力への対応である。 まずKEY_START/KEY_HOLD/KEY_STOP/KEY_RESETという 4つの定義が出てくるが、これは KEY 0~ KEY3の 4つのキーそれぞれへの対応である。今回の場合、IORD_ALTERA_AVALON_PIO_DATA(KEY_BASE) を呼ぶとキーの状態が5bitの形で返ってくるが、0bit目が KEY 0、1bit目が KEY 1...となっており、それぞれに対応した形だ。 新しくAlarm_Int()という関数が追加されているが、これはAlarmで呼び出されるCallback関数だ。今回の場合、Alarmは1msにセットされている(つまりAlarm_Int()は 1ms毎に呼び出される)事になるので、内部でカウンタを回して 100回(つまり100ms)経過したらNum(0.1秒単位のカウンタ)を 1つ増やし、それにあわせてLEDと7セグメントLEDの表示を行って戻るだけの処理を行う。 一方メインルーティンだが、while(1)の中でまずキーの値を読み取り、何かしらキーが押下されていた(7セグメント LEDと同じく、押されていないと 1、押されると 0が bitfieldに返ってくる)ら、それにあわせてAlarmをストップしたりスタートしたり、あるいはカウンタ(TickとNum)をクリアしたり、といった処理を行っているだけである。 余談になるが、先にPhoto03のキャプションでこの KEYの入力については Edge Captureを最終的に無効にしたと書いた。本来この機能は、割り込みと組み合わせて使うものだ。Photo03を見ると「Interrupt」という項目があって、必要ならキーの押下を検出して割り込みを発生させることができる。この際、押しっぱなしにすると延々割り込みが発生するのはまずいので、押された瞬間を検出しようというわけだ。 ところが今回の様にポーリングで検出する場合、押された瞬間があまりに一瞬すぎるためにほぼ取りこぼす。そんな訳で今回は「押されている」という状態を検出するようにしたわけだ。 さらに余談になるが、こうした確認には printfデバッグが有効である。ところがメモリが 64KBだと printfが動かない(厳密にいえば、printf ("Hello, world\n");は動作するが、printf( "Hello, %d", 100);はメモリが足りずにビルドに失敗する)ため、128KBにしたというわけだ。

Photo08:ちなみに Periodは 1msにしたが、10msでも良かったかも。それ以外はデフォルトのままである。名前は "ONE_ms_Timer"とした

※このページのソースコードはこちら → http://monoist.atmarkit.co.jp/mn/articles/1609/09/news009.html     ムービーはこちら → https://www.youtube.com/watch?v=JeLxu98yVis

56

Photo09:連載 第 7回の時は、timestamp_timerを指定して sys_clk_timerはnoneだった

Photo10:たまたまなのか、筆者のケースでは追加したら 2つともこの状態になっていた

Photo11:NIOS IIのプログラムとデータの両方がここに格納されるので、dataの先に両方が結線される

 さて、あとはビルドして実行させるだけである。実行結果はこんな感じ(Movie02※)である。ボタンは右からSTART/HOLD/STOP/RESETに設定されており、7セグメント LEDで秒を、10個の LEDで 0.1秒をそれぞれ示している。

「ストップウォッチ」をMAX 10 内蔵フラッシュから起動する

 恐ろしい事に今回はここまでが前段階であり、ここからが本題となる。多少なりとも意味のあるプログラムが完成したところで、それではこれをMAX 10の内蔵 Flash Memoryから起動させる手順をご紹介したい。 まずは再びQSYSに戻る。"Basic Functions"→ "On Chip Memory"→ "Altera On-Chip Flash"を選択し、内蔵 Flashを追加する(Photo09)。

ここで注意点は ・ Configure Modeを "Single Uncompressed Image"にする。 ・ Initialize flash contentのチェックを外す。の 2点である。 追加後は Photo11の様に結線を行い、再度 "Assign Base Address"でアドレスの再配置を行う。次に、NIOS IIのパラメータを表示し、Reset Vectorを "onchip_memory2_0.s1"から"onchip_flash_0.data"に変更する(Photo12)。 以上でQSYSの作業は終了で、後は保存してGenerate HDLでHDLを生成してからQuartus IIに戻る。 Quartus IIではまずメニューの "Assignments"→ "Device"でDevice Menuを呼び出し、ここの "Device and Pin Options..."ボタンを押してDevice and Pin Options Menuを表示する

Photo12:要するにCPUにリセットが掛かったときどこに飛ぶかの指定で、これで内蔵 Flash Memoryに飛ぶことになる

※このページのムービーはこちら → https://www.youtube.com/watch?v=TFGjrZEhJYM

57

(Photo13)。ここのConfigurationの中の "Configuration Mode"を "Single Uncompressed Image(3584Kbit UFM)"に設定し、OKボタンを押す。 これが完了したらQuartus IIに戻ってコンパイルを行うが、完了してもProgrammerはまだ呼び出さない。その前にEclipse側の作業がある。 QSYSでハードウェアの構成変更を行ったので、stopwatch_bspのコンテクストメニューから"Nios II" → "Generate BSP"を呼んでBSPの再構成を行う。その後でもう一度 "Nios II" → "BSP Editor"を起動する。 ここで左のツリーを下の方までスクロールしてゆくと、"Settings" → "Advanced" → "HAL" → "Linker"という項目がある。このHAL.Linkerの 5つのチェックボックスに全てチェックを入れておく(Photo14)。 続いて上の Tabを "Main"から "Linker Script"に切り替えると、セクション毎にどこに保存するかの指定があるが、ここで .textを"onchip_memory2_0"から"onchip_flash_0_data"に切り替え

Photo13:ここは Photo10と設定をあわせる形

る(Photo15)。以上で BSPの変更は完了したので、もう一度Generateボタンを押してBSPの再生成を行い、終了する。 続いてEclipseに戻り、まず stopwatch_bspの再ビルドを行った後、stopwatchの方のコンテクストメニューから "Make Targets" → "Build..."を選ぶ(Photo16)。するとTargetメニュー

Photo16:stopwatch_bspの方は、自動で再ビルドが掛かるはずであるが、まぁ一応明示的に

Photo14:デフォルトでは "enable_alt_load_copy_rodata"と "enable_alt_load_copy_exception"にはチェックが入っていない

Photo15:その他の箇所は変更不要

Photo17:ここで Buildボタンを押すと、まず elfファイルの Buildが行われた後に、これを HEXファイルに変換してくれる

58

が出てくる(Photo17)ので、ここで "mem_init_generate"を選択した上で Buildボタンを押すと、通常の elfファイルではなく、Flashに組み込むための HEXファイルが生成される。以上でEclipseでの作業は終了し、再びQuartus IIに戻る。 Quartus IIは、"File" → "Convert Programming File..."からConverter画面(Photo18)を立ち上げる。ここでまず "Mode"を "Internal Configuration"に切り替えてから "Options/Boot info..."ボタンを押すと "MAX 10 Device Options"画面が出てくる(Photo19)。この画面で、

・ UFM sourceを "Page_0"から "load memory file"に変更。 ・ その下のファイル選択ボタンを押し、mem_initフォルダの下に生成された onchip_flash_0.hexを指定。

を行う(Photo20)。完了したら "OK"ボタンを押してこの画面は終了である。 再び Converter画面に戻るので、下にある "Add File..."ボタンを押し、先にQuartus IIで生成した .sofファイル(今回だとNEEK_LED3.sof)を指定してから(Photo21)Generateボタンを押す。問題なければ、これで .pofファイルが生成される。最後にProgrammerを呼び出し、今生成した .pofファイルを指定し

Photo19:この画面は、そんなわけでPhoto18でModeを Internal Con�gurationにしない限り出てこない

Photo20:File Pathがグレーアウトされているのでちょっと分かりにくい

Photo18:標準は外部の Flashに格納(というか内蔵 Flashを持っているのがMAX 10しかない)なので、Modeの切り替えでいろいろ変わる

Photo21:今回はデフォルトのままなので output_�le.sofというファイル名になるが、この画面で変更(例えばNEEK3_LED.pof)も可能

59

て書き込む(Photo22)。これが 100%になれば完了である。 以上で作業は終了である。 これで、電源を入れると直ちにストップウォッチが起動する。Movie03※がその様子だが、ACアダプターだけつないだ(USBケーブルはつないでいない)状態で電源スイッチを入れるとすぐに7セグメント LEDが 0クリアされ、その後、スイッチの操作でストップウォッチが動いているのがお分かりいただけるかと思う。 いろいろと設定があって面倒だが、取りあえず、このような手順を踏む事で、FPGAのConfigurationとNIOS IIのプログラムの両方を Flashに格納できる様になった。

Photo22:メモリに書き込む .sofファイルの場合と異なり、Flash Memoryの書き込みには時間がかかるため、Progressバーの進み方はかなりゆっくりである。

※このページのムービーはこちら → https://www.youtube.com/watch?v=jLja8IGeLss

「MAX 10 NEEK」でストップウォッチを開発し、内蔵メモリから起動する