SoC平台环境搭建

在这里插入图片描述

SoC平台环境搭建

作者:毛茏玮 / Saint
掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a
微博:https://weibo.com/5458277467/profile?topnav=1&wvr=6&is_all=1
GitHub:github.com/saint-000
CSDN: https://me.csdn.net/qq_40531974

一、实验目的
1.了解SoC平台环境搭建的具体操作流程
2.学习Xilinx Vivado&SDK 2017.3工具的使用
3.熟悉SoC平台环境搭建过程和工作原理

二、实验内容
以PS与PL协同设计实现GPIO为例,自行搭建SoC平台环境。
将FPGA当做一个PS处理器的外设,通过寄存器地址映射到PS的寻址空间。在处理器中使用C程序访问这些寄存器,来实现软件和逻辑结合的协同设计的效果。
具体步骤是先在VIVADO中配置ZYNQ处理器,做好FPGA的外设,互联完成之后生成BIT流文件下载到板子。在SDK环境下开发好软件之后,进行在线调试运行。

三、实验步骤
1.打开桌面VIVADO 2017.3,点击Create Project创建新工程。为新工程命名,选择工程保存路径,点击Next。选择芯片xc7z020clg484-1,点击Next → Finish。点击Create Block Design,创建块设计,并命名

2.在右侧Diagram窗口空白处右击 → Add IP。搜索zynq,双击ZYNQ7 Processing System,添加zynq处理器,并点击Run Block Automation,勾选处理器→ 点击OK,会自动进行一些配置

3.再添加两个GPIO核,在Diagram窗口空白处右击 → Add IP → 搜索gpio → 双击。操作两次,添加两个AXI GPIO核,点击Run Connection Automation,勾选All Automation,点击OK,进行自动配置。自动连接之后在空白处右击选择Regenerate Layout,重新布局

4.双击ZYNQ处理器核,进行配置,更改DDR型号为MT41K256M16 RE-15E,将Bank1 I/O电平设为1.8V,勾选Uart1,用于通过串口查看程序打印信息

5.将GPIO IP核的名字和端口名称修改为LED和SW。双击LED IP核,配置LED为输出,GPIO Width设置为8,对应8个LED灯,点击OK。双击SW IP核,配置SW为输入,GPIO Width设置为8,对应8个拨码开关,点击OK

6.新建约束文件:右击Constraints → Add Sources → 点击Next—Create File,为文件命名,点击OK → Finish。根据EES331用户手册中LED和SW的管脚约束表,在PINS_SET.xdc中添加引脚与电平约束并保存

7.生成顶层文件:先右击system → Generate Output Products → Generate,再右击system → Create HDL Wrapper → OK。Vivado会为IP子系统生成一个顶层文件,以便对该系统进行综合、实现并生成比特流

8.工程配置完成,点击左下侧Generate Bitstream生成比特流,点击Yes → OK,等待比特流生成。若没有其他错误,比特流生成完成后直接关闭弹出的窗口或选择查看报告

9.硬件工程设计好之后,可在以下窗口中看到系统分配给外设的地址。接下来将硬件工程导出到SDK,在SDK中进行软件编译与运行(注:不要单独打开SDK,是在VIVADO中导出)。VIVADO -> File → Export Hardware Design to SDK,导出硬件到SDK,打钩,包括比特流,点击OK

10.打开SDK:File → Launch SDK → OK,进入SDK界面。在SDK中新建工程对LED和SW进行编程,实现相应功能。为新工程命名,并产生相应的BSP → 注意选Next → 选择空工程 → Finish

11.在新建的工程中添加源文件,新建Source File或者Header File,为文件命名,注意要跟上文件类型.c或.h,点击Finish,在源文件中添加代码

12.硬件和软件设计好之后,保存工程,接下来调试和运行程序,运行之前先把板子的上所有拨码开关拨到下面。使用USB线连接PC机和开发板J3端口(JTAG/PS_UART),打开板子开关,在Vivado中点击左下角Open Hardware Manager → Open target → Auto Connection
若连接不上板子
(1) 重启板子或电脑:开关断开或按下板子上的复位按钮(LED和数码管旁边S3/POR(B5))
(2) 杀进程:打开任务管理器——进程——hw_server.exe

