MicroBlaze:Xilinx官方软核学习与一些实验测试

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mmphhh/article/details/117339225

一、引言
1、MicroBlaze简介。

用于做嵌入式处理操作的软核,来加速系统设计。与传统独立CPU相比,软核嵌入式处理器同样有较高的处理能力,并且在可构建多核系统、可定制取舍等方面均优于传统CPU。下图是传统的系统架构与SOPC架构,即较新的可编程片上系统。

MicroBlaze 是 Xilinx 公司提供的一款 32/64 位软核嵌入式处理器,是一款高度灵活可配置的易用型处理器, 它能够利用 FPGA 内部通用资源和相关 IP 核,实现可编程片上系统(SOPC)的设计。该处理器采用的是32 位 RISC(Reduced Insrtction System Computer)优化结构和 Harvard 总线结构,广泛适用于 Spartan、 Virtex 和 Artix 等系列的 FPGA。

MicroBlaze 软核嵌入式处理器是高度可定制的 IP 核,支持 70 多个配置选项,有 32 个 32 位通用寄存器以及 2 个 32 位特殊寄存器(PC 指针寄存器和 MSR 状态标志寄存器)。另外 MicroBlaze 软核处理器还配有指令和数据缓存、 浮点单元、内存管理单元和许多其他选项,从而大大提高其运算性能。 MicroBlaze 软核嵌入式处理器的所有指令字长都是 32 位,具有 3 个操作数和两种寻址模式, 指令按功能可划分为:逻辑运算、算术运算、分支、存储器读/写和特殊指令等等。指令以并行流水线的方式执行,其流水线可分为取指、译码和执行。

下图为 MicroBlaze 的框图,展示了固定的硬件特性模块和可配置选项,如指令和数据缓存。

