$30で始めるfpga
TRANSCRIPT
BeMicro Max10 FPGA Eva Kit
2
MAX10という安価なFPGA搭載。ちっちゃい。
MiniUSBでPCとつなぐだけ– USB-Blaster内蔵
USB-BlasterはUSB経由でFPGAにプログラムするためのシステムです。
– USBつなぐと電源もON
ボードとケーブル以外、DVDも説明書も何もついていないという割り切りの良さ
ただし搭載FPGAが10M08なので、回路はあまり入らない
で…
この資料の対象者
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が乗ったようなもの。
Project新規作成
21
本資料で使っているのはバージョン14.1.1ですが、ダウンロードしたのは14.1.0用デザインなので、そのままでは画面に出てきません。
Include unsupported versionsにチェックを入れ、今登録したデザインを選択します。
Finishを押します。
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初期画面
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が追加されているのが確認できます。沢山エラーが出ていますね。
接続ポイントをクリックしクロックを接続してみます。
– 最初から接続されているところもありますね。
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で良いですね。
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以外のバス、ぐらいに思っておいてください。
Nios IIのリセット・例外設定
38
ではまず一番上のエラーを消してみましょう。Nios IIのところをダブルクリックしてパラメタ設定画面を開き、以下のように設定します。
– Reset Vector
On-Chip Flashに設定
– Exception Vector
On-Chip Memoryに設定
アドレスはそのままでOKです。
終わったらXを押します。
Qsysでアドレスマップ設定
43
ここではこんな風に修正してみました。
– 超適当です。本番ではまじめに考えましょう。メモリは下のアドレスにそろえるとか、レジスタ系は後ろのほうにまとめるとか…
エラーがなくなったのでRTLを作ります。Generate HDLをクリック。
QsysでRTL生成
46
こんなポップアップが表示されますので確認してください。要は今Qsysで作った合成用デザイン(.qipファイル)をProjectにマニュアルで追加してやる必要があります。
– なぜ自動で登録されないのかは良くわからない…
QsysでRTL生成
47
最後にQsysメニューのGenerate>HDL Exampleを選択します。
出てきたコードをコピーしておきましょう。これを元にTop moduleを書き換えます。
一通り終わったのでQsysは閉じてよいですが、開けっ放しでも別に問題ありません。
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 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
59
Top module名.sofファイルがFPGAの構成情報(Configurationデータ)です。
output_filesというディレクトリに生成されているはずです。
Quartus II Programmer
61
無事Program出来ました。
Failした場合は以下等を確認しましょう。
– 他にUSB-Blasterを使うアプリが立ち上がっていませんか
– 間違った.sofを指定していませんか
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でコード修正
69
こんなコードにしてみました。PIOの8本の出力に対し、0x55と0xaaを交互に出力します。500,000usのウェイトも入れてあります。
ファイル名はそのままにしていますが、気持ち悪ければリネームしてください。
Nios II SBTでビルド
70
ではBuildしてみましょう。
Buildの前にBSPのGenerateが必要な場合があります。test0_bsp右クリック>Nios II>Generate BSPで生成できます。
Nios II SBTで実機デバッグ
75
Target Connectionタブをクリックします。
一応右上のRefresh Connectionsをクリックしておきます。
この時点で右下のDebugボタンがグレーアウトしている場合は、System ID checksの2つのIgnore mismatched system *にチェックを入れてみましょう。
では右下のDebugをクリックして実行開始しましょう。
メモリ初期値ファイル生成
81
では、せっかくなのでこのプログラムをFPGAの内蔵Flashに焼いてみます。右上のNios IIをクリックして元の画面に戻り、Project Explorerよりtest0右クリック>Make Targets>Buildをクリック。
メモリ初期値ファイル生成
82
mem_init_generateを選択してBuildクリック。HEXファイルが生成されます。
後ほどこのファイルと.sofファイルから.pofファイルを作り、Flashに書き込みます。
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をクリック
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書き込み
94
では書き込んでみましょう。先ほど.sofを書いたときとはちょっと画面が異なるのに注意。
– CFM0はConfiguration Flash Memory0の略で、FPGAのConfigurationデータ専用です。
モードによってはCFM1も使えます。
– UFMはUser Flash Memoryの略で、ユーザの好きな情報を格納できます。
書き込み終了と同時にLEDが点滅開始するはずです。USBケーブルを抜いて電源を一旦落とし、再起動で正常動作するか確認しましょう。
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でクロック指定
100
OptionsのFilterでSignalTap II: pre-synthesisを選択します。このモードだと信号名がそのままなので選びやすいです。
Clockを選択するので、高速化のためNamedのところに*CLKと入力します。
– 大きなFPGAでは特に重要
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が命令を規則的に読んでいるのが分かりますね。
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制御モジュール登録
120
Synthesis Filesに先ほど作ったledctrl.svを追加し、Analyze Synthesis Filesを押します。RTLにSyntax Error等あると、ここでエラーが出ます。
LED制御モジュール登録
122
Simulation用のファイルもそのままで良いので、Copy from Synthesis Filesをクリックしてコピーします。お、幾つかエラーが出ているようですね。これはSystemVerilogのエラーではありません。
LED制御モジュール登録
127
エラーの原因はMaximum pending read transactionsでした。ここは1以上にする必要があります。数字の意味は別資料を参照ください。
Finishをクリックします。
LED制御モジュール登録
128
設定した情報をまとめた.tclを作ってくれました。Saveしましょう。
バス幅等parameterize出来るようにRTLを書くと、もっと高度なモジュールになります。
LED制御モジュール評価
134
作った.sofファイルをFPGAに書き込んだら、Nios II SBTを起動し、デバッグ開始します。ledctrlはアドレス0xa0000に設定したので、そこを見てみます。
0xa0000に0x0f000000を書き込んでLEDをオンにしてみましょう.
全部入りサンプルを使う
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用サンプルではないので注意。
Top module修正
146
なぜかこっちのサンプルはTop ModuleがVHDLですが、気にせずtop.vhdを修正します。VHDLを知らなくてもQsysでコピーしたExampleを参考に適当に削れば何とかなります。これでコンパイル&書き込み。
全部入りサンプル改造版評価
147
試しにNios II SBTでSDRAMを触ってみましょう。0x800000番地からがSDRAMのようなので、Memoryタブで内容を確認、R/Wを試します。Suspend状態にしておくことを忘れずに。
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あたりは誰も使っていないはず。
ModelSimで見たい信号選択
161
元のウィンドウにはNios IIの信号が表示されたはずです。見たい信号上で右クリック>Add Waveし、Nios IIのバス関連の信号を追加していきます。ここではi_で始まる信号(命令バス)とd_で始まる信号(データバス)を追加しましょう。
ひと通り追加したらWaveタブをクリックしてみます。クロックリセットも追加で。
動かない…
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}};
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上で散見されましたね
おまけ
171
FPGAのConfigurationデータを圧縮することで、2つのデータを入れることが出来ます。で片方を書き換える、とかが可能です。IoT時代を見越しているんでしょうか。
– CFM0/1
– オンボードのジャンパで2つのデータを切り替えられます。
2つ目のデータは書き換え可能に設定できます。
– Nios IIでCFM1を書き換えることも。
おまけ
172
当然.pof生成時にも2つの.sofを登録します。
書き込み時にも、CFM0/1の2つが現れます。
書き込み後、ボード上のジャンパJ3で2つのConfigurationが切り替え可能になります。