本文转载自:巨大八爪鱼的博客
本教程以米联客XC7A35T FGG484-2开发板为例,详细讲解一下用Xilinx Vivado 2020.1创建MicroBlaze软核工程,然后再用Xilinx Vitis 2020.1建立Hello World C程序工程的完整操作步骤。最后程序运行起来后,还要在Vitis里面将程序固化到SPI Flash中,断电再开机后也能启动运行。
(关于带外部DDR3内存的工程的建法,请参阅https://blog.csdn.net/ZLK1214/article/details/113201726)
米联客开发板自带的那个PDF教程(名字叫Artix-7修炼秘籍)里面,讲MicroBlaze的时候用到了DDR3内存,最后C程序是跑在DDR3内存里面的。固化的时候,需要多固化一个SREC SPI Bootloader工程。bootloader的作用是开机的时候将SPI Flash里面存的C语言程序加载到外部DDR3内存上,然后跳转过去执行,这个过程(对helloworld程序来讲)需要半分钟的时间,这使得开机启动非常慢。
实际上MicroBlaze的运行根本就不需要DDR3内存,在FPGA片内的BRAM中运行就可以了。没了DDR3内存,Vivado block design会变得简单很多。没有了SREC SPI Bootloader,Vitis里面固化程序也变得非常非常简单,开机也能瞬间启动,不会等上半分钟串口才能输出个Hello World。
开发板上的晶振频率为50MHz,是接到FPGA的V4引脚上的。FPGA片内BRAM内存的容量为225KB(手册上写的是1800b,除以8就得到了225KB)。存储程序用的外部SPI Flash型号为MT25QL128。
ALINX基于Vivado的MicroBlaze基础教程.pdf:https://pan.baidu.com/s/1q3wgbaq2OX0pozCyTo2faQ(提取码:m6zg)
在Vivado 2020.1里面建好一个空白的工程后,首先新建一个Block Design,名称可保持默认:
然后,添加MicroBlaze IP核:
点击Run Block Automation:
MicroBlaze运行内存选择128KB:
Run Block Automation自动生成了很多外设出来。其中就有clk_wiz_1倍频器,但时钟输入端是差分输入,还带有一个reset复位输入。我们板子上的50MHz晶振时钟输出只有1个引脚。所以双击这个IP修改一下设置。
输入的时钟改为50MHz,单端输入:
输出的时钟为100MHz,作为MicroBlaze的运行时钟。下面要把reset复选框去掉,使Clocking Wizard没有复位输入引脚。
然后,在clk_in1的右键菜单上选择Make External命令,引出clk_in1引脚。后面需要在xdc文件里面将这个引脚和FPGA上连接外部晶振的V4引脚绑定。
Clocking Wizard输出的locked信号代表倍频是否成功。locked=0时说明倍频还未成功,locked=1时说明倍频已成功,时钟输出已稳定。因此这个locked引脚可以作为MicroBlaze的复位引脚,在Block Design里面手动连线到rst_clk_wiz_1_100M的ext_reset_in引脚上,低电平时复位。
接下来,添加AXI Uartlite串口IP核,用于程序中printf打印和scanf输入:
将串口的波特率改为115200:
点击Run Connection Automation,自动连线:
最终的Block Design连线如下图所示。没有了DDR3内存,整个Block Design是非常简单的。
在Address Editor选项卡上可以看到片内BRAM内存的地址范围,以及Uartlite的寄存器地址范围:
点击Generate Block Design:
然后,点击Create HDL Wrapper,根据Block Design创建Verilog顶层模块:
有了生成的Verilog模块代码(design_1_wrapper.v),就可以点Synthesis综合了:
等待Generate Block Design和Run Synthesis完毕:
综合完毕后,选择Open Synthesized Design,点击OK,接下来我们要绑定FPGA管脚。
需要配置的引脚就三个:50MHz晶振时钟输入引脚、串口接收引脚和串口发送引脚。是不是很简单?
将引脚配置保存为pins.xdc文件,然后打开这个xdc文件,我们要加一段代码,使板子开机启动的时候,用4线QSPI方式加载SPI Flash中保存的程序。
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE Yes [current_design]
这个步骤非常关键!!!!不添加这段代码的话,开机的时候就是1线启动,那就要花好几秒的时间才能启动成功,才打印的出来Hello World 。
而且这个地方一旦忘了这个步骤,建好Vitis工程后,再来添加这段代码,就只有把整个Vitis workspace删了重建,新的设置才能生效!!!
所以千万不能忘了!!!!!!!!
点击Generate Bitstream,生成Vivado工程的bit文件:
bit文件生成成功后,点击Export Hardware,导出xsa文件:
这里要选择Include bitstream:
注意一下xsa文件的保存路径。
有了xsa文件,就可以启动Vitis 2020.1了。
这里选择Vitis workspace的存放位置,单独再找一个文件夹来存放Vitis工程:
进去后,先建立Platform Project:
选择刚才Vivado导出的xsa文件:
选择完之后要Build一下Platform工程:
再建立一个Application Project,用来写C语言代码:
直接用里面现成的代码Build一下:
然后点击运行:
提示正在将程序下载到FPGA中:
下载完了之后,就可以看到串口里面输出了Hello World了。
但是这个程序掉电就会丢失,我们需要将这个程序固化到SPI Flash里面,让开发板断电后一开机就能运行这个程序,打印出Hello World。
固化的方法非常简单,只需要两步。
第一步是在Program FPGA对话框里面,将Vivado工程的Verilog代码生成的design_1_wrapper.bit文件和Vitis工程的C代码生成的hello_world.elf文件合并成一个download.bit文件:
第二步就是在Program Flash对话框中,把合并后的download.bit文件烧写到SPI Flash里面:
注意选择SPI Flash的型号。Offset可以不用填,默认就是0。
这个时候就固化成功了。开发板断电之后,程序也能启动运行。并且是瞬间就启动成功,在串口中打印出Hello World。
如果发现microblaze程序固化后,开机启动很慢,要好几秒之后串口才能打印出Hello World。
那肯定是忘了往Vivado工程里面的xdc文件添加SPI 4位模式的配置了。
这个时候要回到Vivado工程改xdc文件,然后generate bitstream,然后export hardware。
然后,整个Vitis工程都必须删了重建!!!!!!
重新建立Platform工程,Build一下,再重新建立Application工程,再Build一下
点Program FPGA生成download.bit,再点Program Flash把download.bit固化到flash
开发板断电,再上电,瞬间就打印出了hello world。
切记,一旦忘了改xdc文件导致fpga microblaze开机启动很慢,vitis工程就必须重建。仅仅update hardware specification,clean一下再build一下platform工程,是没有用的。
工程里面没有配置gpio模块,如果在c代码中加入gpio的代码,会提示找不到
14:17:00 **** Incremental Build of configuration Debug for project hello_world ****
make all
'Building file: ../src/helloworld.c'
'Invoking: MicroBlaze gcc compiler'
mb-gcc -Wall -O0 -g3 -c -fmessage-length=0 -MT"src/helloworld.o" -IE:/fpga_projects/test4/microblaze_test3/microblaze_test3/export/microblaze_test3/sw/microblaze_test3/standalone_domain/bspinclude/include -mlittle-endian -mcpu=v11.0 -mxl-soft-mul -Wl,--no-relax -ffunction-sections -fdata-sections -MMD -MP -MF"src/helloworld.d" -MT"src/helloworld.o" -o "src/helloworld.o" "../src/helloworld.c"
../src/helloworld.c:50:10: fatal error: xgpio.h: No such file or directory
50 | #include
| ^~~~~~~~~
compilation terminated.
'Finished building: ../src/helloworld.c'
' '
14:17:00 Build Finished (took 314ms)
这时应该:
(1)回到vivado工程的block design里面,把AXI GPIO模块加进去,按ctrl+s键保存,然后generate block design
(2)run synthesis,在schematic里面配置gpio管脚,然后generate bitstream,再export hardware
(3)回到vitis工程里面,这个时候就不需要删了重建vitis工程了,只需在(Assistant窗格)platform工程上update hardware specification(注意xsa文件的路径对不对,有可能是错的,要手动改过来),然后build一下platform工程
(4)这个时候,含有gpio代码的application工程就能编译通过了,能够找到xgpio.h和gpio的函数了