はじめに
初めまして、nefrockのFPGAコースでインターンシップに参加した東京工業大学の池守和槻です. 大学ではプログラミング言語の研究をしており、特に型システムと型推論の研究をしています.
今回のインターンシップでは、ハードウェア記述言語を用いたFPGA開発とLattice Semiconductor社のFPGA (iCEstick iCE40HX1K) の実機調査というテーマで開発と調査を行いました.
インターンのテーマ内容について
今回のインターンで開発・調査したFPGAボードはLattice Semiconductor社から販売されているiCEstick (iCE40 HX1K)です.サイズとしてはUSBより一回り大きいぐらいのとてもコンパクトなFPGAボードです.
Lattice Semicondutor社はアメリカに本社を置くFPGAボードの開発を行う半導体会社で、販売されているFPGAボードは小型で低消費電力が特徴です.
iCEstick (iCE40 HX1K) の実機調査はメンターのごとぅーさんが作った音源ICの RTL (以下、音源IC) とPCのやり取りを行う部分を開発し、その都度開発ツールや注意点などのノウハウをまとめていく方針で進めました. インターンでの開発・調査の流れは大まかに以下のように進めました.
- iCEstickでLチカプログラムを動作させ、開発の一連の流れとLatticeのソフトウェアの使用方法を確認
- 音源ICの仕様を理解し、FPGA側のデータの受信部分を作成
- PC側のデータの送信アプリを作成
- iCEstickの音源ICと通信部分の動作確認
実装物の概要
インターンでは画像の点線の部分のモジュールをVerilogで実装しました.
それぞれのモジュールについて簡単に説明します.
- uart_rx.v: PCからUARTで送られた8bitのデータを受信し、8bitのバスにして出力するモジュール
- decoder.v: 受信したデータがどのコマンドかをデコードするモジュール
- addr_counter.v: メモリアドレスをインクリメントするモジュール
- reg_ram.v: 8bit * 16本のレジスタアレイ(RAMの代替として使用、理由は後述)
コマンド送信アプリの概要
さらに、今回のインターンではPCからiCEstick HX1Kへ設定データを送るためのコマンドの仕様と、コマンドを送信するための簡単なGUIアプリも作成しました.
コマンドの仕様
音源ICから音を発生させるためのコマンドとして、以下の5種類を定義しました.
- start : コマンド送信の開始を知らせる
- end : コマンド送信の終了を知らせる
- set_ch : 各チャンネルの周波数と音量、エンベロープの有無を設定する
- set_no : ノイズの周波数を設定する
- set_env : エンベロープの周波数と形を設定する
- wait : 指定された時間だけコマンドの送信を停止する
例えば、1KHzの音で音量が100の音を出力させたい場合は以下のように記述します.
start set_ch a, 1000, 100, 0 set_mix 01, 00, 00 end
GUIアプリの概観
GUIアプリでは、二種類の方法でコマンドをiCEstick (iCE40 HX1K)に送信することができます.
まず一つ目が、GUI上で周波数などの各種の設定をして、一つの音の設定をコマンド列として送信する方法です.
二つ目に、あらかじめコマンドが記述されたテキストファイルを読み込んで、複数の音のコマンド列を送信する方法です.
二つ目の方法は、曲を演奏させたい場合を考慮して実装しました.
例えば、ゼルダのハイラル平原のテーマ曲を音源ICに演奏させたい場合、waitコマンド や set_chコマンド などを組み合わせたコマンド列が記述されたファイルを読み込むことで演奏させることが可能です.
BRAMの不安定な挙動
実装したVerilogコードを内蔵のBRAMを用いてiCEstick (iCE40 HX1K)にプログラムを書き込むとBRAMが不安定な挙動を示しました.
iCEstick (iCE40 HX1K)のメモリの仕様書によると読み出しはアドレスがセットされてから、1clock遅れてデータが出力されます.
つまり、以下のようなタイミングチャートが期待される挙動です.
しかし、ロジックアナライザで計測された波形ではアドレスセットと同時にメモリからデータが読み出されていました.
つまり、以下のようなタイミングチャートになります.
さらに、これを踏まえてコードを変更すると仕様書の通りにメモリから1clock遅れてデータが出てくるという堂々巡りの状態に陥りました.
したがって、内蔵のBRAMの使用は避けて8bit*16本のレジスタアレイをBRAMの代替として使用することにしました.
ピンアサインの変更による振る舞いの変化
メモリ以外にも出力のピンアサインを変更すると出力の挙動が変化するという問題にも直面しました.
1KHzの音が正しく出力されていて、内部配線の出力を見るためにピンアサインを変更すると1KHzの音が出力されなくなるというケースがありました. 最低限、音を正しく出力させるためにピンアサインを変更して正しく出力される組み合わせを探しましたが、どのピンアサインでも何かしらのコマンドが正しく動作しませんでした. (エンベロープは動作するけど、ノイズが動作しない..., etc..)
原因としては、論理合成時の最適化によって内部配線が消失しているのではと考えました. メモリの不安定な挙動に対処するためにレジスタアレイを使用したので、ロジックセルの使用率が(957/1280)と高くなっていました. ロジックセルの使用率が高いので、論理合成ツールが不要と判断した内部配線を積極的に削除しているとようです.
そこで、レジスタアレイの本数を16本から8本に減らし、論理合成ツールの設定を変更することで解決しました.
また、論理合成ツールはデフォルトのSymplify ProからLattice Synthesis Engine(LSE)に変更し、Resource SharingとRemove Duplicate Registerというオプションを無効化しました.
そうすると、音源モジュールが正しく動作するようになりました.
まとめ
今回のインターンでは、Lattice Semicondutor社のFPGAボード iCEstick (iCE40 HX1K)にPCとの通信モジュールを開発し、PCからやり取りできる音源ICモジュールを実装しました.
また、実装の際に得られたソフトウェアの使い方や注意点を資料にまとめました.
作成した音源モジュールはインターンの終了日前日の夜に正しく動作するようになりました.
(本当によかった...)
インターンを振り返ってみて
僕はFPGAに興味はあるけど実際にはやったことはない状態で今回のインターンに申し込みました. 申し込みをした理由はいくつかありますが、最も大きな理由の一つは何か物理的にものを作り動かすのは面白そうだと思ったからです.
僕は普段ソフトウェアの開発をしているときに自分の作ったものが動くのを物理的にみたいと思うことがたびたびありました.
じゃあ、ラズパイでもやればいいじゃないかと思われる人がいるかもしれません.
しかし、ラズパイはすでにCPUが搭載されOSが動作します.
また、ラズパイを用いたデバイスの実装はソフトウェア開発の域を完全には脱しきれていないようにも思っていました.
Pythonで色々できてしまう.
そこでVerilogなどのハードウェア記述言語を用いて、回路を自由にプログラムできるFPGAに興味を持ちました.
インターン中のFPGA開発は慣れていない部分が多くごとぅーさんに助けてもらいながらでしたが、とても楽しかったです.特に音源モジュールがインターンの終了日の前日に動作したときは嬉しかったです.
音源モジュールはインターン終了日の前日の夜に正しく動作するようになったので、 この原稿も当初は「動きませんでした.残念です...」と書いていました.
今回のインターンを経て、FPGAボードを購入して自作CPUを動作させたいなと考えています.
個人的な感想ですが、普段はソフトウェアをやっているけれども自分のプログラムを物理的に動作させてみたいと思っている人にはぜひ参加して欲しいインターンだと思います.
謝辞
まず、今回のインターンでメンターをして頂いたごとぅーさんに心から感謝します.
ハードウェアの素人がいきなりインターンに来たにもかかわらず、大変丁寧に教えていただきました.
また、インターンの参加に対して温かく受け入れてくださった株式会社ネフロックの社員の皆様に心から感謝します.
最後に、楽しい催しを開いてくださったNefrockビルの皆様にも心から感謝します.