$30で始めるfpga

173
$30で始めるFPGA 2015/10/9版 竹村幸尚 @yukitaketake

Upload: yukitaka-takemura

Post on 15-Jul-2015

4.152 views

Category:

Devices & Hardware


0 download

TRANSCRIPT

$30で始めるFPGA

2015/10/9版

竹村幸尚 @yukitaketake

BeMicro Max10 FPGA Eva Kit

2

MAX10という安価なFPGA搭載。ちっちゃい。

MiniUSBでPCとつなぐだけ– USB-Blaster内蔵

USB-BlasterはUSB経由でFPGAにプログラムするためのシステムです。

– USBつなぐと電源もON

ボードとケーブル以外、DVDも説明書も何もついていないという割り切りの良さ

ただし搭載FPGAが10M08なので、回路はあまり入らない

で…

$30の衝撃

3

しかも送料かからないなんて…*1

ポチって3日後に来たし。アメリカから。

*1 送料がかかるようになったり、また無料になったりしている様子…

この資料の対象者

4

こんな人に是非おすすめ

– 仕事や趣味でマイコン使ってるがFPGAに興味がある

– FPGAでメカ等制御してみたい

こんな人にまあまあおすすめ

– とにかく安くFPGAを経験してみたい

– 「普段はカフェで開発してるんでFPGAはね~」

こんな人は別のFPGAを買いましょう

– FPGAで計算させてみたい

– Linuxポーティングしたい

本資料では、基本的にQuartus IIおよびその周辺ツールの説明のみ扱います。

– HDLの解説はしません。

– ハードウェアそのものの解説もしません。

– Verilogベースで説明しますので、VHDLを使いたい人は適宜読み替えて下さい。

– OSはWindows7/8を使いますが、Linuxでも同様です。

ただし…

5

初心者はES品は避けたほうが良い場合があります。

– MAX10はまだピカピカの新製品です。

$30ならまあいいか、という人にしか薦められないかも。

– 少なくともこの資料に書いてあることは出来るので、まあ大丈夫でしょう!

見よこの恐ろしげな2文字

目次的な

6

事前準備

MAX10 FPGAについて

S/WによるLED制御

– Quartus IIを使ってみる

– Qsysを使ってみる

– Nios IIプロセッサを使ってみる

Nios II Software Build Toolsを使ってみる

SignalTap IIで波形を見てみる

H/WによるLED制御

– Lチカモジュールを準備

– IP登録してみる

全部入りサンプルを触ってみる

ModelSimでSimulationしてみる

おまけ

(追記するかも?)Nios IIにオレオレ命令を追加してみる

(追記するかも?)RTOSを入れてみる

まずは購入

7

こちらへ

– http://parts.arrow.com/reference-design/45CDF7D717BC14E6DFB1044001FB7C4F

Arrowは北米最大のAltera代理店です。

4/3現在、まだ$30で沢山在庫あり

ついでにここでスタートガイドも落としておきましょう。

– よく分からんですが、Download Reference Designというボタンを押すとダウンロードできます。

ここ

Quartus IIのダウンロード

8

Quartus II Web Editionの最新版をダウンロードします。

– こちらからどうぞ

http://dl.altera.com/?edition=web

DevicesはMAX10だけでOKです。

– もちろん全部ダウンロードしても可

– 「一式ファイル」タブから全部入りが入手可

現在最新版はV14.115.0です。

アップデートタブをクリックして最新版アップデートも入手しましょう。

– これでV14.1.115.0.2になります。

これだけでOK

ここ

Quartus IIのインストール

9

特に難しいことはないです。ポイントは以下。

– ダウンロードした.exeやら.qdzやらを同じディレクトリに置いて、QuartusSetupWeb的なやつを実行しましょう。

アップデータは後から実行します。

– Winユーザの方、ユーザ名はアルファベットのみスペース無しをオススメします。

余計なトラブルに合わなくて済みます。後述しますが私自身トラブりました。

パス名にもスペースを含めるのは避けたほうが無難です。

– 出来るだけインストーラが指定したパスにインストールしましょう。

余計なトラブルに合わなくて済みます。

例)C:\altera\14.1

– アップデートのインストールも忘れずに。

MAX10は最新デバイスなので特に重要

USB-Blaster用のドライバインストールでハマる場合があります。

– 困ったらGoogle先生に頼りましょう。

既に他のバージョンのQuartus IIを使っている方は、消さずに残しておきましょう。

– EDAツールというのはそういうもんです。

Quartus IIのインストール

10

インストール中には特にややこしいことは聞かれないですが、TalkBackに関しては確実に「Enable sending TalkBack data to Altera」チェックを付けておきましょう。

– じゃないと一部機能が使えなくなります。

サンプルデザイン入手

11

全くのゼロから作り始めるのも良いですが、あまりお勧めできません。

– 多分面白くもありません。ピン情報とかをシコシコいれるだけですし。

以下からサンプルデザインを入手し、それをベースにしましょう。

– http://www.alterawiki.com/wiki/BeMicro_MAX_10

– 最初にEmpty Baseline Projectというのを使います。

リンクをクリックするとaltera.comのDesign Storeというところに飛びます。そこから最新版をダウンロードしましょう。

BeMicro_MAX10_Baseline.par

これで準備は完了です。

※なお、この資料で作るデザインの最終形が以下に有りますので、動かない場合は参照して下さい。https://github.com/yktakemura/BeMicro_MAX10_example/tree/master/test0

FPGAについて

12

www.google.com

www.amazon.co.jp

詳しくはそのうち書くとして…

FPGAとはなんぞや

– Field Programmable Gate Arrayの略です。フィールドでプログラム可能なゲートアレイ、ですね。

– ゲートアレイはNAND素子が敷き詰められたLSIの一種で、そこに配線層を加えてNAND同士を繋げるだけで回路が作れる、という代物です。配線層だけ設計すれば良いので、比較的安く作れました。

– FPGAでは、NAND素子の代わりにLEが敷き詰められています。

世代が進むに従って、LE以外のもの(メモリやDSP等)も実装されるようになってきました。

LEとはなんぞや

– Logic Elementの略です。

– 基本的には4bit address入力/1bit data出力の小さなSRAMと、その1bitの出力に接続されるFlip flop、及び配線で構成されます。

