AMBA协议AXI-Stream(板级验证)

系列文章目录

AMBA协议AXI-Stream(协议信号、设计实践)


文章目录

  • 系列文章目录
  • 前言
  • 一、环境
  • 二、验证SOC搭建
    • 2.1 系统框图
    • 2.2 IP核打包
    • 2.3 SOC系统硬件设计
    • 2.4 SOC系统软件设计
  • 三、开源地址


前言

  在上一篇中,我们已经讲述了AXI-Stream(以下简写AXIS)的相关信号和对应的缓冲模块设计;
  在本篇中,将给出后续的上板实验过程;


一、环境

  本次上板基于Xilinx 的Zynq 7010 FPGA,Digilent 的Zybo Z7板卡,Vivado集成开发环境;采用软硬协同的方式进行逻辑验证;
  板卡图片:

二、验证SOC搭建

2.1 系统框图

  在设计验证系统时,我们参考正点原子的AXI-DMA实验,只不过将其中的FIFO替换成我们自己编写的AXI-Stream-test模块;
  正点原子系统框图AMBA协议AXI-Stream(板级验证)_第1张图片  AXIS验证系统框图

AMBA协议AXI-Stream(板级验证)_第2张图片  验证需要zynq硬核的参与,PS端的HP内存映射接口与AXI DMA进行数据流的通信,GP接口与AXI DMA进行AXI-Lite通信,DMA将数据流以AXIS协议发送给AXI-Stream-test IP,并将AXI-Stream-test IP处理后的数据通过HP接口写入DDR3;


2.2 IP核打包

  若想进行Block Design设计,则需要将AXI_Stream_test逻辑打包成IP;

  1.选择Tools->Creat and Package New IPAMBA协议AXI-Stream(板级验证)_第3张图片  2.选择Package a specified directory
AMBA协议AXI-Stream(板级验证)_第4张图片  首先进行File Groups,然后选择Ports and Interfaces,点击+号
AMBA协议AXI-Stream(板级验证)_第5张图片选择axis_trl接口,取名M_AXISMode选择masterAMBA协议AXI-Stream(板级验证)_第6张图片  点击Port Mapping,绑定信号,绑定信息如下:
AMBA协议AXI-Stream(板级验证)_第7张图片
  继续绑定S_AXIS接口;AMBA协议AXI-Stream(板级验证)_第8张图片
  其端口映射如下:AMBA协议AXI-Stream(板级验证)_第9张图片
  4.点击Customization GUI,将C_M_Axis_Burst_Len参数托到Page0

AMBA协议AXI-Stream(板级验证)_第10张图片AMBA协议AXI-Stream(板级验证)_第11张图片5.点击Review and Package完成IP打包AMBA协议AXI-Stream(板级验证)_第12张图片

2.3 SOC系统硬件设计

  在Vivado中,SOC的BD设计如下所示:
AMBA协议AXI-Stream(板级验证)_第13张图片  其中,DMA配置如下:
AMBA协议AXI-Stream(板级验证)_第14张图片  取消勾选 Enable Scatter Gather Engine 选项;
  配置地址位宽为32
  配置数据流数据位宽为32


  其中,AXI_Stream_test IP配置如下:
AMBA协议AXI-Stream(板级验证)_第15张图片
  C_M_Axis_Burst_Len:为8(最大传输为8,每8个数据就拉高一次TLAST信号)
  Comb_Len:为4,缓冲4个数据(128bit);


2.4 SOC系统软件设计

  先后点击exportLaunch SDK
AMBA协议AXI-Stream(板级验证)_第16张图片
创建一个新工程;
AMBA协议AXI-Stream(板级验证)_第17张图片
AMBA协议AXI-Stream(板级验证)_第18张图片
在新工程中添加一个main.c文件,其中代码如下:

#include "xaxidma.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "../user/headfile.h"

/************************** Constant Definitions *****************************/

