Chisel入門書「Digital Design with Chisel」1章の勉強記録

#　記事の概要
Chiselの入門書「Digital Design with Chisel」の1章の勉強記録です。
本文の概要を備忘録として整理し、また実際に行った演習を紹介します。

本のpdfデータとプログラム一式は無料で以下から入手できます。
https://raw.githubusercontent.com/wiki/schoeberl/chisel-book/chisel-book.pdf
https://github.com/schoeberl/chisel-book

## 1.1 Installing Chisel and FPGA Tools
ChiselはScalaライブラリです。
ChiselとScalaのインストール方法は、以前に私が作成した以下などをご参照ください。

[Ubuntu上でのRISC-Vの環境構築](https://qiita.com/Kosuke_Matsui/items/14aadce506fe3df79600)

## 1.2 Hello World

```Scala
object HelloScala extends App{ 
    println("Hello Chisel World!") 
}
```
このプログラムをsbtでコンパイルして実行します。

```
sbt "runMain HelloScala"
```

Hello Worldプログラムは以下を出力します。

```
[info] Running HelloScala 
Hello Chisel World!
```

このプログラムはいかなるハードウェアも生成しません。
次に具体的なハードウェアとしてLEDを点滅させる回路を作成します

## 1.3 Chisel Hello World

LEDを点滅させる回路を作成するプログラムです。

```Scala
class Hello extends Module { 
  val io = IO(new Bundle { 
    val led = Output(UInt(1.W)) 
  }) 
  val CNT_MAX = (50000000 / 2 - 1).U;
  
  val cntReg = RegInit(0.U(32.W)) 
  val blkReg = RegInit(0.U(1.W))
  
  cntReg := cntReg + 1.U 
  when(cntReg === CNT_MAX) { 
    cntReg := 0.U 
    blkReg := ˜blkReg 
  }
  io.led := blkReg
}
```
## 1.4 An IDE for Chisel
プロジェクトの作成方法として、Githubから既存のソースをコピーして新しいプロジェクトを作成し、build.sbtのプロジェクト名を修正する方法を紹介しています。

## 1.5 Source Access and eBook Features
この本についての話をしています

## 1.6 Further Reading
参考資料を紹介しています

## 1.7 Exercise
### FPGA上で動作させる
以下のコマンドにより、1.3で紹介したサンプルプログラムをverilogに変換できます

```
git clone https://github.com/schoeberl/chisel-examples.git 
cd chisel-examples/hello-world/ 
make
```

変換したverilogをFPGA上で動作させてみます。
以下に実際にvivadoで実行した手順を紹介します。

#### FPGAボード
FPGAボードにはXillinks社の評価ボードArty S7を使用しました。
秋月電子などで購入できます。

[ＡＲＴＹ　Ｓ７　ＦＰＧＡ評価ボード
](http://akizukidenshi.com/catalog/g/gM-12558/)

#### vivadoの使用方法
vivadoを起動後、File→Project→Newを選択します。
<img width="70%" alt="FPGA_step1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/573de165-1e76-7082-e286-4174f97a2791.png">

Nextを選択します。
<img width="70%" alt="FPGA_step2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/486b0647-934a-6175-fc3d-34c2e240fa4b.png">

Project nameを入力し、Nextを選択します。
Creat project subdirectoryはチェックを外しても問題ありません。
<img width="70%" alt="FPGA_step3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/fe196aa8-22c5-b5d9-8d60-41f12070ae1f.png">

RTL Projectを選択します。Do not specify sources at this timeにチェックを入れて、Nextを選択します。
<img width="70%" alt="FPGA_step4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/ad6259e0-0064-6cc5-00c8-d4e7020bf8d8.png">

FPGAボードの型番xc7s50csga324-2を選択して、Nextを選択します。
<img width="50%" alt="FPGA_step5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/e005ae20-d918-cd32-2110-aee345bb8444.png">

Finishを選択します。
<img width="70%" alt="FPGA_step6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/53b154d4-9b6e-8c33-5174-b3a44a4f6f09.png">

プロジェクト起動後、まずはプロジェクトに先ほど生成したverilogファイルHello.vを追加します。
SourcesウィンドウのDesign Sourcesから右クリックでAdd Sourcesを選択してください。
<img width="50%" alt="FPGA_step6b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/d6e81d91-d055-46cb-ff12-e95bb2ef2f4a.png">

Add or create design siurcesをチェックして、Nextを選択します。
<img width="70%" alt="FPGA_step6c.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/74d20c73-6da5-7fab-514e-03b6a43a45ee.png">

先ほど生成したverilogファイルHello.vを選択して、Finishを選択します。
<img width="70%" alt="FPGA_step6d.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/feb7069a-66e5-a1d7-b3d4-2c231ee4478d.png">

次に以下の制約ファイル"hello_test.xdc"を作成します。制約ファイルは、作成した信号と実際のFPGAの端子を関連付けるための設定ファイルです。

```
## This file is a general .xdc for the Arty S7-25 Rev. E
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project

## Clock Signals
set_property -dict { PACKAGE_PIN F14   IOSTANDARD LVCMOS33 } [get_ports { clock }]; #IO_L13P_T2_MRCC_15 Sch=uclk
create_clock -add -name sys_clk_pin -period 83.333 -waveform {0 41.667} [get_ports { clock }];

## LEDs
set_property -dict { PACKAGE_PIN E18   IOSTANDARD LVCMOS33 } [get_ports { io_led }]; #IO_L16N_T2_A27_15 Sch=led[2]

## Buttons
set_property -dict { PACKAGE_PIN G15   IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L18N_T2_A23_15 Sch=btn[0]

## Configuration options, can be used for all designs
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]

## SW3 is assigned to a pin M5 in the 1.35v bank. This pin can also be used as
## the VREF for BANK 34. To ensure that SW3 does not define the reference voltage
## and to be able to use this pin as an ordinary I/O the following property must
## be set to enable an internal VREF for BANK 34. Since a 1.35v supply is being
## used the internal reference is set to half that value (i.e. 0.675v). Note that
## this property must be set even if SW3 is not used in the design.
set_property INTERNAL_VREF 0.675 [get_iobanks 34]
```
hello_test.xdcをプロジェクトに追加します。SourcesウィンドウのConstraintsから右クリックでAdd Sourcesを選択してください。
<img width="70%" alt="FPGA_step7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/91396d84-a144-91a8-eb4e-da87f7176bbd.png">

Add or create constraintsをチェックして、Nextを選択します。
<img width="70%" alt="FPGA_step8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/bf24e4b2-58a2-0602-0385-b263c3d44c83.png">

先ほど作成した制約ファイルhello_test.xdcを選択して、Finishを選択します。
<img width="70%" alt="FPGA_step9.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/65355161-2135-2721-094c-de79a63af0f9.png">

次に論理合成とネットリストの作成を行います。Generate Bitstreamをクリックしてください。
<img width="50%" alt="FPGA_step10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/950df7df-afb4-fbac-732d-4566157aa629.png">

Yesを選択します。
<img width="70%" alt="FPGA_step11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/0c018e47-a5e9-a94d-8ae5-4b9bbb915107.png">

OKを選択します。
<img width="70%" alt="FPGA_step11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/2dda3a92-ef8c-6775-8619-a7eea2fc29b5.png">

論理合成の進行具合はDesign Runsで確認できます。
<img width="70%" alt="FPGA_step13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/4902a52f-08d0-732c-ae33-dbecde1d62a3.png">

ネットリスト作成が成功すると以下の画面が表示されます。ここでは何もしないのでCancelを選択します。
<img width="50%" alt="FPGA_step14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/92485519-a572-fb9f-4f19-cdeffcc78a98.png">

次にネットリストをFPGAボードに書き込みます。
FPGAボードをパソコンに接続し、Open Hardware Manager→Open Target→Auto Connectを選択します。
<img width="50%" alt="FPGA_step15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/e83f83c6-abee-f984-e378-7f740ab4280a.png">

Open Hardware Manager→Program Device→xc7s50_0を選択します。
<img width="50%" alt="FPGA_step16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/df0f9623-79e8-5f77-50a9-fa71577b1f36.png">

生成したネットリストを選択して、Programを選択します。
<img width="70%" alt="FPGA_step17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/516e2a34-bcfa-ac71-0b0f-8c9670f1ef63.png">

正常に書き込みが完了すると、LEDが点滅します。
終了する時は、下図の個所から右クリックでClose Targetを選択します。
<img width="70%" alt="FPGA_step18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/5e72ff48-8781-173a-6bd1-90b19c4cf5d9.png">

### LEDを毎秒200ミリ秒間点灯させる
プログラムを修正し、毎秒200ミリ秒だけ点灯させるようにします。
FPGAボードのメインクロックは12MHzなので、$12*10^6$をカウントすると1秒になります。

```Scala
/*
 * This code is a minimal hardware described in Chisel.
 * 
 * Copyright: 2013, Technical University of Denmark, DTU Compute
 * Author: Martin Schoeberl (martin@jopdesign.com)
 * License: Simplified BSD License
 * 
 * Blinking LED: the FPGA version of Hello World
 */

import chisel3._
import chisel3.Driver

/**
 * The blinking LED component.
 */

class Hello extends Module {
  val io = IO(new Bundle {
    val led = Output(UInt(1.W))
  })
  val CNT_ON = (2400000 - 1).U;
  val CNT_MAX = (12000000 - 1).U;

  val cntReg = RegInit(0.U(32.W))
  val blkReg = RegInit(0.U(1.W))

  cntReg := cntReg + 1.U
  when(cntReg === CNT_ON) {
    blkReg := 0.U
  }
  when(cntReg === CNT_MAX) {
    cntReg := 0.U
    blkReg := 1.U
  }
  io.led := blkReg
}

/**
 * An object extending App to generate the Verilog code.
 */
object Hello extends App {
  chisel3.Driver.execute(Array[String](), () => new Hello())
}
```

これを先ほどと同様にしてFPGAに書き込むと、期待の動作が得られます。


## 関連記事

[Chisel入門書「Digital Design with Chisel」2章の勉強記録](https://qiita.com/Kosuke_Matsui/items/be68930d121b13402e2a)
[Chisel入門書「Digital Design with Chisel」3章の勉強記録](https://qiita.com/Kosuke_Matsui/items/b82edca18089084350c0)
[Chisel入門書「Digital Design with Chisel」4章の勉強記録](https://qiita.com/Kosuke_Matsui/items/23800cf34fb435225ec9)
[Chisel入門書「Digital Design with Chisel」5章の勉強記録](https://qiita.com/Kosuke_Matsui/items/847665e371185f14e735)
[Chisel入門書「Digital Design with Chisel」6章の勉強記録](https://qiita.com/Kosuke_Matsui/items/dd526ae4d59f30d1f586)
[Chisel入門書「Digital Design with Chisel」7章の勉強記録](https://qiita.com/Kosuke_Matsui/items/53a9e61facbc1cc79025)
[Chisel入門書「Digital Design with Chisel」8章の勉強記録](https://qiita.com/Kosuke_Matsui/items/3ab4be6bdba6d94be10b)
[Chisel入門書「Digital Design with Chisel」9章の勉強記録](https://qiita.com/Kosuke_Matsui/items/4c11d32c799800680f5c)