MicroBlaze 处理器的外部接口定义如下:

  • DPLB(Data Processor Local Bus):数据接口,处理器本地总线。
  • DOPB(Data On-chip Peripheral Bus):数据接口,片上外设总线,该接口实现 CPU 与片内外设的数据交换。
  • DLMB(Data Local Memory Bus):数据接口,本地存储器总线, 该总线为 CPU 与本地块存储器间的数据交换通道。
  • IPLB(Instruction Processor Local Bus): 指令接口,处理器本地总线。
  • IOPB(Instruction On-Chip Peripheral Bus): 指令接口,片上外设总线, CPU 通过此总线读取外部存储器的程序代码。
  • ILMB(Instruction Local Memory Bus): 指令接口,本地存储器总线, 该总线与内部块存储器相连,提供高速指令的提取。
  • MFSL0…15 (Fast Simple Link FSL master interface): FSL 主设备数据接口,提供点对点的通信通道。
  • SFSL0…15 (Fast Simple Link FSL slave interface): FSL 从接口,提供点对点的通信通道。
  • IXCL(Instruction side Xilinx Cache Link interface): 指令侧高速缓存链接接口。
  • DXCL(Data side Xilinx Cache Link interface):数据侧高速缓存链接接口。
  • MicroBlaze 处理器通常有三种预设配置,如下图所示:

  • Microcontroller:运行裸机应用程序的简单微控制器。
  • Real-Time:具有高速缓存和与运行嵌入式实时操作系统的实时处理器。
  • Application:最后是带有运行 Linux 的内存管理单元的应用处理器。
  • MicroBlaze可以在所有 Xilinx FPGA 中用作独立处理器,也可以在 Zynq SoC 系统中用作协处理器。

    2、MicroBlaze系列计划。

    MicroBlaze系列属于FPGA软核部分的学习,主要还是CPU相关的学习,将其列为了FPGA_ASIC部分。首先,会做一部分实验,包括串口、LED、按键中断、定时器中断等。接着,使用Xilinx提供的一些AXI模板,来设计一些能挂接MicroBlaze的IP。最后,MicroBlaze应该有些有趣的项目了,考虑用它来做一些较为大型的设计。开发板使用达芬奇Pro。

    二、HelloWorld实验
    1、基本流程。

    step1 至 step4 为硬件设计部分,在 Vivado 软件中实现。step5 为软件设计部分,在 Vitis 软件中实现。step6 为功能的验证。

    2、嵌入式最小系统。

    以 MicroBlaze 为核心、 LocalMemory(片上存储) 为内存,加上传输信息使用的 UART 串口就构成了嵌入式最小系统。当程序比较简单时, Local Memory 可以作为程序的运行空间以及存储空间,空间大小可以根据需要设置最小 8KB 到最大 128KB;当程序比较复杂的时候,我们也可以使用片上搭载的外部存储器(如 DDR3)作为程序的运行空间以及存储空间。

    AXI Interconnect IP 核用于将一个(或多个) AXI 存储器映射的主器件与一个(或多个) 存储器映射互联。互联实际上是一个开关,它管理并指挥所连接的 AXI 接口之间的通信。

    3、工程搭建。

    1°添加MicroBlaze。

    2°对IP进行配置。

    Predefined Configurations:用于配置模板。点击 Select Configuration 右侧的目录框我们能够看到多个模板选项。本次试验不需要用到模板,因此保持默认选项“Current settings”就可以。

    Select Processor Implementation:用于选择 32 位或 64 位处理器。 64 位处理器将两个 32 位通用寄存器扩展为一个 64 位寄存器,提供处理 64 位数据的附加指令,并且可以使用最多 64 位地址寻址和最多 4 个 EB 指令和数据。 一般情况使用 32 位处理器就可以了。

    Select implementation optimization:用于使能面积优化功能,打开其右侧的目录,我们可以看到有PERFORMANCE、 AREA 和 FREQUENCY 三个选项表示三种优化方式,其中 AREA(区域)表示三级优化,速度最慢占用资源最少; FREQUENCY(频率)表示八级优化,速度最快占用资源最多;PERFORMANCE(性能)是五级优化,速度和资源占用量在 AREA 和 FREQUENCY 两者之间,本实验我们选择PERFORMANCE。

    Enable MicroBlaze Debug Module Interface:使能调试功能,一般情况下我们都开启该功能,只有在资源十分紧张的情况下才会禁止此功能

    Use Instruction and Data Caches: 使用指令和数据缓存。当使用外部存储时,激活这个选项可以明显地改善性能,由于本次实验我们使用的是本地存储,该选项对实验没影响,因此不选择。

    Enable Exceptions:异常功能的使能。

    Enable Discrete Ports:使能软核上的独立端口。

    配置完成后点击“Next”进入第二页 General 页面, General 页面能够选择单元的选择和优化。 直接保持默认就可以了,点击“Next”进入 Debug 页面

    Debug 页面是进行断点设置和查看点的数量。 这里我们同样保持默认设置。

    Buses页面能进行总线设置。Local Memory Bus Interfaces是本地内存总线接口(LMB),我们将两项都选中; AXI and ACE Interfaces 是 AXI 和 ACE 接口, 下拉选择 AXI 接口, 勾选 Enable Peripheral AXI Data interface 用来控制外围模块(AXI 数据接口是与外围接口数据交互的总线, 之后所有模块都挂在这个总线上); Stream Interfaces 和 Other Interfaces 分别用于开启 Stream 流接口和一些其它接口,本实验中我们直接保持默认配置就好了,配置完成后点击“OK”完成 MicroBlaze 的配置。

    3°点击Run Block Automation进行自动连线。

    在弹出的界面选择“Local Memory”为 64KB,其余选项默认,点击“OK”。

    4°自动连接后,生成四个新模块。

    clk_wiz_1 模块提供系统时钟, rst_clk_wiz_1_100M 是系统复位模块,用以给系统各个模块提供复位信号, mdm_1 是 MicroBlaze 调试模块, microblaze_0_local_memory 模块是片上存储模块。

    5°时钟配置。

    将输入时钟设为50MHz,在 Source 目录将信号类型改为单端信号。切换到 Output Clocks 页面设置输出时钟,输出时钟设为 100MHz,在 Reset Type 栏选择“Acitive Low”设置为低电压复位,点击“OK”。

    6°时钟模块Make External改名。

    更改一些外部连接的名称后,再将“ext_rest_in”与“sys_rst_n”进行连接。

    7°添加AXI UART的IP。

    点击左上方“Run Bonnection Autmation”在弹出的页面中,选中所有信号,点击“OK”进行自动连线。

    可以生成下面新的互联模块。uart模块和MicroBlaze之间的数据可以相互传输。

    验证一下,没啥问题。后面就是常规的generator,生成wrapper,添加下约束并综合实现等。

    具体的管脚约束文件如下所示:

    create_clock -period 20.000 -name sys_clk [get_ports sys_clk]
    set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS15} [get_ports sys_clk]
    set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS15} [get_ports sys_rst_n]
    set_property -dict {PACKAGE_PIN E14 IOSTANDARD LVCMOS33} [get_ports UART_rxd]
    set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS33} [get_ports UART_txd]

    最终,得到xsa的平台文件,用于vitis新建工程用。

    新建一个vitis_prj文件夹,用来做开发vitis软件的环境。

    8°Launch Vitis并建立工程。
    1)tools——>Launch Vitis。

    2)选择之前新建的vitis_prj文件夹,作为工作空间。

    3)新建一个application project。

    4)添加自己刚刚生成的硬件平台。

    5)CPU默认microblaze_0,OS选择standalone,编程语言选C语言。模板选择HelloWorld。

    9°点击展开硬件平台 Platfrom 工程“design_1_wrapper” , 双击 platform.spr 即可看到 Platform 对应生成的 BSP 工程(Board Support Package 板级支持包), 在这里可以对 BSP 进行配置, 里面包含了用于应用程序开发的驱动信息。

    10°源文件代码。

    非常简单。可以看到 init_platform 函数的作用是使能 caches 和初始化 uart; cleanup_platform 函数的作用是取消使能 caches。 对于软件部分我们不需要做修改,直接使用官方的实例就可以了。如果想查看函数的定义,可以按住 Ctrl 键不放,用鼠标点击相应的函数,就会跳转到其定义的地方(超级有用)。

    #include
    #include "platform.h"
    #include "xil_printf.h"

    int main()
    {
    init_platform();

    print("Hello World\n\r");

    cleanup_platform();
    return 0;
    }

    11°编译工程。

    接下来编译工程, 选中 APP 工程“HelloWorld_system” ,右键“Build Project” 或点击图中“锤子” 按键,进行工程编译。工程编译结束后, 成功生成 elf 文件, 在 Vitis 软件右下 Console 信息栏中会打印相关信息。

    12°Terminal 窗口打开。

    在 Vitis 软件的下方,找到 Terminal 窗口。如果界面中没有找到该窗口,或者操作过程中把该窗口给关闭了,则可以通过在菜单栏中依次点击“Window->Show view->Terminal 文件夹->Terminal”, 最后点击“Open”,接口成功添加 Terminal 窗口。

    下面开发的板子,每次按下复位都会输出一个Hello World,测试成功。

    三、AXI_GPIO实验
    AXI GPIO IP 核为 AXI 接口提供了一个通用的输入/输出接口。 AXI GPIO 是一个软核(Soft IP),是由用户通过配置芯片的逻辑资源来实现的一个功能模块。。

    AXI GPIO 可以配置成单通道或者双通道,每个通道的位宽可以单独设置。另外通过打开或者关闭三态缓冲器,AXI GPIO 的端口还可以被动态地配置成输入或者输出接口。

    模块的左侧实现了一个 32 位的 AXI4-Lite 从接口,用于主机访问 AXI GPIO 内部各通道的寄存器。 当右侧接口输入的信号发生变化时,模块还能向主机产生中断信号。不过只有在配置 IP 核时选择“使能中断”,才会启用模块的中断控制功能。

    1、系统框图。

    由系统框图可以看出, AXI GPIO 和 AXI UART 都通过 AXI Interconnect 模块与 MicroBlaze 互联,Microblaze 处理器输出 LED灯的控制信号,通过AXI Interconnect互联模块传输到AXI GPIO 模块, AXI GPIO 模块根据 AXI4-Lite 协议将 LED 灯控制信号解析出来,输出到 FPGA 的 LED 引脚,从而控制 LED 灯。

    2、UART实现另存为新工程。

    选择一个新的路径,另存为一个新的工程。

    下图为生成的一个新的工程。至此,在原工程的基础上成功创建了一个新的工程而没有破坏原来的工程,也避免了重新创建工程或复制工程后修改的麻烦。

    3、打开Block Design,新建一个AXI GPIO。

    自动连接后,得到下面的工程。

    管脚文件如下所示。
    create_clock -period 20.000 -name sys_clk [get_ports sys_clk]
    set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS15} [get_ports sys_clk]
    set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS15} [get_ports sys_rst_n]
    set_property -dict {PACKAGE_PIN E14 IOSTANDARD LVCMOS33} [get_ports UART_rxd]
    set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS33} [get_ports UART_txd]
    set_property -dict {PACKAGE_PIN V9 IOSTANDARD LVCMOS15} [get_ports {gpio_tri_io[0]}]
    set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS15} [get_ports {gpio_tri_io[1]}]
    set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS15} [get_ports {gpio_tri_io[2]}]
    set_property -dict {PACKAGE_PIN W7 IOSTANDARD LVCMOS15} [get_ports {gpio_tri_io[3]}]
    set_property BITSTREAM.GENERAL.COMPRESS TRUE [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 BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]

    4、综合实现,得到xsa文件,新建工程。

    打开platform.spr 文件,找到点击板级支持包“Board_Support_Package”,点击展开“Peripheral Drivers” , 右侧有相关文档和示例。点击“Documentation” 会在浏览器窗口打开 GPIO_API 文档, 会展示关于 GPIO 的详细信息, 想了解 GPIO 的,可以仔细浏览其中的信息。

    路径:D:/Xilinx/2019.2/Vitis/2019.2/data/embeddedsw/XilinxProcessorIPLib/drivers/gpio_v4_5/doc/html/api/index.html。

    这里,点击“Import Examples” ,会弹出下图的导入示例界面, 关于 GPIO 有四个示例。

    点击OK后,可以发现在左边的工程中,添加了新的样例工程。“xparameters.h”定义了一些默认的参数,“xil_printf.h”是打印函数用来控制打印信息,“xgpio.h” 文件包含 Xilinx 通用 I/O(Xgpio)设备驱动程序的软件 API 定义。我们本次实验的软件程序部分就可以根据官方示例“xgpio_example.c”进行设计。

    5、在src文件夹下,新建一个file文件。进行新的开发。

    新建一个工程。

    #include "xparameters.h"
    #include "xgpio.h"
    #include "xil_printf.h"
    #include "sleep.h"

    #define LED_ID XPAR_GPIO_0_DEVICE_ID //led器件ID
    #define LED_CHANNEL 1 //LED通道

    XGpio Gpio; //GPIO实例

    int main(void){
    int i=0;

    xil_printf("GPIO LED TEST\n\r");
    //初始化GPIO
    XGpio_Initialize(&Gpio, LED_ID);
    //为指定的信道设置方向 ,0 输出 ,1输入
    XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0);

    while (1) {
    //向指定通道写入数据,LED每0.5秒流转一次
    XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x01 << i);
    //循环计数,表示第几个灯亮
    if(i == 3)
    i = 0;
    else
    i = i + 1;
    //延时0.5秒
    usleep(500000);
    }
    return 0;
    }

    多调用了一个“sleep.h”的头文件,该头文件包含 ARM CortexA53、A9、 R5、 Microblaze 处理器特定的延迟 API。调用该文件中的相关函数可以实现延迟处理。宏定义了 LED_ID,使其为 XPAR_GPIO_0_DEVICE_ID。 如果在 Vitis 软件中,按住 Ctrl 键不放,将鼠标移动到 XPAR_GPIO_0_DEVICE_ID 上,当鼠标变成手指状时,单击鼠标左键,会自动跳转到 xparameters.h 文件中,该文件定义了各个外设的基地址、器件 ID、中断等,我们这里重新宏定义 XPAR_GPIO_0_DEVICE_ID 是为了以后方便修改。定义了 LED 的通道,这里我们指定通道 1。

    6、实验测试。

    实验结果,四个led循环流水。

    四、一些注意
    1、uart实验关键:microblaze基本的配置,复习vitis工程的建立。
    2、gpio实验关键:vivado工程另存为方式,vitis工程中导入模块模板。

    最新文章

    最新文章