そのSRAMのことをLUT(Look Up Table)と言ったりします。

– 起動時にLUTの中身を書いてやれば、4入力1出力の組み合わせ回路と同等になります。

– これを沢山つなげれば、何でも回路作れそうですよね。実際そうです。

– そのLUTことSRAMの中身を設定するために、FPGAは必ずROM等のメモリとセットで運用されます。後のページでFPGA構成情報とかConfiguration情報とか出てくるのは、このSRAMに設定するデータであり、ROMの中身のことです。

MAX10について

13

Flashを積んでいるのが最大の特徴。– Flashには以下等を入れておく。

FPGA構成情報(CFM)

プログラム(UFM)

ユーザデータ(UFM)

– 他のFPGAでは必須の外付けメモリが不要、単体で立ち上がる。

PLD的

マイコン的

A/Dコンバータ内蔵– マイコン的

後は割と普通– Logic Array Blocks (LAB)

1LAB = 16LE

– 内蔵SRAM (Embedded Memory)

– 18x18bit乗算器 (Embedded Mul)

– 基本的にはCyclone IV(TerrasicDE0ボードに乗ってるやつ)にFlashが乗ったようなもの。

Quartus IIでデザイン作成

14

さあ本番です。

まずはFPGAのデザインを作ってみます。

Quartus II起動

15

では早速Quartus IIを起動しましょう。まずProjectを作ります。

File>New Project Wizardをクリック、または図のアイコンをクリック。

Project新規作成

16

Nextをクリック

Project新規作成

17

Projectを作るパス及びProject名称を決定します。

Top module名には_topを付けてみましたが、別に無くても良いです。

Nextをクリック

Project新規作成

18

Project templateの方を選択します。

Nextをクリック。

Project新規作成

19

Install the design templatesをクリック

Project新規作成

20

先ほどダウンロードした.parファイルを指定します。インストール先はどこでも良いです。

Project新規作成

21

本資料で使っているのはバージョン14.1.1ですが、ダウンロードしたのは14.1.0用デザインなので、そのままでは画面に出てきません。

Include unsupported versionsにチェックを入れ、今登録したデザインを選択します。

Finishを押します。

Project作成完了

22

Projectが出来ました。

Project構成

23

Project NavigatorのFilesタブを押すと、現在Projectに登録されているFileが表示されます。

– 試しにTop moduleとなるBeMicro_MAX10_top.vをダブルクリックして中身を見てみましょう。I/O定義だけで空っぽですね。

中身を作りましょう。メニューからTools>QsysでQsysを立ち上げます。

Qsysとは

24

Qsysでは主にIPコアを取り扱います。– 以下IPと略します。– IPとは、ざっくり言うと各種ベンダまたは個人が提供する有償無償の回路モジュールのことです。

Qsysには以下の機能があります。– IPを選択し、回路に取り込む– IP同士やクロックリセット等を配線する– アドレスマップを作る– 新規IPを登録する– RTLを生成する– テストベンチを生成する– その他

Qsysは2種類の標準バスに対応しています。– Qsysで扱うIPは基本的にこの2種類のバスのどちらかをI/Fとして持ちます。

ARM社策定AMBAバス(AXI・APB等)Altera社策定Avalonバス(Avalon-MM・Avalon-ST)クロック・リセット系のIPは例外です。

– AMBAとAvalonも自由に接続出来ます。暗黙的に変換ブリッジが挿入されます。

– 非同期ブリッジの挿入も自動です。検証用IP(Bus Function Model等、BFMと略す)をQsysで接続して、テスト環境を作ることも出来ます。

非常に便利なので、是非使いこなして下さい。古いバージョンのQuartus IIではSOPC Builderというのがついていました。こちらを使っている方も是非この機会にQsysを。

Qsys起動

25

Qsysを起動します。まずファイル名を指定しましょう。ここではプロジェクト名と同じ名前を付けておきますが、必須ではありません。

Qsys初期画面

26

Qsysが起動しました。既にclk_0というモジュールが登録されています。これはそのまま使います。

– 実際には、このclk_0は単なる外部I/Fを示しています。

まずNios IIプロセッサIP(Gen2)を追加しましょう。左上のIP Catalogの検索欄にniosと入れ検索するとすぐ見つかります。ダブルクリックで追加します。

Nios IIプロセッサ追加

27

Nios IIのパラメタ設定画面が立ち上がります。パラメタは後で設定しますので、ここではとりあえずNios II/eを選択するだけにします。

– Nios II/fの方が高性能ですが、Web Editionでは使えません。

Qsysで試しに接続

28

Finishを押すと元の画面に戻ります。Nios IIが追加されているのが確認できます。沢山エラーが出ていますね。

接続ポイントをクリックしクロックを接続してみます。

– 最初から接続されているところもありますね。

Qsysで試しに接続

29

次にresetを接続。下のエラー表示が減っていくのが分かります。

On-Chip Flash追加

30

On-Chip Flash IPを追加します。Configuration Modeが「Single Uncompressed Image」となっていることを確認しましょう。後ほど他のモードも試します。

Initialize flash contentのチェックは忘れずに外しておきます。

On-Chip Memory追加

31

必要なIPをどんどん追加しましょう。次はOn-Chip Memory IPです。Nios IIのプログラムやデータ・スタック・ヒープ領域等に使います。

パラメタはデフォルトのままでOKです。後で容量を増やしたければここで調節します。

PIO追加

32

PIOです。GPIOを使って外部を制御するのに使います。ここではLED制御に使います。

– PIOやGPIOの意味がわからない人はGoogle先生に聞きましょう。

ボードには8個LEDがついているので、Widthは8とします。入力機能は必要ないので、DirectionはOutputで良いですね。

JTAG UART追加

33

JTAG UARTです。PC上で動くデバッガとの接続に使います。パラメタはデフォルトで。

Dual Configuration追加

34

Altera Dual Configuration。これは入れなくても良いですが、一応入れておきます。

– MAX10に2つのConfiguration情報を入れる際に必要になります。

Qsysでどんどん接続

35

全て追加が終わったら、どんどん接続していきます。クロックリセットは全てのモジュールで共通、AvalonバスはNios IIと接続。Nios IIはNameを右クリックでnios2にしました。

I/Oのエクスポート