13.下载比特流:点击Program device,在弹出的窗口中找到工程的比特流,比特流文件在工程中的路径为:project_name/project_name.runs/impl_1/system_wrapper.bit,如下图,点击Program下载比特流到板子。

14.若运行程序,则右击工程——Run As ——Launch on Hardware(GDB)
若调试程序,则右击工程——Debug As——Launch on Hardware(GDB)

15.查看串口打印:使用桌面串口工具Putty,设置波特率和端口号。
端口号查看方式:右击桌面电脑/计算机 → 管理 → 设备管理器 → 端口

16.若工程正确,可看到8个LED灯循环闪烁,向上拨动任意一个拨码开关时,流水灯运行到最后一个LD7时停止。

四、实验结果
实验1.通过配置IP核以及创建约束文件来生成顶层文件,导出比特流文件,搭建好硬件逻辑。实验截图如下:
在这里插入图片描述
在这里插入图片描述
顶层文件代码:

set_property PACKAGE_PIN V4 [get_ports {led_tri_o[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[0]}]

set_property PACKAGE_PIN U6 [get_ports {led_tri_o[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[1]}]

set_property PACKAGE_PIN U5 [get_ports {led_tri_o[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[2]}]

set_property PACKAGE_PIN V7 [get_ports {led_tri_o[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[3]}]

set_property PACKAGE_PIN W7 [get_ports {led_tri_o[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[4]}]

set_property PACKAGE_PIN W6 [get_ports {led_tri_o[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[5]}]

set_property PACKAGE_PIN W5 [get_ports {led_tri_o[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[6]}]

set_property IOSTANDARD LVCMOS33 [get_ports {led_tri_o[7]}]
set_property PACKAGE_PIN U7 [get_ports {led_tri_o[7]}]

  

set_property PACKAGE_PIN AB6  [get_ports {sw_tri_i[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[0]}]

set_property PACKAGE_PIN Y4  [get_ports {sw_tri_i[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[1]}]

set_property PACKAGE_PIN AA4  [get_ports {sw_tri_i[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[2]}]

set_property PACKAGE_PIN R6  [get_ports {sw_tri_i[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[3]}]

set_property PACKAGE_PIN T6  [get_ports {sw_tri_i[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[4]}]

set_property PACKAGE_PIN T4  [get_ports {sw_tri_i[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[5]}]

set_property PACKAGE_PIN U4   [get_ports {sw_tri_i[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[6]}]

set_property PACKAGE_PIN V5   [get_ports {sw_tri_i[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw_tri_i[7]}]

实验2.在SDK进行软件的编写。实验截图如下:
在这里插入图片描述
实验代码如下:

/*
 * gpio_tst.c
 *
 *  Created on: 2018年11月8日
 *      Author: Saint
 *      Function:8个LED实现流水灯,向上拨动任意一个拨码开关时,流水灯运行到最后一个LD7时停止
 */



#include"xparameters.h"
#include"xgpio.h"
#include"xil_printf.h"//有输出语句就要用到
#include"xil_cache.h"

#define GPIO_BITWIDTH 8
#define GPIO_LED_DEVICE_ID 0
#define GPIO_SW_DEVICE_ID 1
#define LED_DELAY 10000000  //简单的延时参数宏定义
#define LED_MAX_BLINK 0x1 //闪烁次数
#define LED_CHANNEL 1
#define printf xil_printf

XGpio GpioOutput;
XGpio GpioInput;
u32 flag=0;
u32 DataRead;

int Gpio_led(u16 Deviceid,u32 Gpio_Width)
{
	volatile int delay;
	u32 Ledbit;
	u32 Ledloop;
	int status;
	status=XGpio_Initialize(&GpioOutput,Deviceid);
	if(status !=XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	XGpio_SetDataDirection(&GpioOutput,LED_CHANNEL,0x0);
	for(Ledbit =0x0;Ledbit < Gpio_Width;Ledbit++)
	{
		for(Ledloop=0x0;Ledloop<LED_MAX_BLINK;Ledloop++)
		{
			XGpio_DiscreteWrite(&GpioOutput,LED_CHANNEL,1<<Ledbit);
			for(delay=0;delay<LED_DELAY;delay++);
			XGpio_DiscreteClear(&GpioOutput,LED_CHANNEL,0x00);
			for(delay=0;delay<LED_DELAY;delay++);
		}
	}
	return XST_SUCCESS;
}

u32 Gpio_sw(u16 Deviceid,u32 *DataRead)
{
	int Status;
    Status = XGpio_Initialize(&GpioInput, Deviceid);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	XGpio_SetDataDirection(&GpioInput, LED_CHANNEL, 0xFFFFFFFF);
	*DataRead = XGpio_DiscreteRead(&GpioInput, LED_CHANNEL);

	u32 data;
	data=*DataRead;
    return data;
}

int main()
{
	while(1)
	{
		flag =Gpio_sw(GPIO_SW_DEVICE_ID, &DataRead);
	    if(flag == 0)
	    {
			u32 status;
		    status = Gpio_led(GPIO_LED_DEVICE_ID,GPIO_BITWIDTH);
		    if(status==0)
		    {
		    	printf("SUCCESS.\r\n");
		    }
		    else
			    printf("FAIL.\r\n");
	    }
	    else
	    {
	    	u32 Ledbit;
		    for(Ledbit =0x0;Ledbit < GPIO_BITWIDTH;Ledbit++)
		    	XGpio_DiscreteClear(&GpioOutput,LED_CHANNEL,0x00);
	    }
	}
}

实验3.连接开发板,下载比特流,执行软件程序并进行串口打印。实验图如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、实验总结
1.知道怎么搭建SoC平台环境,知道如何设计GPIO。
2.理解将FPGA当做一个PS处理器的外设,通过寄存器地址映射到PS的寻址空间。使用C程序访问寄存器,熟悉软件和逻辑结合设计。

实验心得:在编写GPIO软件代码时,我们可以通过改变GPIO_BITWIDTH定义的数值来改变代码功能。实验中LED在拨码开关的作用下,呈现向左移动的流水灯显示,我们可以通过改变for()循环语句里的代码,使流水灯向右移动。

具体代码:For(Ledbit=0x000010000;Ledbit<GPIO_Width;Ledbit--)
在这里插入图片描述

六、实验思考题
1.ZYNQ 7000中提供了哪几种实现GPIO的方式,这几种之间有什么区别与联系?
zynq中三种实现GPIO的方式,分别为MIO、EMIO和IP方式。
MIO和EMIO方式是使用PS部分的GPIO模块来实现GPIO功能的。
而IP方式是在PL部分实现 GPIO功能
MIO:
在这里插入图片描述

EMIO:
在这里插入图片描述

IP:
在这里插入图片描述
在这里插入图片描述
MIO方式不占用PL部分资源,其输出管脚只能为固定的54个,EMIO方式会占用PL的管脚资源,其管脚可在PL部分任意选择,IP方式除了占用PL部分管脚资源外还会占用PL部分逻辑资源,所以其GPIO功能在PL部分实现其调用函数也和前两种不同,EMIO和IP方式在vivado都需要绑定管脚。
在本次实验中,我们使用的是MIO方式。

2.Create Block Design过程中,添加IP核之后不点击Run Block Automation和Run Connection Automation,尝试自己连接线,理解其工作原理,并叙述。
Run Block Automation是完成对ZYNQ7 Processing System IP核的配置
在这里插入图片描述
在这里插入图片描述

事实上,我们可以知道Run Block Automation和Run Connection Automation可以方便我们在各个模块之间连接的快速布局,清晰的连接关系使我们的逻辑布局不会因为打乱而导致连接上出现逻辑错误。
在这里插入图片描述

我们在通过自己布局发现,不仅只有GPIO的连接,我们还要考虑复位模块,AXI总线,可见我们的信息传输采用总线传输方式,当外设上的GPIO信息发生变化时通过AXI总线向Zynq处理器核传送信息,Zynq处理器核接收信息后发送反馈给GPIO以完成一个系统信息变化的传输,同时也有复位模块,当按下复位键时,该模块也会有变化,传送给处理器,处理器接收到信息变化执行相应反馈。

猜你喜欢

转载自blog.csdn.net/qq_40531974/article/details/83897886