Qsysを使ってNios IIを組み込んだモジュールを作成する

またしても忘却曲線の彼方になりつつなるVerilogの勉強を再開した。
今回はこちらの本を片手に格闘中だ。

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

この本は初心者向けのVerilog文法や簡単な回路の組み方のような事にはほとんど触れない。
一方で、読んで実際にVerilogを書いていくうちに、"初めてのVerilog"のような本には書かれていないVerilogの基礎が身につくようになっている。
良書だ。
さて、この本の第5章でNios IIの組み込みがでてくる。
Quartus IIには使いごたえのある各種IPが含まれている。
その一つがNios IIというSoft IPのマイクロコントローラ、つまりマイコンだ。
Nios IIも含めたIPを組み合わせてモジュールを作るSOPC Builderというツールも含まれている。
この本ではSOPC Builderを使ってNois IIを組み込むことにだいぶページが割かれているのだが、筆者の使っているQuartus II 13.1(Cyclone IIIをサポートする最新のIDE)では、SOPC BuilderがQsysに完全に置き換えられているのだ。
この本の巻末にもQsysの使い方は簡単に触れてある。
これを元にこの本の第5章の内容をQsysyでやってみた。
例によって忘却曲線の彼方とならないように、ここに詳細を書いておく。

Quartus IIでプロジェクトを作成する

これは本の指定通り、プロジェクト名を"nios2pio"とする。
プロジェクトの作成方法はこちら

Qsysを開く

Quatrus IIのメニューから、"Tools" -> "Qsys"で開く。

QsysでIPを組み込む

"Library"ペインからIPを選択し、"Add"ボタンを押すことでモジュールに組み込むことができる。
今回使用するIPは下記の通り。

追加の際にでるダイアログで、"Nios II/e"を指定する。

  • "Memories and Memory Controllers" -> "On-chip" -> "On-chip Memory (RAM or ROM)"

追加の際にでるダイアログで、"Size" -> "Total memory size"を"8192(byes)にする。

  • "Peripherals" -> "Microcontroller Peripherals" -> "PIO (Parallel I/O)"

これは2つ組み込む。
一つは追加の際にでるダイアログで、"Width"を"8"bit、"Direction"を"Output"(それぞれデフォルトのまま)とする。
もう一つは、"Width"を"4"bit、"Direction"を"Input"とする。

  • "Interface Protocols" -> "Serial" -> "JTAG UART"
  • "Peripherals" -> "Debug and Performance" -> "System ID Peripheral"

それぞれデフォルトのままで追加する。

クロックとリセットを接続する

下の図で、赤丸のついているところをクリックし、CLK IPと"clk"と"clk_reset"を各IPのclk、resetと接続する。

データバスを接続する

上の図で、青丸のついているところをクリックし、Nios IIのデータバスとメモリー、PIO、JTAG、System IDのデータバスを接続する。

命令バスを接続する

上の図で、緑丸のついているところをクリックし、Nios IIの命令(instruction)バスとメモリーを接続する。

PIOの入出力をモジュールの宣言にexportする

オレンジ色の部分をダブルクリックし、各PIOの入力、出力をモジュールの宣言にexportする。
ダブルクリックした際に、ポート名が入力きるようになるが、デフォルトでよい。

JTAGの割り込みを接続する

上の図で、黄色丸のついているところをクリックし、JTAGの割り込みをNios IIに接続する。
これをするとWarningが消えるが、実用上はWarningがあっても今のところは問題がないようだ。

Reset VectorとException Vectorを指定する

Nios IIのIPをダブルクリックして設定を開く。
下図のように、Reset VectorとException Vectorvector memoryを"(上記のメモリーモジュール名).s1"に指定する。
これはプルダウンメニューから選ぶだけでよい

各IPのアドレスマップを変更する

Address Mapタブを選択し、各IPのアドレスマップを下図の通りに変更する。

この段階で、"Message"タブに現れていたエラーの全てが消えるはずだ。

"Generate" -> "Generate"でモジュールを生成する

これでQuartus IIから組み込み可能なモジュールのqsysファイルと、モジュールの宣言をしたVerilogが生成される。

Quartus IIでQsysで作成したモジュールを組み込む

再びこちら。

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

本書では、SOPC Builderで各種IPを組み込んだモジュールを作成したあと、それを含んだトップモジュールは回路図エディタで作成している。
Verilogを勉強しているところなので、このトップモジュールもVerilogで書いてみることにした。

トップモジュールを作成する

プロジェクトで新しいVerilogファイルを作成する、名前は"nios2pio.v"。

module nios2pio(
	input wire in_clk, 
	input wire [9:0] in_switch, 
	input wire [2:0] in_button, 
	output wire [9:0] out_led, 
	output wire [7:0] seven_segment_0, 
	output wire [7:0] seven_segment_1, 
	output wire [7:0] seven_segment_2, 
	output wire [7:0] seven_segment_3);
endmodule

上記で使用しているポートは、筆者がひな形にしていて、ピンアサインメントを事前に作成してあるものだ。
ピンアサインメントの作成方法と、インポートの方法はこちら

Qsysで作成したqsysファイルとverilogファイルをプロジェクトに追加する

"Project" -> "Add/Remove Files in Project..."を選択すると、下記のダイアログが開く。

"File name:"横の"..."ボタンを押してファイルを指定し、"Add"ボタンで追加する。
qsysファイルはプロジェクトのルートに、verilogファイルは(qsysのファイル名/synthesis)の下にあるはずだ。
追加が終わったら、OKでダイアログを抜ける。

Qsysで作成したモジュールをトップレベルのモジュールに追加する

"nios2pio.v"を以下のように修正する。

module nios2pio(
	input wire in_clk, 
	input wire [9:0] in_switch, 
	input wire [2:0] in_button, 
	output wire [9:0] out_led, 
	output wire [7:0] seven_segment_0, 
	output wire [7:0] seven_segment_1, 
	output wire [7:0] seven_segment_2, 
	output wire [7:0] seven_segment_3);
	// modules
	nios2pio_qsys nios2pio_qsys(
		.clk_clk(in_clk),
		.reset_reset_n(in_button[0]),
		.pio_0_external_connection_export(seven_segment_0),
		.pio_1_external_connection_export(in_switch[3:0])
	);
	//
	assign seven_segment_1 = 8'b1111_1111;
	assign seven_segment_2 = 8'b1111_1111;
	assign seven_segment_3 = 8'b1111_1111;
	assign out_led = 9'b0_0000_0000;
endmodule

ここで出てくる"nios2pio_qsys"がQsysで作成したモジュールになる。
設定により名前は異なる可能性があるので、上記でプロジェクトに追加したverilogファイルを開き、モジュールの宣言を確認する。
ちなみに筆者の環境ではそのVerilog("nios2pio_qsys.v")は以下のようになっている。

module nios2pio_qsys (
		input  wire       clk_clk,                          //                       clk.clk
		input  wire       reset_reset_n,                    //                     reset.reset_n
		output wire [7:0] pio_0_external_connection_export, // pio_0_external_connection.export
		input  wire [3:0] pio_1_external_connection_export  // pio_1_external_connection.export
	);


以上で終了だ。
あとは通常通りコンパイルすれば、Cyclone IIIに焼くことができるsofファイルが作成される。