#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
#define RX_INTR_ID XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define DDR_BASE_ADDR XPAR_PS7_DDR_0_S_AXI_BASEADDR //0x00100000
#define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x1000000) //0x01100000
#define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) //0x01200000
#define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00300000) //0x01400000
#define RESET_TIMEOUT_COUNTER 10000
#define TEST_START_VALUE 0x0
#define MAX_PKT_LEN 32
/************************** Function Prototypes ******************************/

static int check_data(int length, u8 start_value);
static void tx_intr_handler(void *callback);
static void rx_intr_handler(void *callback);
static int setup_intr_system(XScuGic * int_ins_ptr, XAxiDma * axidma_ptr,
u16 tx_intr_id, u16 rx_intr_id);
static void disable_intr_system(XScuGic * int_ins_ptr, u16 tx_intr_id,
u16 rx_intr_id);

/************************** Variable Definitions *****************************/

static XAxiDma axidma;
static XScuGic intc;
volatile int tx_done;
volatile int rx_done;
volatile int error;

/************************** Function Definitions *****************************/

int main(void)
{
	int i;
	int status;
	u8 value;
	u8 *tx_buffer_ptr;
	u8 *rx_buffer_ptr;
	XAxiDma_Config *config;

	tx_buffer_ptr = (u8 *) TX_BUFFER_BASE;
	rx_buffer_ptr = (u8 *) RX_BUFFER_BASE;

	xil_printf("\r\n--- Entering main() --- \r\n");

	config = XAxiDma_LookupConfig(DMA_DEV_ID);
//	 if (!config) {
//	 xil_printf("No config found for %d\r\n", DMA_DEV_ID);
//	 return XST_FAILURE;
//	 }

	 status = XAxiDma_CfgInitialize(&axidma, config);
//	 if (status != XST_SUCCESS) {
//	 xil_printf("Initialization failed %d\r\n", status);
//	 return XST_FAILURE;
//	 }
//
//	 if (XAxiDma_HasSg(&axidma)) {
//	 xil_printf("Device configured as SG mode \r\n");
//	 return XST_FAILURE;
//	 }


	status = setup_intr_system(&intc, &axidma, TX_INTR_ID, RX_INTR_ID);
//	if (status != XST_SUCCESS) {
//	xil_printf("Failed intr setup\r\n");
//	return XST_FAILURE;
//	}


	tx_done = 0;
	rx_done = 0;
	error = 0;

	value = TEST_START_VALUE;
	for (i = 0; i < MAX_PKT_LEN; i++) {
		tx_buffer_ptr[i] = value;
		value = (value + 1) & 0xFF;
	}


	Xil_DCacheFlushRange((UINTPTR) tx_buffer_ptr, MAX_PKT_LEN);

	status = XAxiDma_SimpleTransfer(&axidma, (UINTPTR) tx_buffer_ptr,MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);
	XAxiDma_SimpleTransfer(&axidma, (UINTPTR) rx_buffer_ptr,MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

	while(1)
	{
		 while(!tx_done);
		 xil_printf("tx_done\n");
		 while(!rx_done);
		 usleep(100000);
		 xil_printf("Finish!\n");
		 Xil_DCacheFlushRange((UINTPTR) rx_buffer_ptr, MAX_PKT_LEN);
		 int i;
		 xil_printf("RES:");
		 for(i = 0;i< MAX_PKT_LEN;i++)
		 {
			 xil_printf("%x,",rx_buffer_ptr[i]);
		 }
		 xil_printf("\n");
		 sleep(5);
		 XAxiDma_SimpleTransfer(&axidma, (UINTPTR) tx_buffer_ptr,MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);
		 XAxiDma_SimpleTransfer(&axidma, (UINTPTR) rx_buffer_ptr,MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

	}
	 return XST_SUCCESS;
}

static void tx_intr_handler(void *callback)
{
	int timeout;
	u32 irq_status;
	XAxiDma *axidma_inst = (XAxiDma *) callback;

	irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DMA_TO_DEVICE);

	XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DMA_TO_DEVICE);


	if ((irq_status & XAXIDMA_IRQ_ERROR_MASK))
	{
			error = 1;
			XAxiDma_Reset(axidma_inst);
			timeout = RESET_TIMEOUT_COUNTER;
			while (timeout)
			{
				if (XAxiDma_ResetIsDone(axidma_inst))
				break;
				timeout -= 1;
			}
		return;
	}

	//Tx 完成
	if ((irq_status & XAXIDMA_IRQ_IOC_MASK))
	tx_done = 1;
}