36

PIOのexternal_connectionは接続先がありませんね。これはLEDと接続するのでQsysの外に出してやる必要があります。Exportのところをクリックし、名前をつけましょう。ここでは「pio」とします。

DescriptionにConduitとありますね。これは、AvalonやAMBA以外のバス、ぐらいに思っておいてください。

Qsysのエラーを解決

37

さて、現時点でのエラーを見てみましょう。これだけ出ています。

Nios IIのリセット・例外設定

38

ではまず一番上のエラーを消してみましょう。Nios IIのところをダブルクリックしてパラメタ設定画面を開き、以下のように設定します。

– Reset Vector

On-Chip Flashに設定

– Exception Vector

On-Chip Memoryに設定

アドレスはそのままでOKです。

終わったらXを押します。

Qsysのエラーを解決

39

エラーがちょっと減りました。

Qsysでアドレスマップ設定

40

上のAddress Mapタブをクリックします。メモリマップが重複しまくっているのがわかります。これを適当に重ならないよう修正していきます。

Qsysでアドレスマップ設定

41

アドレスのところをダブルクリックで修正できます。まずはOn-Chip Memoryのアドレスを修正してみます。先頭アドレスだけ入れればOKです。

Qsysでアドレスマップ設定

42

修正できました。ちょっとエラー表示が変わりました。

この調子で一通り修正します。

Qsysでアドレスマップ設定

43

ここではこんな風に修正してみました。

– 超適当です。本番ではまじめに考えましょう。メモリは下のアドレスにそろえるとか、レジスタ系は後ろのほうにまとめるとか…

エラーがなくなったのでRTLを作ります。Generate HDLをクリック。

QsysでRTL生成

44

とりあえずは合成用のHDLがあればよいので、下のように設定します。

Generateをクリック。RTL生成が開始されます。

QsysでRTL生成

45

ちょっと待つと生成が完了します。小さいデザインなので比較的短時間で終わります。

Closeをクリック。

QsysでRTL生成

46

こんなポップアップが表示されますので確認してください。要は今Qsysで作った合成用デザイン(.qipファイル)をProjectにマニュアルで追加してやる必要があります。

– なぜ自動で登録されないのかは良くわからない…

QsysでRTL生成

47

最後にQsysメニューのGenerate>HDL Exampleを選択します。

出てきたコードをコピーしておきましょう。これを元にTop moduleを書き換えます。

一通り終わったのでQsysは閉じてよいですが、開けっ放しでも別に問題ありません。

Top module修正

48

先ほどのRTLをTop module(BeMicro_MAX10_top.v)にコピーします。

Top module修正

49

ポートに必要な信号を接続しましょう。下のようにRTLを書いて下さい。

– このボードはリセットが無いようなので、適当にプッシュボタン入力から作ります。

– 一応チャタリングキャンセルを入れてあります。こんなんで良いのかは謎。

.qipファイル登録

50

先ほどの.qipファイルをProjectに登録します。メニューのProject>Add/RemoveFiles in projectで下の画面表示。File nameのところで先ほどの.qipファイルを登録。Addボタンクリックを忘れずに。

Quartus IIでコンパイル

51

.qipファイルの追加を確認しましょう。

それではいよいよコンパイルです。メニューからProcesing>Start Compilation、または三角マークのボタンをクリック

Quartus IIでコンパイル

52

げーやってしまいました。私の環境では失敗です。どうもWin8でユーザ名に漢字とか使ってるとこうなるみたいです。しょーがない、レジストリいじるか。やったことないけど…

Quartus IIでコンパイル

53

まあ何しろテンポラリ領域を示すパス名に2バイト文字が使われてなければ良いんだろということで、私の場合ここを修正。これがベストかは知らんですが、うまく行きました。

Quartus IIでコンパイル

54

これで再挑戦。コンパイル無事完了です。

– TimeQuest Timing Analyzerのところが赤字で気になりますが、今回は無視!

Quartus II Programmer

55

では試しにFPGAを焼いてみます。その前にUSB-Blasterが認識されているか確認しましょう。

認識されていない(不明なUSBデバイスのままの)場合、ドライバの更新等を試しましょう。ドライバは\quartus\driversにあります。

Quartus II Programmer

56

Quartus IIのメニューでTools>Programmerとクリックし、Programmerを立ち上げます。

– USB-Blasterが認識されているはずです。されていない場合はHardware Setupをクリック

ではAuto Detectをクリックしましょう。

Quartus II Programmer

57

デバイスを選択します。今回のボードでは以下をチェックしましょう。

Quartus II Programmer

58

FPGAが認識されます。

FPGAの画像をクリックするとChange Fileボタンが押せるようになります。クリックしましょう。

Quartus II Programmer

59

Top module名.sofファイルがFPGAの構成情報(Configurationデータ)です。

output_filesというディレクトリに生成されているはずです。

Quartus II Programmer

60

Program/Configureにチェックを入れるとStartボタンが押せるようになるので、クリックします。

Quartus II Programmer

61

無事Program出来ました。

Failした場合は以下等を確認しましょう。

– 他にUSB-Blasterを使うアプリが立ち上がっていませんか

– 間違った.sofを指定していませんか

Nios IIを動かしてみる

62

これでFPGAは出来上がりました。

次に、Nios IIを使ってボード上のLEDを点滅させてみます。

Nios II SBTを使ってみる

63

ではNios IIのプログラムを作りましょう。Quartus IIメニューからTools>Nios II Software Build Toolsで起動します。

– コマンドラインやスタートメニューから起動してもOKです。

正体はご存知eclipseです。Workspaceは変えたければ変えてOKをクリック

Nios II SBTでProject作成

64

Fileメニューから新規Projectを作成します。BSPも必要なのでNios II Application and BSP from Templateを選択。

Nios II SBTでProject作成

65

.sopcinfoファイルを指定。これはQsysが生成するファイルで、IPのパラメタ情報やアドレスマップ等全ての情報が入っています。

Project nameは適当に。

TemplateからHello World Smallを選択

– ただのHello Worldはメモリを食います。

Finishをクリック。

Nios II SBTでコード修正

66

Projectが出来ました。Project Explorerから、生成されたtest0以下のコードhello_world_small.cを表示させてみます。

今回は、手っ取り早くこのファイルのmain()を編集します。

