MicroBlazeを用いたハードウェア構築
MicroBlazeを用いたハードウェア構築
はじめに
前回に続き、「FPGAプログラミング大全 第2版」をやる
HDL経験:Verilog入門書を一日読んだだけ 基本の文法のみ
本投稿では本書6-1~「ソフトマクロCPUシステム」を実施したメモを書きます
環境
FPGA : Xilinx Zybo Z7-20
OS : WSL2 Ubuntu20.04
開発環境 : Vivado ML edition 2022.1 Linux版
やりたいこと
- Zynqで構築したハードウェア同等の回路をソフトマクロCPU MicroBlazeを使って実装する
- UART通信はZynq PS側で埋まっているため、直接PL側と通信できない。そのためMicroBlazeのDebug Moduleを経由してUART通信を行う
Microblazeとは
- Xilinxが提供しているソフトマクロCPU
- 対応バス
- LMB :BRAM接続用
- AXI :ARM系バス
- ACE :AXI拡張
- MicroBlaze Processor Reference
実装
ハードウェア構築
Vivadoでハードウェアを構築していく
- Create project -> Create Block Design
- MicroBlaze IPを追加
- Microcontroller
- LocalMemory設定
- Debug+UART
- 割り込みコントローラは不要
- Run Connection Automation実行
ペリフェラルが生成される(local memory, clock,reset等) - MicroBlazeのInput Clockを100->125MHzに変更
- CLK端子はシングルエンドなのでDifferential -> SingleEndに変更
- Reset: Active Highで使用。Sys ResetとClock Resetを接続
- GPIO IPを追加 ALL Output[2:0] 1Ch構成で使用する
- 制約ファイルに合わせてI/Oの信号名を変更
- 最後にエラーが出るのでZynq PSを配置しておく
- Validate design -> Create HDL Wrapper -> Generate Bitstream
最終的なブロックデザイン
Bitstreamを行ったところエラー
要はI/Oが割り当てられず、それによりDRCエラーを吐いている。
-> 制約ファイルの追加を忘れていたのが原因🥺
制約ファイルを追加してGenerate Bitstream
無事に完了したのでExport Hardware
MicroBlaze アドレスマップ
GPIO/BRAM/MDMのレジスタアドレスが確認できる
VitisからMicroBlazeを制御
- Vitis起動
- Hardware構築で生成したxsaファイルを使用してPlatform projectを作成
- Applicationでhello worldを選択
- Build project
- Debug As -> Launch Hardware
実行完了
MicroBlazeはSerialportではなくUARTを使うのでConsole上で確認する
LED点灯プログラムを動かす
次にApplication Projectを再作成してMicroblazeからGPIOを制御し、LEDを点灯させる
LED_test.cをimport Source -> Build project
コードはここから参照してます
/*xparameters.h
/* Canonical definitions for peripheral AXI_GPIO_0 */
#define XPAR_GPIO_0_BASEADDR 0x40000000
#define XPAR_GPIO_0_HIGHADDR 0x4000FFFF
#define XPAR_GPIO_0_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID
#define XPAR_GPIO_0_INTERRUPT_PRESENT 0
#define XPAR_GPIO_0_IS_DUAL 0
/*led_test.c */
#include "xparameters.h"
#include "xil_printf.h"
#define LED *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x00))
#define LED_ctrl *((volatile unsigned int*) (XPAR_GPIO_0_BASEADDR + 0x04))
int main()
{
int i, j;
LED_ctrl = 0x0;
xil_printf("Hello FPGA World!\r\n");
while(1) {
for ( i=0; i<5; i++ ) {
xil_printf("i=%d\r\n", i);
switch ( i ) {
case 0: LED = 0x4; break;
case 1: LED = 0x2; break;
case 2: LED = 0x1; break;
case 3: LED = 0x7; break;
case 4: LED = 0x0; break;
default: LED = 0x0;
}
for ( j=0; j<40000000; j++);
}
}
return 0;
}
VivadoでGenerate Bitstreamを行うとxparameters.hにHardware側のGPIOレジスタが生成されるので、それを制御プログラム側でポインタとして指定している
xparameters.hを見るとXPAR_GPIO_0_BASEADDRは16bitのレジスタ空間が用意されている(0x40000000~0x4000FFFF)
動作としてはwhile文で3bitのGPIO=3つのRGB LEDライトを(100)->(010)->(001)->(111)->(000)の順でj<40000000のループ毎に実施している
今後やること
MicroBlaze + 自作IPで動作させる(そのうち本記事に追加する
感想
- AXI busめちゃ便利
- これでZynq(PS)が無くても一応制御できるようになった
おわり
Discussion