//DMA RX 中断处理函数
static void rx_intr_handler(void *callback)
{
	 u32 irq_status;
	 int timeout;
	 XAxiDma *axidma_inst = (XAxiDma *) callback;

	 irq_status = XAxiDma_IntrGetIrq(axidma_inst, XAXIDMA_DEVICE_TO_DMA);
	 XAxiDma_IntrAckIrq(axidma_inst, irq_status, XAXIDMA_DEVICE_TO_DMA);

	 //Rx 出错
	 if ((irq_status & XAXIDMA_IRQ_ERROR_MASK))
	 {
		 error = 1;
		 XAxiDma_Reset(axidma_inst);
		 timeout = RESET_TIMEOUT_COUNTER;
		 while (timeout)
		 {
			 if (XAxiDma_ResetIsDone(axidma_inst))
			 break;
			 timeout -= 1;
		 }
		 return;
	 }

	 //Rx 完成
	 if ((irq_status & XAXIDMA_IRQ_IOC_MASK))
	 rx_done = 1;
}

static int setup_intr_system(XScuGic * int_ins_ptr, XAxiDma * axidma_ptr,
u16 tx_intr_id, u16 rx_intr_id)
{
	int status;
	XScuGic_Config *intc_config;

	//初始化中断控制器驱动
	intc_config = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == intc_config) {
	return XST_FAILURE;
	}
	status = XScuGic_CfgInitialize(int_ins_ptr, intc_config,
	intc_config->CpuBaseAddress);
	if (status != XST_SUCCESS) {
	return XST_FAILURE;
	}

	//设置优先级和触发类型
	XScuGic_SetPriorityTriggerType(int_ins_ptr, tx_intr_id, 0xA0, 0x3);
	XScuGic_SetPriorityTriggerType(int_ins_ptr, rx_intr_id, 0xA0, 0x3);

	//为中断设置中断处理函数
	status = XScuGic_Connect(int_ins_ptr, tx_intr_id,
	(Xil_InterruptHandler) tx_intr_handler, axidma_ptr);
	if (status != XST_SUCCESS) {
	return status;
	}

	status = XScuGic_Connect(int_ins_ptr, rx_intr_id,
	(Xil_InterruptHandler) rx_intr_handler, axidma_ptr);
	if (status != XST_SUCCESS) {
	return status;
	}

	XScuGic_Enable(int_ins_ptr, tx_intr_id);
	XScuGic_Enable(int_ins_ptr, rx_intr_id);

	//启用来自硬件的中断
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler) XScuGic_InterruptHandler,
	(void *) int_ins_ptr);
	Xil_ExceptionEnable();

	//使能 DMA 中断
	XAxiDma_IntrEnable(&axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE);
	XAxiDma_IntrEnable(&axidma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA);

	return XST_SUCCESS;
}

连接开发板,并打开终端;AMBA协议AXI-Stream(板级验证)_第19张图片下载硬件和软件程序,观察终端打印情况;AMBA协议AXI-Stream(板级验证)_第20张图片

打印数据为0-31,结果正确;


三、开源地址

工程开源:https://gitee.com/gewenjie_host/axis_test

你可能感兴趣的:(AMBA协议,基于Vivado的硬件设计,fpga开发)