Nios II SBTでコード修正

67

Project Explorerからtest0_bsp以下のsystem.hを表示させてみます。Qsysで設定したアドレス等が確認できます。今回はLEDを制御するので、PIOのところを見てみます。

Nios II SBTでコード修正

68

altera_avalon_pio_regs.hに、PIOレジスタにアクセスするためのマクロがあります。これを使いましょう。

Nios II SBTでコード修正

69

こんなコードにしてみました。PIOの8本の出力に対し、0x55と0xaaを交互に出力します。500,000usのウェイトも入れてあります。

ファイル名はそのままにしていますが、気持ち悪ければリネームしてください。

Nios II SBTでビルド

70

ではBuildしてみましょう。

Buildの前にBSPのGenerateが必要な場合があります。test0_bsp右クリック>Nios II>Generate BSPで生成できます。

Nios II SBTでビルド

71

無事Build出来ました。

Nios II SBTで実機デバッグ

72

では実記にプログラムをダウンロードし、動作させて見ましょう。下の通り、Debug Configurationをクリックします。

Nios II SBTで実機デバッグ

73

左の欄のNios II Hardwareをダブルクリックします。

– そのうち一番下のv2というのに置き換わる予定です。

Nios II SBTで実機デバッグ

74

Nameを適当に変えましょう。

Project nameをクリックし、test0を選択します。

Nios II SBTで実機デバッグ

75

Target Connectionタブをクリックします。

一応右上のRefresh Connectionsをクリックしておきます。

この時点で右下のDebugボタンがグレーアウトしている場合は、System ID checksの2つのIgnore mismatched system *にチェックを入れてみましょう。

では右下のDebugをクリックして実行開始しましょう。

Nios II SBTで実機デバッグ

76

こんな画面で一旦止まります。ボタンを押して実行を進めましょう。

LEDが点滅すれば成功です!余裕があればコードを修正して点滅の仕方等変更してみて下さい。

Nios II SBTで実機デバッグ

77

さて、実機は無事動作しましたが、練習のためレジスタの内容を確認してみましょう。Memoryタブをクリックします。+ボタンを押してアドレスを設定しましょう。

Nios II SBTで実機デバッグ

78

見たいアドレスを指定します。ここではPIOのアドレスを指定してみます。

Nios II SBTで実機デバッグ

79

こんな画面になったら、適当に表示方法を選びましょう。ここではHEXにします。

Nios II SBTで実機デバッグ

80

レジスタの状態が表示されました。アドレス0x60000は0xaa000000となっていますね。ちょうど0xaaを書いている場合のようです。

メモリ初期値ファイル生成

81

では、せっかくなのでこのプログラムをFPGAの内蔵Flashに焼いてみます。右上のNios IIをクリックして元の画面に戻り、Project Explorerよりtest0右クリック>Make Targets>Buildをクリック。

メモリ初期値ファイル生成

82

mem_init_generateを選択してBuildクリック。HEXファイルが生成されます。

後ほどこのファイルと.sofファイルから.pofファイルを作り、Flashに書き込みます。

メモリ初期値ファイル生成

83

こんな感じです。アイコンがおかしなことになってますが、無視してください。

使うのはonchip_flash_0.hexの方です。

Flash書き込み前に色々確認

84

幾つか確認事項があります。まずQuartus IIに戻ってメニューよりAssignments>Deviceをクリック。

Flash書き込み前に色々確認

85

Device and Pin Optionsをクリック

Flash書き込み前に色々確認

86

Configuration schemeがInternal Configurationになっていることを確認。

Configuration modeがSingle Uncompressed Imageになっていることを確認。

– ここでの設定が、QsysのOn-Chip Flashの設定と一致している必要があります。

違っていたら、場合によってはQsysの再GenerateおよびQuartus IIでの再コンパイルが必要です。

Flash書き込み前に色々確認

87

次にBSPの設定を確認します。Nios II SBTで、Project Explorerよりtest0_bspを右クリック>Nios II>BSP Editorをクリック

Flash書き込み前に色々確認

88

BSP Editorが起動しました。下の画面と同じ状態になっているか確認します。

Flash書き込み前に色々確認

89

Linker Scriptタブをクリックしてください。下の画面と同じ状態になっているか確認します。

ProgrammerでFlash書き込み

90

では.pofファイルを作ります。Quartus IIのメインメニューよりFile>Convert Programming Filesをクリック

ProgrammerでFlash書き込み

91

Programming file typeはProgrammer Object File(.pof)を選択

その右下のプルダウンメニューでInternal Configurationを選択

出力ファイル名は適当に。

– たまに意図しないディレクトリにいつの間にかなっていてハマることがあるので、確認しましょう。

Options/Boot infoをクリック

ProgrammerでFlash書き込み

92

ここでプログラムファイルを指定します。一番下のUFM sourceをLoad memory fileに変更し、File pathで先ほどのHEXファイルを指定しましょう。

ProgrammerでFlash書き込み

93

最後に.sofファイルを指定します。下の枠内のSOF Dataをクリックして、右のAdd Fileをクリック。.sofを選択します。

ProgrammerでFlash書き込み

94

では書き込んでみましょう。先ほど.sofを書いたときとはちょっと画面が異なるのに注意。

– CFM0はConfiguration Flash Memory0の略で、FPGAのConfigurationデータ専用です。

モードによってはCFM1も使えます。

– UFMはUser Flash Memoryの略で、ユーザの好きな情報を格納できます。

書き込み終了と同時にLEDが点滅開始するはずです。USBケーブルを抜いて電源を一旦落とし、再起動で正常動作するか確認しましょう。

FPGA内部の波形を見てみる

95

これで基本的なFPGAの開発は経験しました。

次に、より高度なデバッグ手法として、FPGA内部の信号線の観察をしてみましょう。

SignalTap IIとは

96

SignalTap IIはFPGAの内部信号を観測するためのツールです。

– ロジック・アナライザをFPGA内部に当てるようなものです。

– ロジック・アナライザ同様、様々なトリガ条件を設定できます。

取得した波形を見るとSimulation波形に似ていますが、サンプリングのタイミングを指定されたクロックまたは信号で行う(つまりそのクロック以下の周期の信号は記録できない)ことに注意してください。

