1 概述
学习 C 语言时,我们跑的第一个工程大多都是跑一个 Hello World!不同于 ZYNQ 自带了硬核,FPGA 可以嵌入软核 CPU,这个软核是由 FPGA 内部的逻辑资源实现,虽然性能上比不了 ZYNQ 的硬件,但在一些控制的领域还是能做到游刃有余。同样的,xilinx 也提供了软核的 IP,这就是 MicroBlaze。
MicroBlaze™ CPU 是嵌入式、可修改预置 32 位 RISC 微处理器配置系列。利用没有成本、基于 Eclipse 的Xilinx 软件开发套件,系统设计人员可在没有任何 FPGA 经验的情况下,使用所选的评估套件立即启动 MicroBlaze处理器的开发。MicroBlaze 处理器符合大量不同应用的需求,这些应用包括工业、医疗、汽车、消费类以及通信市场等。
本实验就将为大家介绍如何搭建一个 MicroBlaze 最小系统,并打印 Hello World。
2 系统框图
一个 MicroBlaze 最小系统主要由四个部分组成:CPU、内存(BRAM 或者 DDR 等)、FLASH 和 UART,下一个实验我们会在当前的系统加入 MIG DDR 控制器。接下来分别介绍这四个部分的搭建,最后使之成为一个完整的系统。
3 基于图形化设计 SOC 系统
3.1 创建 vivado 工程
1-1:在打开的VIVADO2021.1软件界面,单击Create Project。
1-2:单击NEXT,在弹出的窗口中输入工程名和选择保存路径,然后单击Next。
1-3:选择RTL Project,单击NEXT
1-4:在弹出的窗口中选择与板卡对应的芯片型号,这里的图片仅作参考
1-5:单击Finish完成工程的创建
3.2 CPU 配置
MicroBlaze 是基于 Xilinx 公司 FPGA 的一款 32/64 位软核嵌入式处理器,已针对 Xilinx FPGA 的实现进行了优化。
MicroBlaze 内部有 32 个 32/64 位通用寄存器和 16 个 32/64 位特殊寄存器。为了提高性能,MicroBlaze 还具有指令和数据缓存。所有的指令字长都是 32 位,有 3 个操作数和 2 种寻址模式。指令按功能划分有逻辑运算、算术运算、分支、存储器读/写和特殊指令等。指令执行的流水线是并行流水线,它分为 3 级流水:取指、译码和执行。MicroBlaze 可以响应软件和硬件中断,进行异常处理,通过外加控制逻辑,可以扩展外部中断。
下图显示了 MicroBlaze 内核的功能框图。
针对 xilinx 不同系列的芯片,下表中提供了 MicroBlaze 内核的最大频率。
MicroBlaze 官方提供了三种预设配置: Microcontroller(运行裸机应用程序的简单微控制器)、FreeRTOS(一种具有高速缓存和存储器保护单元接口的实时系统处理器、Application(运行 Linux 的内存管理单元的应用处理器)。下表显示了这三种配置在官方 XC7A200T 芯片设备上的性能和利用率。
创建一个空的 FPGA 工程,BD(block design)命名为 system
添加 IP
双击 MicroBlaze 图标,对其进行配置
预设配置:选择 current setting。
处理器配置:默认 32-bit 处理器
Select implemention to optimize(优化设置):
area(面积优先)。如果选了这个,implementation 就会优化面积,尤其是减少流水线数量,从 5 条减少到 3 条。(推荐:建议在资源比较紧张的架构,如 Artix-7,使能这个选项。然而,如果对性能有敏感的要求,就不要选这个选项,因为一些指令需要额外的时钟周期去执行。另外,对于 MMU, Branch Target Cache, Instruction Cache Streams,Instruction Cache Victims, Data Cache Victims, ACE 是不能进行面积优化的。)
Enable MicroBlaze Debug Module Interface(调试接口)
使能调试功能。用 Xilinx Microprocessor Debugger 来下载、调试程序。(推荐:除非面积资源奇缺,否则不要禁止这个功能。)
Use Instruction and Data Caches(指令和数据 cache,当使用外置 DDR 的时候使用):
当执行放在 LMB 之外的程序的时候,可以使用指令缓存来改善性能。指令缓存有如下特点:当使用外部存储时,激活这个选项可以明显地改善性能,即使这个缓存很小。
Enable Exceptions(异常处理使能)
当使用一个支持异常的操作系统时,需要激活这个选项。或者在一个单独的程序中添加异常回调函数。
Use Memory Management(内存管理)
当使用一个支持虚拟内存保护的操作系统时(如 Linux),需要激活。(当你使能面积优化或者堆栈保护功能时,内存管理单元是不可见的,自动禁止)
Enable Discrete Ports:使能软核上的独立端口。
单击 NEXT 进入下一页配置:
这一页是关于移位器、浮点单元、整形乘法器,整形除法器、模式比较器、其他机器状态寄存器指令、加载、存储和交换指令、额外的流指令、容错功能。
使能桶型移位器(Enable Barrel Shifter):使能软核中的筒形移位器硬件。激活这个参数,就可以使用如下指令
(bsrl,bsra,...)使能这个可以提高应用的性能,但是会增大软核的尺寸。如果激活,编译器会自动使用筒形移位器指令。
使能浮点单元(Enable Floating Point Unit):使能一个单精度浮点单元(FPU)。使用 FPU 可以明显地提高应用的单精度浮点性能,同时也会增大软核的尺寸。
使能整形乘法器(Enable Integer Multiplier):使能一个整形乘法器硬件。若激活,则可以在给 MUL32 赋值时,使用 mul 和 muli 指令。当给 MUL64 赋值时,使用 mulh,mulhu,mulhsu 指令。这个参数可以设置为 NONE,可以把 MUL或者 DSP48 释放,用作其他用途。这样做对软核的面积影响很小。当使用这个选项,编译器自动使用 mul 指令。
使能整形除法器(Enable Integer Divider):使能一个整形除法器硬件。若激活,可以使用 idiv,iduvu 指令。使能这个选项可以提高应用中的除法性能,但是增大了软核的尺寸。当使用这个选项,编译器自动使用 idiv 指令。
使能额外机器状态寄存器指令(Enable Additional Machine Status Register Instructions):若激活,则可以读写 MSR,使用 msrset 和 msrclr 命令。可以提高访问 MSR 的性能。
使能模式比较器(Enable Pattern Comparator):如激活,则可以使用模式匹配指令 pcmpbf,pcmpeq,pcmpne。模式匹配字节查找指令(pattern comparator byte find, pcmpbf)返回找到的第一个字节的位置,提高字符串和模式匹配操作的效率。若使能,SDK 库会自动使用这个指令。pcmfeq 和 pcmpne 指令根据两个字是否相同,返回 1 或者 0。这些指令会提高 setting flags 的效率,编译器会自动使用它们。激活这个选项还可以 count leading zeros 指令,clz。clz 指令能提高优先级编码的效率。
使能保留的加载/保存和交换指令(Enable Reserved Load/Store and Swap Instructions):lbur,lhur,lwr,sbr,shr,swr,swapb,和 swaph。这些指令能够以相对的字节序来读写数据,交换指令能交换字节或者半个字长。当用 little-endian 的MicroBlaze 访问 big-endian 的网络时,可以提高效率。
使能额外的流命令(Enable Additional Stream Instructions):当使用 AXI4-Stream 链接时,提供额外的功能。这包括动态访问指令 GETD 和 PUTD,这两个指令用寄存器来选择接口。(重要:一定要激活流异常功能,才能使用这些指令,而且知道选择一个流链接)
单击 Next 进入下一页配置:
这一页是对 microblaze 的调试接口进行配置,选择默认的 BASIC 配置
单击 Next 进入下一页配置:
该页面主要用于设置总线接口,设置本地内存总线接口、AXI 总线接口、Stream 总线接口
单击 OK 完成配置,产生使用 VIVADO BD 的自动化功能
设置如下
自动化连线后
3.3 添加 AXI UARTLite IP
我们还要添加一个 UART 用于串口打印,因为不需要复杂功能,我们只要添加一个基本的 UART IP
设置 UART 核
通过连线的方式,连接到 AXI interconnect,增加 AXI interconnect 的接口,这里的操作建议看视频
连接 AXI 接口到 UART 的 AXI 接口
连接中断
连接时钟
连接复位
3.4 CLK_WIZ 时钟设置
修改 clk_wiz 时钟输入,这里注意每个板子的输入可能不一样,有单端,有差分,有 25M 50M 100M 200M,请大家核对原理图
取消时钟复位
把时钟输入,和 UART 端口引出
相同方法,引出时钟
修改时钟名,让时钟名符合使用习惯
最后的整理我们发现软件还提示有线未连接
点击自动连接看下,发现是一个复位,关闭,准备手动连接复位信号
复位信号,连接到 clk_wiz 的 locked 脚
自动连线消失
因为只用到 1 个中断,修改 concat IP,改为 1
3.5 添加 AXI QUAD SPI IP 核
接下来,添加一个 axi_quad_spi 核
双击设置如下
增加 axi-interconnect
使用相同的方法,完成 axi-interconnect IP 的连线
3.6 完成基于 IP 图形化的最小系统设计
完成后的最小系统如下包含了 CPU、中断、调试模块、UART、QSPI:
3.7 BD(block design)层次化功能
我们可以利用 BD 的层次化功能,把目前的最小系统层次化为 1 个最小系统,按下 ctrl+A 选中所有 IP
然后右击,创建层次化
我们可以取一个名字,这里我们输入 MinSoc
现在看起很不舒服
继续右击,选中 Regenerate Layout
现在看起来非常清爽了,端口只包含了时钟输入、串口、FLASH
3.8 地址空间的分配
PS(microblaze cpu 或者 ARM 简称 PS)通过访问地址空间可以实现寄存器,或者内存的访问。检查地址空间的分配,BRAM 的地址空间已经分配,AXI_INTC IP 地址也已经分配,UART 和 SPI 的的地址没有分配。
选中 assign ALL
分配完成后
我们发现 BRAM 的内存大小需要设置到 64KB 或者更大,可以放一些基本的程序,修改后如下
3.9 VIVADO 自动校对功能
利用 VIVADO 自动化校验功能
现在图形化的设计已经完成
3.10 自动产生调用 BD 代码的接口代码
BD 图形化设计本质还是 FPGA 代码,是一种图形化形象编程的方式。
检查自动产生的顶层文件,可以看到顶层文件调用了 BD 模块
3.11 绑定 FPGA pin 脚
这需要看原理图,以 MLK-F9-100T 为例,为了方便管理文件,米联客统一在工程路径下新建 uisrc 路径,和以下文件夹,其中 04_pin 放 pin 脚约束,我们这里可以串接一个 fpga_pin.xdc 文件,保存到 04_pin 路径
右击 constrs,选中 add sources
如果有存在的文件可以选中 add files 否则选 Create files
输入 fpga_pin
可以手动输入也可以先综合后,通过软件分配,我这里手动输入
设置完成后如下
3.12 编译 FPGA 工程
4 编译完成后,导出硬件
米联客会新建 3 个文件路径
到此,完成了 SOC FPGA 部分的设计工作
5 导出导入 BD 的 tcl 脚本方法
最小系统搭建完成之后,在之后的设计中可能会再次使用到这一部分的设计,为了避免重复的设计,浪费开发时间,笔者这里介绍一种高效的工程管理方式——将 BD 文件导出为 tcl 脚本。导出 tcl 脚本之后,在下次设计中,我们就只需要运行 tcl 脚本即可完成此部分电路的配置,能有效的节省开发时间。
5.1 导出 BD 为 tcl
首先确保 Block design 处于被打开的状态,在 TCL 控制台中输入如下命令可将 BD 文件导出为 tcl 脚本。
5.2 导入 BD tcl
新建一个 vivado 工程
自定义 IP(如果用户用到自定义 IP 需要设置,没用到不需要设置)路径设置,如果用到必须设置,否则导入 tcl 会找不到自定义 IP。
本实验没有用到自定义 IP
导入 TCL 到新的 vivado 工程
运行完 source 指令之后,系统会自动生成我们之前搭建好的 BD 文件,之后我们就可以使用这个文件来搭建最小系统。
6 搭建 Vitis-sdk 工程
创建 soc_base sdk platform 和 APP 工程。
6.1 创建 SDK Platform 工程
启动 Vitis-Sdk
设置好路径
米联客资料中的路径规范如下图:
soc_prj 里面是基于 SOC 的硬件工程源码
soc_hw 里面是 xsa 格式文件,soc_prj 编译会导出 system_wrapper.xsa 到这个文件
soc_sdk 里面是裸机的 sdk 工程,sdk 工程创建依赖 soc_hw 中的 system_wrapper.xsa
单击 Create Platform Project 创建基于开发平台的工程
添加之前创建的 system_wrapper.xsa 文件
6.2 创建 hello_world APP 工程
自动产生一个 helloworld 传输输出程序
右击工程编译
7 程序分析
hello_word APP 就是简单通过调用 FPGA 工程中的 uart-lite IP 串口输出一些字符信息,程序代码简单不做分析。双击,lscript.ld 可以看到我们这里只有 BRAM 的内存
如果右击,选中 Generate Linker Script
对于本系统,由于只有 BRAM 可以使用因此代码、数据、堆栈都放在了 BRAM 中。这里 BRAM 大小 64KB
8 实验演示
8.1 硬件接线
8.2 实验结果
为了观察实现结果,需要打开串口
首选选中 Debug,出来 Vitis Serial Terminal,串口终端
设置正确的串口号
单击 OK 打开终端
选中 Design 切换界面
右击选中调试
双击 System Project Debug
选中 SystemDebug_hellowrld_sytem 单击 debug
输入结果如下,最小系统运行正常
|