MiniZedでLチカ(3) Vitis
Avent社のFPGAボード MiniZedでLチカする手順です。前の記事でBitstreamを出力するところまで済ませました。この記事ではLチカまでを書きます。
開発環境
Vitisの起動
Tools -> Laungh Vitis IDE をクリック
プロジェクトルートを指定してLaunghをクリック
Platform Projectの作成
Create Platform Projectをクリック
Platform project nameを入力してNextをクリック
プロジェクトルートにVivadoから出力したxsaファイルがあるのでこれを指定してFinishをクリック
Application Projectの作成
File -> New -> Application Project をクリック
Nextをクリック
Nextをクリック
Application project name入力してNextをクリック
Nextをクリック
Finishをクリック
プログラム記述
helloworld.c内にLチカするプログラムを追加します。 Hardware User GuideのTable 13 – Allocation of MIO pinsを見ると、LEDは52番ピンと53番ピンにつながっていることが分かります。
#include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "sleep.h" // sleep()に必要 #include "xgpiops.h" // gpio操作に必要 int main() { XGpioPs_Config *cfg; XGpioPs ins; init_platform(); cfg = XGpioPs_LookupConfig(XPAR_XGPIOPS_0_DEVICE_ID); XGpioPs_CfgInitialize(&ins, cfg, cfg->BaseAddr); // gpioのconfigを初期化 // ピンの入出力を指定 第3引数が0で入力, 1で出力 XGpioPs_SetDirectionPin(&ins, 52, 1); XGpioPs_SetDirectionPin(&ins, 53, 1); // ピンの出力を有効化 XGpioPs_SetOutputEnablePin(&ins, 52, 1); XGpioPs_SetOutputEnablePin(&ins, 53, 1); print("Hello World\n\r"); print("Successfully ran Hello World application"); while(1) { XGpioPs_WritePin(&ins, 53, 0); sleep(1); XGpioPs_WritePin(&ins, 52, 1); sleep(1); XGpioPs_WritePin(&ins, 53, 1); sleep(1); XGpioPs_WritePin(&ins, 52, 0); sleep(1); } cleanup_platform(); return 0; }
プログラムの書き込み
まず、ボードのディップスイッチを書き込みモードになっていることを確認します。 HW Users Guideの5章 Boot Modes をみると、JTAG Boot Modeを選択するにはMIO[5], MIO[4], MIO[3]をすべて0にすれば良いことが分かります。さらに、Table 15 – Boot Mode Switch Selectionsを見るとBoot Mode SwitchをJにすれば良いことが分かります。
続いて、USB JTAG UART のMicro USBポートとPCを接続して、プログラムをZynqに書き込みます。
Xilinx -> Program Device をクリック
Program をクリック ボードのDONE LED(青色)が点灯すれば完了です。
プログラムのビルド
LedBlink_system[System]を右クリック -> Buildをクリック
Console にエラーがなくビルドが終了していれば成功です。
プログラムの実行
Debugを右クリック -> Run -> Debugger_LedBlink-Default (Single Application Debug) をクリック
PS LEDが赤 -> 黄 -> 緑 -> 滅 と点滅します。
参考にさせていただいたサイト
MiniZedでLチカ(2) Vivado
Avent社のFPGAボード MiniZedでLチカする手順です。前の記事で環境構築を済ませました。この記事ではVivadoでプロジェクトを作成してBitstreamを出力するところまでを書きます。
開発環境
Vivadoプロジェクトの作成
Create projectをクリック
Next
プロジェクト名(今回はMiniZedLedBlinkにしました)とパスを入力してNextをクリック
Do not specify sources at this timeにチェックを付けてNextをクリック
BoardタブでMiniZedを選びNextをクリック
Finish
回路記述
記述と言ってもほとんどGUIでできてしまいます。すごい。
Create Block Designをクリック
OKをクリック
プラスボタンをクリック
ZYNQを検索して選択
Run Block Automationをクリック
OKをクリック
Source -> Design Sources -> Create HDL Wrapper OKをクリック
ビットストリームの生成
Generate Bitstreamをクリック
Yesをクリック
OKをクリック
Cancelをクリック
ビットストリームの出力
File->Export Hardware
Nextをクリック
Include bitstreamを選択してNextをクリック
Nextをクリック
Finishをクリック
参考にさせていただいたサイト
MiniZedでLチカ(1) 環境構築
Avent社のFPGAボード MiniZedでLチカするための環境を構築します。
開発環境
MiniZedの製品ページからマニュアルやBoard Definition Filesをダウンロードしておきます。
IDEのインストール
Next
2019.2 のリリースより、ザイリンクス SDK 開発環境は、Vitis 統合ソフトウェアプラットフォームに統合されました。ここでVivadoを選ぶとVitis(SDKの後継)がインストールされません。 Vitisを選びNext
ディスク使用量が多いので必要なものだけ選びNext
同意してNext
Next
Yes
Install 途中で何回かUAC等が出てくるので進めます。
OK
これでインストールは完了です。
Board Definition Filesの追加
MiniZedの製品ページからダウンロードしたBoard Definition Filesを解凍する(2つのZipが入れ子になっているので両方解凍)と、minizedフォルダがあります。これを”C:¥Xilinx¥Vivado¥2020.2¥data¥boards¥board_files”にコピーします。
Cyclone V GT FPGA Development KitでHello, world!
Cyclone V GT FPGA Development Kitにはキャラクタ液晶(LCD)が付いているので何かと便利に使えそうだ.
さぁ適当なIPをインポートしてサクッとHello, world!と思ったら,そのような便利なIPは(少なくとも無償では)無いらしい.えーI2C通信自分で書くの・・・.今までマイコン等でI2Cの何かを使うときはライブラリの上から適当に使ってきたので,信号の細かな動きは全く知らない.仕方ないので調べながら書いた.この界隈そんなに人少ないのか・・・.
資料
公式のユーザーガイドとリファレンスマニュアル.
LCDのデータシート
http://www.newhavendisplay.com/specs/NHD-0216K3Z-NSW-BBW-V3.pdf
環境
プロジェクトファイル一式:https://github.com/SenriYoshikawa/CycloneVGTFPGADevelopmentKit/tree/master/LCD
仕様
実装
コードすべての説明を書くとかなりの量になりそうなので,特に詰まったところだけメモがてら書き残す.
inoutピン
SCLとSDAは場合により入力にも出力にもなり得る.そんなものどうやってVerilogで書くのだと思い調べたところ,inout宣言した入出力ポート(wire)に対して,条件によりregか'z'(ハイインピーダンス)をassignすればよいらしい.
こんな感じ.
assign i2c_sda = sda_valid ? sda_reg : 1'bz;
自分(FPGA)はマスターなので,出力したいときはsda_validをHighにしてsda_regに書き込み,スレーブの応答を見たいときはsda_validをLowにしてi2c_sdaを読めば良い.
SCLのためのクロック生成
I2Cの詳細については丁寧に解説しているサイトがたくさんあるのでそちらに譲る.FPGAで実装しようとしてまず困ったのは,I2Cのクロック信号(SCL)がせいぜい数百kHzまでしか対応しないらしく,PLLではそこまで遅いクロックを作ることができないことだ.
仕方がないので以下のような何とも言えないモジュールを書いた.50MHzクロックでカウンタを動かし,50KHzのクロックを生成している.一応動いているので良しとしているが,より良い方法ご存じの方教えてください・・・.
ちなみに,なぜリセットのエッヂ検出をしているかというと,リセット中にカウントが止まるとクロックも止まり,50Kで同期しているレジスタをリセットできないからだ.ここも少し嵌った.
module Clk50K( input clk_50M, input rstn, output reg clk_50K ); reg [1:0] rstn_buf; reg [9:0] count_50K; // rstn_buf always @(posedge clk_50M) begin rstn_buf <= {rstn_buf[0], rstn}; end // count_50K always @(posedge clk_50M) begin if(rstn_buf == 2'b10) begin count_50K <= 0; end else if(count_50K >= 499) begin count_50K <= 0; end else begin count_50K <= count_50K + 10'd1; end end // clk_50K always @(posedge clk_50M) begin if(rstn_buf == 2'b10) begin clk_50K <= 1'b0; end else if(count_50K >= 499) begin clk_50K <= ~clk_50K; end else begin clk_50K <= clk_50K; end end endmodule
SCLとSDAの同期
SCLはSDAに対するクロックで,通常のデータ転送においてはSCLがLowの間にSDAを書き換える同期回路でよく見る動作なのだが,スタートシーケンスではSCLがHighの間にSDAをLowに,ストップシーケンスではSCLがHighの間にSDAをHighにしなければならない.
この動作を実現するために,2ビットのひたすらインクリメントするレジスタを設け,この上位ビットをSCLに繋いだ.
reg[1:0]scl_reg | scl |
---|---|
2'b01 | 0 |
2'b10 | 1 |
2'b11 | 1 |
2'b00 | 0 |
これによりSCLがHighとLowのそれぞれで2クロックあるので,SCLがHighの間にSDAを操作したければ,scl_regが2'b10の時に代入すればよい.通常のデータ代入はscl_regが2'b00か2'b01の時に行えばよい. しかし後で見たら自分でも首を傾げそうな実装だ.みんなどうしてるんだろう.
その他
あとは初めに思ったほどややこしいことはなく,愚直に書いたら動いた.
ピン配置
LCDのピンがどこにつながっているかはリファレンスマニュアルのP2-25に書いてある.
LEDはデバッグ用に3つ繋いでいるがなくても動く.
書き込み・動作確認
例によってデバイスチェーンに気を付けて書き込んで動作確認.
動いた.うれしい.
Cyclone V GT FPGA Development KitでLチカする
ボードを手に入れたらとりあえずLチカしたい.適当にググってその通りにすれば30分で終わるでしょ,と思っていたら全然情報がなくて普通に時間かかったのでメモ. 基本的に頼りになるのは公式のユーザーガイドとリファレンスマニュアル.
環境
- Windows 10 1903
- Quartus Prime 18.1 Standard Eiditon
プロジェクトファイル一式:https://github.com/SenriYoshikawa/CycloneVGTFPGADevelopmentKit/tree/master/PushButtonLED
Verilogを書く
PB(Push Button)1とPB2の状態をラッチするレジスタを用意し,これをLEDへの出力とする.あまり意味はないが,PB0をリセット信号として使い,レジスタを初期化するようにした.PB1を押すとLED0が,PB2を押すとLED1が点灯する.
module PushSwitchLED( input clk, input rstn, input [1:0] button, output reg [1:0] led ); // led always @(posedge clk_50M) begin if(~rstn) begin led <= 2'b11; end else begin led <= button; end end
PushSwitchLED.vとしてプロジェクトフォルダ直下に保存しておく.
プロジェクトを作る
File -> New Project Wizard
Next
プロジェクトフォルダの場所とプロジェクト名を入力してNext
Next
Add Allで先に保存したPushSwitchLED.vがリストに入る -> Next
Board -> Cyclone V GT FPGA Development Kit -> Next
Simulationは好きなのを選べばいいともう.Finish
ピンアサイン
先にAnalysis & Synthesis をしておく.
Pin Plannerを起動.
Assignment -> Pin Planner
何をどこにつなげばいいのかはリファレンスマニュアルを見ればわかる. clkは何でもよいが50MHzのPIN_V28を繋いだ.リファレンスマニュアルP2-20を参照. プッシュボタンとLEDはリファレンスマニュアルP2-23とP2-24を参照.
Pin Plannerを閉じる.
書き込み
先にStart Compilationしておく.
その間にFPGAボードにACアダプタとUSBケーブルを接続する.ディップスイッチがデフォルトになっていることを確認(詳細はユーザーズガイドを参照)し,電源を入れる.
Programmerを起動する. Tools -> Programmer
Hardware Setup
USB-BlasterIIを選択してClose.
ここで意気揚々とStartを押すと失敗する.このボードにはCyclone Vの他にMax Vが載っていて,書き込む対象がCyclone Vだけでも両方のFPGAを含むJTAGチェーンを構成しないと書き込めないらしい.そんなの言われなきゃ分からないって・・・.
Auto Detect
一番近いものを選びOK.
これが正常なフローなのか自信を無くしながらYes.
Cyclone VのFileにoutput_files/PushButtonLED.sofが入り,Program/Configureにチェックが入っていればOK.こうなっていなければ,左側のChange Fileから手動でファイルを差し替えてこの状態にする.Startで書き込みを開始する.
動作確認
Programmer右上の進捗バーが100%になれば書き込みは終わっているはず.
ボード上のプッシュボタンを押すとLEDが光る.これだけでも動くとうれしい.