波形データは内部SRAMに格納します。従って、FPGAに応じてサイズに制限があります。

波形取得回路を自動挿入します。従って、パンパンにユーザ回路を入れていると使えない可能性があります。

SignalTap II起動

97

では試しにNios IIがどのようにInstructionを読んでいるか波形で確認してみましょう。Quartus IIのメインメニューからTools>SignalTap II Logic AnalyzerクリックでSignalTap IIを起動します。

SignalTap IIでクロック指定

98

起動しました。まずはClockを指定します。Clockのところの右のボックスをクリック。

SignalTap IIでクロック指定

99

右上のボタンをクリック

SignalTap IIでクロック指定

100

OptionsのFilterでSignalTap II: pre-synthesisを選択します。このモードだと信号名がそのままなので選びやすいです。

Clockを選択するので、高速化のためNamedのところに*CLKと入力します。

– 大きなFPGAでは特に重要

SignalTap IIでクロック指定

101

今回はSYS_CLKを使います。選択し>ボタンをクリック。右側にコピーします。OKをクリック。

SignalTap IIで信号選択

102

次に観測する信号を登録します。中央のDouble-click to add nodesとある辺りをダブルクリック

SignalTap IIで信号選択

103

Clockの時と同じ要領で、見たい信号をどんどん追加していきます。Insertボタンクリックを忘れずに。階層構成やノード名はQsysで作ったのと同じイメージになります。ここではNios IIの命令リードバス関連を全て登録します。

SignalTap IIでトリガ設定

104

最後にトリガ条件(波形取得を開始または終了する条件)を指定します。Trigger Conditionsのところを右クリックで設定変更。

ここではr_reset_n信号の立ち上がり、つまりリセット解除をトリガとします。AND又はOR条件も合わせて指定。実戦では、より複雑な条件を定義することが多いです。詳しくは別資料を。

SignalTap II設定終了

105

Sample depth(何回データサンプルするか)を指定します。もちろん深くしたほうがたくさん取れてデバッグに役に立ちますが、FPGA内部のRAMを使うので大きさに限界があります。

– Instanceのところに使用リソース情報が表示されています。

右上のUSB-Blasterおよびダウンロードファイルの設定は、この時点で行っても後でもOKです。

最後にメニューよりProcessing>Start Compilationをクリック

SignalTap II設定終了

106

以下のようなポップアップが表示されます。SignalTap IIではFPGAに専用回路を入れますので、Quartus IIに情報を登録しておく必要があります。この場合、下に指定された.stpファイルがそれにあたります。

SignalTap IIファイル

107

コンパイル中のQuartus IIの画面に戻ってみます。.stpファイルが正しくFilesのところに表示されているか確認しましょう。

SignalTap IIの設定を変更すると再コンパイルが必要ですが、この場合Rapid RecompileでもOKです。多少早くコンパイルが終わります。

SignalTap IIで波形を見てみる

108

コンパイルが終わったら、.pofファイルを作り、SignalTap IIの画面に戻ります。Programmerで焼いてもOKですが、ここではSignalTap IIの画面でFPGAを書き込んで見ます。

右上のJTAG Chain Configurationのところを修正し、下の画面のようにします。

書き込みボタン(FPGAの絵)をクリック

SignalTap IIで波形を見てみる

109

書き込みが終わると、Instance ManagerのRun Analysis(一回だけ波形取得)またはAutorun Analysis(トリガ条件が成立するたびに波形アップデート)がクリック出来るようになっているはずです。

Run Analysisボタンをクリックします。トリガ待ち状態になります。

SignalTap IIで波形を見てみる

110

プッシュボタンSW1(PB[1])にリセットを割り当てましたね。押してリセットをかけてみます。

波形が取得できるはずです。i_addressを見ると、アドレス0x0から実行開始し、0x8から0xcまでのループを実行していますね。これはOn-Chip FlashからOn-Chip Memoryにプログラムをコピーする部分を実行しています。

SignalTap IIで波形を見てみる

111

再びRunし、今度はリセットボタンではなくSignalTap II画面のStop Analysisボタンで止めてみます。押した時点の波形が取得できます。

Nios IIが命令を規則的に読んでいるのが分かりますね。

回路を書いてみる

112

波形は正しく見えましたか?

次に、RTLで回路を作って、これまでに作った環境に組み込んでみましょう。

LED制御モジュール作成

113

今度はRTLでLEDを制御してみましょう。点滅は飽きたので、PWM制御的なことをして、輝度をレジスタで調整できるようにしてみます。

自作モジュールは、Qsysに登録して接続する方法と、Qsysから接続用のバスを出し、Top module等で接続する方法の2通りあります。

– QsysでIP化すると、Avalon/AMBAの場合Qsysで接続できますしSimulation環境を作るのも楽ですが、登録作業が必要なのと、修正が入った場合Qsysで再Generateしなければならない煩雑さがあります。

今回はQsysに登録する方法を試します。

LED制御モジュール実装例1

114

サンプルコードを準備して下さい。

SystemVerilog文法を使ったので、ledctrl.svというファイル名でセーブします。場所はどこでもOKですが、管理しやすいところにしましょう。

ここではレジスタ設定用のバスとしてAvalon Memory-Mapped Interfaceを使いました。

– Avalonのほうが、Out of orderの概念が無い等仕様がシンプルで、開発も格段に楽です。

– 最大性能を発揮させたいならAXIかもしれません。

Avalonスペック通りの信号名にすることで、Qsysが色々自動判定してくれます。

– 負論理は末尾に_nや_xを付ける、先頭にnを付ける等色々流派がありますが、末尾_xはQsysが判定してくれないようです。

module ledctrl

(

input wire clk,

input wire reset_n,

input wire read,

input wire write,

input wire [7:0] address,

input wire [3:0] byteenable,

input wire [31:0] writedata,

output wire waitrequest,

output reg readdatavalid,

output reg [31:0] readdata,

output reg [3:0] led

);

// <Register specification>

// adr0: [0]: turn on led[0]

// [1]: turn on led[1]

// [2]: turn on led[2]

// [3]: turn on led[3]

// adr1: [7:0]: brightness of led[0]

// [15:8]: brightness of led[1]

// [23:16]: brightness of led[2]

// [31:24]: brightness of led[3]

