DE0-Nano-SoC (Atlas-SoC)でNios iiを動かす


## 概要
terasicのFPGAボードDE0-Nano-SoCで、AlteraのソフトコアであるNios iiを動かす手順です。
Nios iiでスイッチに接続したParallel IOのInputを監視して、内容によってLEDに接続したOutputの1/0を切り替えて点灯させるプログラムを動かします。

Atlas-SoCについては[Atlas-SoC素晴らしいんじゃないの](http://qiita.com/yukitaketake/items/96f9fd8607cc1f3c8e7c)を参照。
Atlas-SoCについて大雑把に説明するとARMのCPU(Cortex-A9)とFPGA(Cyclone V)が乗ったSoCと、ひととおりのペリフェラルが載ったボードです。$99とXlinksのZynqよりもお手頃。
terasicの購入ページではAtlas-SoCとDE0-Nano-SoCがありますが、ハードは同様でSDカードの中身が異なるだけなのでどちらを買っても良いです。私はAtlas-SoCがOut of StockだったためDE0-Nano-SoCの方を注文しました。

## プロジェクトの準備
Quartus Prime 15.1 Lite Edition, SoC EDS 15.1をインストールしておきます

SDカードにはAtlas-SoCを焼いておきます
http://rocketboards.org/foswiki/view/Documentation/AtlasSoCSdCardImage

DE0-Nano-SoC CD-ROMをダウンロード
http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&No=941&PartNo=4

DE0-Nano-SoC CD-ROMを解凍した中にあるTools/SystemBuilder/DE0_Nano_SoC_SystemBuilder.exeを起動します。
![2016-02-06.png](https://qiita-image-store.s3.amazonaws.com/0/34215/fff07830-7586-bbf2-0d3d-9c846c859cc0.png)
CLOCK, LED, Button, Switch, Arduino Headerにチェックを入れ、こんな感じでGenerateします。

GenerateするとDE0_NANO_SoC_NIOS2.qpfができるので、開くとQuartus Primeが立ち上がります。

## Qsys
Quartus PrimeのメニューからTools→QsysでQsysを開きます。

### IPの追加
まず、Nios IIを追加します。左側に表示されているIP Catalogから、Nios II Processorをダブルクリック。
Nios II ProcessorはLibrary -> Processors and Peripherals -> Embedded Processorsの中にあります。
タブのMainでNios II/eを選択し、右下のFinishを押す。

次にメモリを追加します。メモリはOn-Chip Memory (RAM or ROM)という名前です。
IP Catalogの中のLibrary -> Basic Function -> On Chip Memory の中にあります。
Sizeを16384 bytesに設定し、右下のFinishを押す。

次に、Parallel IOを追加します。Parallel IOはPIO(Parallel I/O)という名前です。
IP Catalogの中のLibrary -> Processors and Peripherals -> Peripheralsの中にあります。
InputとOutputが必要なので、合計2つ必要となります。
まずOutputから追加します。
Basic Settingsの中のWidthを1にし、DirectionをOutputにします。その後右下のFinishを押す。
次にInputを追加します。
こちらも同様にBasic Settingsの中のWidthを1にし、Directionを**Input**にします。その後右下のFinishを押す。

最後に、JTAG UARTを追加します。
IP Catalogの中のLibrary -> Interface Protocols -> Serial -> JTAG UARTにあります。
なにも設定を変えず、そのままFinishを押します。

### 接続
![2016-02-06 (1).png](https://qiita-image-store.s3.amazonaws.com/0/34215/6939114b-2f47-3af7-8026-dfe3f525b7c3.png)
こんな感じになるように、白丸をポチッとクリックすると黒丸になって接続されます。

次にIOの接続をします。
pio_0, pio_1のexternal_connectionのExportの欄に、それぞれ`out_port_from_pio_0`,`in_port_to_pio_1`といれます。

### アドレスの設定
メニューのSystem->Assign Base Addressを選択すると、良い感じにBase Addressが設定されます。
その後、nios2_gen_2_0をダブルクリックし、タブのVectorsでReset Vector memoryをonchip_memory2_0.s 1に、Exception vector memoryもonchip_memory_2_0.s 1に変更。

### HDLの生成
メニューのGererate->Generate HDL...を選択し、Generateをクリック。
VerilogかVHDLかはおこのみで。私はVerilogを選択しました。

Generateが終わったら、メニューのGenerate->Show Instantiation Templateを選択し、表示されているExample HDLをメモしておきます。
ここまでできたらQsysを保存しQuartus Primeに戻ります。

## 合成
Quartus Primeに戻り、左に表示されているProject Navigatorの表示をHierarchyからFilesに変更する。
Filesを右クリックし、Add/Remove Files in Projectを選択。出てきたウィンドウでAdd Allをクリック。
![image](https://qiita-image-store.s3.amazonaws.com/0/34215/fd77089b-e749-690f-4d53-6f97d00510cb.png)
こんな感じにファイルが追加されていれば問題無いです。

次に、DE0_NANO_SOC_NIOS.vを編集します。
` REG/WIRE declarations`の下に、以下のコードを追加します。

```verilog
wire RSTN = KEY[0];
```

`Structural coding`の下に、先ほどメモしたExample HDLをコピーします。

```verilog
    nios2 u0 (
        .clk_clk                    (<connected-to-clk_clk>),                    //                 clk.clk
        .in_port_to_pio_1_export    (<connected-to-in_port_to_pio_1_export>),    //    in_port_to_pio_1.export
        .out_port_from_pio_0_export (<connected-to-out_port_from_pio_0_export>), // out_port_from_pio_0.export
        .reset_reset_n              (<connected-to-reset_reset_n>)               //               reset.reset_n
    );
```
（）の中を、適切なピンに変更します。
変更後は以下のようになるはずです。

```verilog
    nios2 u0 (
        .clk_clk                    (FPGA_CLK1_50),                    //                 clk.clk
        .in_port_to_pio_1_export    (SW[0]),    //    in_port_to_pio_1.export
        .out_port_from_pio_0_export (LED[0]), // out_port_from_pio_0.export
        .reset_reset_n              (RSTN)               //               reset.reset_n
    );
```
メニューから、Processing->Start Compilationを選択します。
私の環境（Intel Xeon E3-1220v3)では約3分くらいで終了しました。

最後に、FPGAに回路を書き込みます。
メニューから、Tools->Programmerを選択します。
![image](https://qiita-image-store.s3.amazonaws.com/0/34215/bd3b5190-07ce-d254-9378-bd6a55b57790.png)
こんな感じになっていればOKです。DE-SoC [USB-1]となっていないときはUSB BlasterのUSBポートが接続されているか確認してください。
左のStartを押すと、回路が書き込まれます。

次はNios II上で動くプログラムを書くために、Nios II Software Building Tools for Eclipseを使います。
メニューから、Tools->Nios II Software Building Tools for Eclipseを起動します。

## Nios II プログラムの作成・実行
メニューから、File->New...を選択します。
Target hardware informationのSOPC Information  File nameに、Qsysで作成された.sopcinfoファイルを選択します。
Project TemplateはHello Worldを選択します。
![image](https://qiita-image-store.s3.amazonaws.com/0/34215/c9feb0e3-6045-5ddb-5e40-7f39279c1ec3.png)
こんな感じになります。Finishを押しましょう。

プロジェクトhelloの中の、hello_world_small.cを編集します。

```c
#include "sys/alt_stdio.h"
#include "system.h"

int main()
{ 
  while (1) {
	  int reg = *(volatile unsigned long *)PIO_1_BASE;
	  *(volatile unsigned long *)PIO_0_BASE = reg;
  }

  return 0;
}
```
ひたすら入力(PIO_1_BASE)の値を出力(PIO_0_BASE)に反映し続けるというプログラムになっています。

いよいよプログラムを実行します。
プロジェクトhelloを右クリックし、Run As -> Nios II Hardwareを選択します。
target connectionタブで、デバイスが接続されていることを確認してください。
![image](https://qiita-image-store.s3.amazonaws.com/0/34215/02250ce2-0d3b-5283-1c59-e050113cbfaf.png)
右下のRunボタンを押すと、FPGAへのプログラムのダウンロードと実行が開始します。
LED0の点灯状態ががSW0の操作によって切り替われば成功です。うまくいかない場合はKEY0を押してNios IIをリセットしてみましょう。

お疲れ様でした。

## 参考
[DE1-SoCでNios IIプロセッサからLEDを制御する](http://c0lvlput3r.blogspot.jp/2014/10/controlling-led-from-nios2-processor-on-de1soc.html)
DE1-SoCはDE0-nano-SoCの上位版のようなボードで、大いに参考にさせていただきました。