サンプルコード (1/3)

LED制御モジュール実装例2

115

assign waitrequest = 0;

reg [3:0] r_turnon;

reg [3:0][7:0] r_bright;

reg [3:0][7:0] r_cnt;

always @(posedge clk or negedge reset_n) begin

if (!reset_n)

r_turnon <= 0;

else if (write & (address == 0) & byteenable[0])

r_turnon <= writedata[7:0];

end

always @(posedge clk or negedge reset_n) begin

if (!reset_n)

r_bright <= 0;

else if (write & (address == 1)) begin

for(int i = 0; i < 4; i++)

if (byteenable[i])

r_bright[i] <= writedata[i*8+:8];

end

end

always @(posedge clk or negedge reset_n) begin

if (!reset_n)

readdata <= 0;

else if (read) begin

case (address)

0: readdata <= {24'h0, r_turnon};

1: readdata <= r_bright;

default: readdata <= 32'hx;

endcase

end

end

サンプルコード (2/3)

LED制御モジュール実装例3

116

always @(posedge clk or negedge reset_n) begin

if (!reset_n)

readdatavalid <= 0;

else

readdatavalid <= read;

end

always @(posedge clk or negedge reset_n) begin

if (!reset_n)

r_cnt <= 0;

else begin

for(int i = 0; i < 4; i++)

if (r_turnon[i])

r_cnt[i] <= r_cnt[i] + 1;

end

end

always @(posedge clk or negedge reset_n) begin

if (!reset_n)

led <= 'hf;

else begin

for(int i = 0; i < 4; i++)

if (r_turnon[i] & (r_cnt[i] <= r_bright[i]))

led[i] <= 0;

else

led[i] <= 1;

end

end

endmodule // ledctrl

サンプルコード (3/3)

LED制御モジュール実装

117

仕事でVerilogを書くなら、私は必ず1’b1, 4’hf等と幅を明記しますが、最近はあまり気にしなくても大丈夫のようです。

– ただ32bit超えるとやっぱり不安…

設定レジスタは2種類しかなく、アドレスデコードも0と1しか見ていません。

– つまり、本来は8bit幅のアドレスなんぞ必要ありません。後ほどダンプを見た時に、アドレス0x0と0x1以外がどういう扱いになるか確認してみてください.

LED制御モジュール登録

118

では作ったモジュールをQsysに登録してみましょう。メニューよりNew Componentをクリックします。

LED制御モジュール登録

119

モジュール名称等を登録。他は空欄でもOKです。

LED制御モジュール登録

120

Synthesis Filesに先ほど作ったledctrl.svを追加し、Analyze Synthesis Filesを押します。RTLにSyntax Error等あると、ここでエラーが出ます。

LED制御モジュール登録

121

エラーが無ければこんな感じ。Closeをクリック。

LED制御モジュール登録

122

Simulation用のファイルもそのままで良いので、Copy from Synthesis Filesをクリックしてコピーします。お、幾つかエラーが出ているようですね。これはSystemVerilogのエラーではありません。

LED制御モジュール登録

123

Signalsタブをクリックします。led出力がavalonと誤判定されてしまっているようです。

LED制御モジュール登録

124

修正しました。エラーがちょっと減りました。

LED制御モジュール登録

125

Interfacesタブをクリックします。Associated Resetのところがnoneになっていますね。他は大丈夫そうです。

LED制御モジュール登録

126

修正しました。まだエラーが一つ残っています。

LED制御モジュール登録

127

エラーの原因はMaximum pending read transactionsでした。ここは1以上にする必要があります。数字の意味は別資料を参照ください。

Finishをクリックします。

LED制御モジュール登録

128

設定した情報をまとめた.tclを作ってくれました。Saveしましょう。

バス幅等parameterize出来るようにRTLを書くと、もっと高度なモジュールになります。

LED制御モジュール完成

129

ledctrlモジュールが完成しました。早速Qsysでつなげます。

LED制御モジュール接続

130

led接続用のConduitポートは、ledと名称変更しておきます。

LED制御モジュール接続

131

後はアドレスマップを直して完成。Generateしましょう。

LED制御モジュール接続

132

Qsysモジュールのポートが増えたので、またHDLサンプルをコピーしておきます。

Top module再修正

133

Top moduleを修正します。今回は8つのLEDのうち、4つをPIO制御、残り4つを今回のモジュール制御とします。

LED制御モジュール評価

134

作った.sofファイルをFPGAに書き込んだら、Nios II SBTを起動し、デバッグ開始します。ledctrlはアドレス0xa0000に設定したので、そこを見てみます。

0xa0000に0x0f000000を書き込んでLEDをオンにしてみましょう.

LED制御モジュール評価

135

アドレス0xa0004に適当な数字を入れてみます。それっぽい輝度のばらつきになったでしょうか。

– 全然線形に変化してる感じがないですね。人の目の特性でしょうか。

全部入りサンプルを使ってみる

136

大分実践的になってきました。

ここで、別のサンプル環境を試してみます。

全部入りサンプルを使う

137

FPGA開発はハマるポイントが多いです。

– ハード開発自体の難しさ

– ツール使いこなしの難しさ

– 運が悪いとツールやFPGAのバグに当たることも…

そのため、勝負したいポイント以外は出来るだけ手を抜くことが重要です。

– 何しろ実績のある設計・実績のあるメソッドを選んで使うのが良さそう

適切なサンプルをベースとして使うのは良い方法です。

– 全部入りサンプルは候補としてピッタリです。

ここでは、そのボードで使える機能を出来るだけ多くカバーしたサンプルを全部入りと称しています。

– 他にも色々あるので、Design Storeやrocketboards.org、alterawiki等を探してみましょう。

– 私も普段からそうやってます。

全部入りサンプル取得

138

http://www.alterawiki.com/wiki/BeMicro_MAX_10経由またはwww.altera.com 経由でV14.1.0用Full Featured Reference Designをダウンロードします。

前述の要領で、Full Featured Reference Designを使ったプロジェクトを作成します。

前回同様、V14.1.1用サンプルではないので注意。

全部入りサンプルのQsys

139

元々の問題なのかV14.1.1を使用するせいなのか分かりませんが、このサンプルはそのままでは動かないようです。修正しながら進めます。

まずはQsysを起動します。

On-Chip Flash修正

140

On-Chip Flashのパラメタ設定画面に行き、下の画像のように修正します。

Generateし、Quartus IIに戻ります。

全部入りサンプル修正

141

Device and Pin Optionsを表示し、下のようになっていることを確認、一致していない場合は修正します。

全部入りサンプル修正

142

Qsysファイル(nios_system.qip)のパス名がおかしいので、元のものを削除後再登録します。

全部入りサンプル修正完了

143

修正しました。これでコンパイル可能になるはずです。

全部入りサンプル改造

144

Qsysで、全部入りから不要なものを削ってみます。今回はSDRAM周りだけ残しました。

全部入りサンプル改造

145

削ったので、当然元のTop ModuleとはI/Oが合わなくなります。HDL Exampleを確認・コピーしておきます。

Top module修正

146

なぜかこっちのサンプルはTop ModuleがVHDLですが、気にせずtop.vhdを修正します。VHDLを知らなくてもQsysでコピーしたExampleを参考に適当に削れば何とかなります。これでコンパイル&書き込み。

全部入りサンプル改造版評価

147

試しにNios II SBTでSDRAMを触ってみましょう。0x800000番地からがSDRAMのようなので、Memoryタブで内容を確認、R/Wを試します。Suspend状態にしておくことを忘れずに。

Simulationしてみる

148

最後に、Simulationツールで動作を確認してみましょう。

ModelSimを試す

149

いきなり実機とか、ホントはダメです。– SignalTap IIがあるとはいえ、実機でのデバッグは大変です。

本来はまずSimulationでデバッグ・検証を行い、実機に移行するべきです。– 何ならテストファーストが望ましいかも

とはいえ、仕事じゃないですしそこはバランスということで。

Qsysのテストベンチ生成機能及びNios II SBTを使うと、簡単にNios IIのプログラム実行のSimulationを行うことが出来ます。

テストベンチ・テストベクタをVerilogで色々作らなくても、Nios IIのプログラムで様々なテストをすることが出来るので楽です。

– 外部モジュールのテストも、前述のPIO IPとかを上手く使えば。

一方、Top moduleのSimulationはそれなりに敷居が高いです。– 真面目にやるならSDRAMの動作モデルを探してきたりとか。

– とはいえ、色々支援環境があるので、ゼロからSim環境を作るよりは楽です。

– 自動化が進みすぎて、ASIC開発者が使うと混乱するのが玉にキズ

ということで、せっかくModelSimがタダで使えるんですし、使わない手はありません。– ModelSimはASIC設計等でも使われる、Mentor Graphics社のSimulatorです。

– Web Edition添付のものは、有料のものより動作速度がかなり遅くなっています。

HWのSimulationとは

150

以下の3つより構成される環境をSimulatorにかけ、実行します。

– テストベンチ

Simulation環境及び検証対象モジュールを含んだHDLのモジュールです。

外部からデータを入れるためのタスクや、信号を時系列で制御するための記述を含む場合もあります。

ファイルから入力データをリードし、それを入力する場合もあります。

期待通りに動作したか確認するモジュールを含む場合もあります。

– テストベクタ

テストベンチに入力するテスト用のデータというイメージです。

Verilogでゴリゴリ書く場合も多いです。

– DUT

Device Under Test

検証対象モジュールです。テストはTop moduleに対して行う場合もありますし、ひとつの機能モジュールに対してテストを行う場合もあります。

SimulatorにはVerilog専用のものやVHDL専用のもの、混合環境対応のものがあります。

– Quartus II添付のModelSimは混合環境には対応していません。

入力データ

DUT期待値比較

テストベクタ

テストベンチ

テストベンチを生成

151

先ほどの全部入りサンプルをSimulationにかけてみましょう。まずQsysで、テストベンチを生成します。

その際、SDRAMの動作モデルを接続するようにしてみましょう。SDRAM Controllerのパラメタ設定を開き、以下にチェックを入れます。

テストベンチを生成

152

Qsysのメニューより、Generate>Generate Testbench Systemをクリックします。

Standard, BFMs for standard Qsys interfacesを選択します。

– 後述しますが、実戦を考えると「Simple, BFMs for clocks and resets」にしてSDRAMは使わない、というのが良いかもしれませんが、ここは練習がてらこれで。

Generateをクリック。

テストベンチ修正

153

nios_system\testbench\nios_system_tb\simulation\nios_system_tb.vがテストベンチのTop moduleです。

中身を確認しましょう。Qsysで作ったnios_systemモジュールやクロックリセット生成モジュール、SDRAM動作モデル等がインスタンス化されているはずです。

自作モジュールをQsysのモジュールの外に付けたい場合、このファイルを編集するのが良いでしょう。

面倒なのでリセットは共通にしてしまいましょう。下を参考にテストベンチを修正して下さい。sdram_pll_areset_conduit_exportのほうは正論理なので注意。

nios_system nios_system_inst (

.clk_clk (nios_system_inst_clk_bfm_clk_clk),

.led_pio_export (nios_system_inst_led_pio_export),

.reset_reset_n (nios_system_inst_reset_bfm_reset_reset),

.sdram_clkout_clk (),

.sdram_pll_areset_conduit_export (!nios_system_inst_reset_bfm_reset_reset), // modified

.sdram_pll_locked_conduit_export (nios_system_inst_sdram_pll_locked_conduit_export),

.sdram_pll_phasedone_conduit_export (nios_system_inst_sdram_pll_phasedone_conduit_export),

.sdram_wire_addr (nios_system_inst_sdram_wire_addr),

.sdram_wire_ba (nios_system_inst_sdram_wire_ba),

.sdram_wire_cas_n (nios_system_inst_sdram_wire_cas_n),

.sdram_wire_cke (nios_system_inst_sdram_wire_cke),

.sdram_wire_cs_n (nios_system_inst_sdram_wire_cs_n),

.sdram_wire_dq (nios_system_inst_sdram_wire_dq),

.sdram_wire_dqm (nios_system_inst_sdram_wire_dqm),

.sdram_wire_ras_n (nios_system_inst_sdram_wire_ras_n),

.sdram_wire_we_n (nios_system_inst_sdram_wire_we_n)

);

テストベンチ修正

154

ちゃんとしたSimulationではSDRAMに初期値なんぞ与えませんが、ここでは設定します。このレベルのSimulationではこれで十分です。

– Nios II SBTが生成するSDRAM初期値ファイルはsdram.datという名称なので、以下のように修正します。

もちろんSDRAMに初期値をロードする部分を作りこんでも可です。

実動作では、Nios II用のROMデータを作る際、ブートコピアと呼ばれるプログラムをROMからRAMにコピーするコードが自動挿入されそれが最初に起動しますが、今回のSimulationのフレームワークではこの動作はテスト出来ません。そのため、SDRAMモデルに初期値を与えるという方法を取ります。

altera_sdram_partner_module #(.INIT_FILE("sdram.dat")) sdram_my_partner (

.clk (sdram_my_partner_clk_bfm_clk_clk),

.zs_dq (nios_system_inst_sdram_wire_dq),

.zs_addr (nios_system_inst_sdram_wire_addr),

.zs_ba (nios_system_inst_sdram_wire_ba),

.zs_cas_n (nios_system_inst_sdram_wire_cas_n),

.zs_cke (nios_system_inst_sdram_wire_cke),

.zs_cs_n (nios_system_inst_sdram_wire_cs_n),

.zs_dqm (nios_system_inst_sdram_wire_dqm),

.zs_ras_n (nios_system_inst_sdram_wire_ras_n),

.zs_we_n (nios_system_inst_sdram_wire_we_n)

);

Nios II SBTでSim準備

155

Nios II SBTを起動します。私は一応test1_2という名前の新しいProjectを作りました。

Main関数をこんな風に修正します。恐ろしいコードですね。後はいつものビルド。

– SDRAMはアドレス0x800000から始まってます。0x900000あたりは誰も使っていないはず。

Nios II SBTでSim準備

156

Project右クリック>Run AS>Run Configurationsをクリック。

ModelSim起動

157

左側のNios II ModelSimのところをダブルクリック。Project name等を下のように設定します。

Runをクリック。ModelSimが立ち上がります。

ModelSim起動完了

158

しばらく待つと、ここまで行くはずです。あともう一枚ウィンドウが出てるはず。

– 今回はNios II SBT経由で立ち上げましたが、別の方法もあります。

ModelSimで見たい信号選択

159

Objectsタブをクリックします。ここで見たい信号を選んでいきます。

ModelSimで見たい信号選択

160

もう一枚のウィンドウで見たいモジュールを選択します。ここではNios IIのバスを見たいので、cpuを選択。

ModelSimで見たい信号選択

161

元のウィンドウにはNios IIの信号が表示されたはずです。見たい信号上で右クリック>Add Waveし、Nios IIのバス関連の信号を追加していきます。ここではi_で始まる信号(命令バス)とd_で始まる信号(データバス)を追加しましょう。

ひと通り追加したらWaveタブをクリックしてみます。クロックリセットも追加で。

足された信号確認

162

ちゃんと足されてそうですね。ではSimulationを流してみましょう。Transcriptタブに移動します。

Simulation実行

163

run 1msと入力し、リターン。これでSimulationが1ms分走ります。

動かない…

164

…エラーで止まっちゃいますね。これは私も予想外でした。-ボタンを連打してクロック波形が見れるぐらいまで縮小し、波形を確認しましょう。i_readdataに不定が乗ってますね。

– 赤で示された信号は値がゼロにも1にも確定できないということで、これを不定と言います。

調べたところ、どうもSDRAMモデルのバグの様子。困ったもんですねこりゃ。

Simulationが動かない原因

165

モデルの開発元に文句は言うとして、とりあえず動くようにしてみましょう。

nios_system\testbench\nios_system_tb\simulation\submodules\altera_sdram_partner_module.vが該当するファイルになりますが、中身見ても作者の趣味なのかイマイチ分からんコードですねこりゃ。

以下を修正すると何となく動きそうでは有りますが…173行目あたりです。これで再度流してみましょう。ホントはこんな適当な直し方ダメですよ。

一旦Clean Project後、ビルドし同じ要領でModelSimを動かして下さい。

今度はrun 2msと実行し、ちょっと長めに流してみましょう。

//assign index = latency - 1'b1;

assign index = latency;

ssign mask = read_mask;

assign zs_dq = read_valid ? read_temp : {16{1'bz}};

Simulation再実行

166

今度は「Hello from Nios II!」と表示されましたね。波形も見てみましょう。

ModelSimで波形閲覧

167

下の画像は波形の最後のところです。前述のとおり、i_read等i_で始まる信号が、Nios IIのInstruction master、つまり命令リード用のAvalon-MM busです。ずっと同じアドレスを読んでいますね。main()のwhile(1);を実行しているようです。

バスの数字の表示がHEXになっていますね。Msgsの列の数字を右クリック>Radix>HEX等で変更できます。

ModelSimで波形閲覧

168

中間らへんを見てみました。d_read等d_で始まる信号がNios IIのData master、つまりデータリード用のAvalon-MM busです。アドレス0x900000からインクリメントしてライトしていっていますね。

ModelSimまとめ

169

SDRAMさえ使わなければ、テストベンチの修正からモデルのバグフィックスまで全て不要です。ですんで、結論としてはOn-chip RAMのみでSimしておくのが楽っぽいですね。

その場合、前述のとおり外部につなげるのはクロックとリセットのみで良くなるので、テストベンチのGenerate時は「Simple, BFMs for clocks and resets」のほうでOKになります。

こういうバグ、FPGAの世界では結構ありますので…

– ちょっと前にも、某社のFPGAツールに対する呪いの言葉がTwitter上で散見されましたね

おまけ

170

おまけったらおまけ

おまけ

171

FPGAのConfigurationデータを圧縮することで、2つのデータを入れることが出来ます。で片方を書き換える、とかが可能です。IoT時代を見越しているんでしょうか。

– CFM0/1

– オンボードのジャンパで2つのデータを切り替えられます。

2つ目のデータは書き換え可能に設定できます。

– Nios IIでCFM1を書き換えることも。

おまけ

172

当然.pof生成時にも2つの.sofを登録します。

書き込み時にも、CFM0/1の2つが現れます。

書き込み後、ボード上のジャンパJ3で2つのConfigurationが切り替え可能になります。

173

おしまい