PL2PS2PL v1.0 关于axi4_stream data fifo和dma ip核

v1.0

 v2.0

任务目标是实现PL到PS的音频信号读取,并在PS中进行滤波操作,滤波结束后输出到PL端。

Axi4_Stream Data Fifo

下面部分引用(28条消息) 关于AXI4-STREAM DATA FIFO的理解及带FIFO的ADDA测试_axi fifo_Laid-back guy的博客-CSDN博客

FIFO模块能够为AXI4-Stream数据流提供临时存储(缓冲区),多用于一下两种情况:

  1. 需要比寄存器更多的缓存单元.
  2. 存储和转发:主机上积累一定数量的字节后,再转发给从机(包模式)。

FIFO,first in,first out,即先入先出的数据缓存队列,其结构如下如所示

 如图所示,FIFO IP核的主要操作是对数据进行写入,读出。虽然AXI4-Stream数据流不涉及内存地址,且FIFO没有地址线,但FIFO的内部含地址操作,其读写过程如下图所示:

FIFO 配置

通用选项

  • 组件名称:生成的核心输出文件的基本名称。名称必须以字母开头,并且可以由以下字符组成:a到z,0到9和"_"。
  • FIFO深度:此选项指定要实例化的FIFO的深度。FIFO深度可以在16和32768之间变化(为2的幂,直到当前最大值2的n)。在某些设备上,较大的FIFO深度可能无法实现。

内存类型

  • Designate the FIFO memory primitive (resource type) to use. Allowable options:
    • Auto: Allow Vivado Synthesis to choose.
    • Distributed RAM: Distributed RAM FIFO (does not support ECC).
    • Block RAM: Block RAM FIFO.
    • UltraRAM: UltraRAM FIFO (does not support independent clocks).

独立时钟

  • 如果设置为Yes,则假定S_AXIS_ACLK和M_AXIS_ACLK时钟信号彼此异步,并且IP在异步模式下运行。

CDC(时钟域交叉)同步阶段

  • 当S_AXIS_ACLK和M_AXIS_ACLK彼此异步时,此参数指定用于交叉时钟域逻辑的同步阶段数量。增加此值会增加设计的平均故障间隔时间(MTBF),但会增加延迟和逻辑利用率。

启用数据包模式

  • 此选项启用FIFO的数据包模式选项。此选项要求启用TLAST信号。在数据包模式下,FIFO将修改为存储传输,直到TLAST信号被断言。当TLAST信号被断言或FIFO已满时,存储的传输将在AXI4-Stream主接口上呈现。
  • 上面太复杂了,就是启用之后

ACLKEN转换模式

  • 此下拉选项选择ACLKEN信号的转换模式。执行ACLKEN转换会增加额外的延迟和逻辑。选项包括:
    • None: 没有与IP关联的ACLKEN信号。
    • S AXIS Only: 与S_AXIS_ACLK时钟信号相关联的S_AXIS_ACLKEN信号,没有M_AXIS_ACLKEN信号。
    • M AXIS Only: 与M_AXIS_ACLK时钟信号相关联的M_AXIS_ACLKEN信号,没有S_AXIS_ACLKEN信号。
    • S AXIS & M AXIS: 两个时钟都有与之相关联的ACLKEN信号。

启用ECC

  • 启用ECC编码器和解码器。仅支持在块RAM和UltraRAM原语类型上启用ECC。

包括ECC错误注入

  • 信号属性:在使用Vivado IP Integrator时,Vivado IDE会自动计算这些参数的值。

TDATA宽度(字节)

  • 此参数指定所有AXI4-Stream接口上TDATA信号的宽度,以字节为单位。该参数是一个整数,可以从0到512变化。设置为0将省略TDATA信号。如果省略TDATA信号,则也会省略TKEEP和TSTRB信号。端口的宽度乘以8可得到以位为单位的宽度。

启用TSTRB

  • 如果设置为Yes,则该参数指定所有AXI4-Stream接口上是否存在可选的TSTRB信号。只有在TDATA宽度(字节)参数大于0时才能启用此选项。

启用TKEEP

  • 如果设置为Yes,则该参数指定所有AXI4-Stream接口上是否存在可选的TKEEP信号。只有在TDATA宽度(字节)参数大于0时才能启用此选项。

启用TLAST

  • 如果设置为Yes,则该参数指定所有AXI4-Stream接口上是否存在可选的TLAST信号。

TID宽度(位)

  • 如果大于0,则该参数指定所有AXI4-Stream接口上是否存在可选的TID信号。值为0时省略此信号。值为1和32将相应设置该信号的宽度。

TDEST宽度(位)

  • 如果大于0,则该参数指定所有AXI4-Stream接口上是否存在可选的TDEST信号。值为0时省略此信号。值为1和32将相应设置该信号的宽度。

TUSER宽度(位)

  • 如果大于0,则该参数指定所有AXI4-Stream接口上是否存在可选的TUSER信号。值为0时省略此信号。值为1和32将相应设置该信号的宽度。

Flags

启用写数据计数:写入数据(S_AXIS)计数输出端口,同步于写时钟。

启用几乎满:写入将满使能输出端口,同步于写时钟。Packet Mode模式下不允许使用,本实验从简不使用。

启用可编程满:使能可编程满,同步于写时钟。可以自己设置阈值来提醒当前FIFO的写入状态。

可编程满阈值:可编程满阈值。

启用读数据计数:读出数据(M_AXIS)计数输出端口,同步于读时钟。

启用几乎空:读出将空,同步于读时钟。Packet Mode模式下不允许使用,本实验从简不使用。

启用可编程空:使能可编程空,同步于读时钟。可以自己设置阈值来提醒当前FIFO的读取状态。

可编程空阈值:可编程空阈值。

AXI Direct Memory Acess

DMA(Direct Memory Access)是一种数据传输技术,其主要作用是在计算机系统中实现高效的数据传输,从而减轻CPU的负担,提高系统性能,以及实现高速的数据传输。

主要作用包括:

  1. 减轻CPU负担:在传统的I/O操作中,CPU需要直接参与数据传输的过程,即通过CPU的寄存器和内部总线将数据从I/O设备传输到内存,或者从内存传输到I/O设备。这会占用CPU的大量时间和计算资源。使用DMA,数据可以直接在I/O设备和内存之间传输,而无需CPU直接参与,从而减轻CPU的负担,使其可以更专注于执行其他重要的任务。

  2. 提高数据传输速率:DMA允许高速设备(如高速网络接口、存储设备等)与内存之间直接传输数据,而不需要通过CPU。这样可以实现更高的数据传输速率,从而加快数据处理和响应速度。

  3. 支持高性能数据流处理:对于需要高性能数据处理的应用,如音视频处理、图像处理等,使用DMA可以在不占用CPU计算资源的情况下,高效地进行数据传输和处理。

  4. 实现并行数据传输:DMA通常支持多通道数据传输,允许多个设备或外设同时访问内存,从而实现并行数据传输,提高整体系统性能。

DMA配置

启用异步时钟: 此设置允许独立操作MM2S接口 m_axi_mm2s_aclk、S2MM接口 m_axi_s2mm_aclk、AXI4-Lite控制接口 s_axi_lite_aclk 和Scatter Gather接口 m_axi_sg_aclk。当启用异步时钟时,s_axi_lite_aclk 的频率必须小于或等于 m_axi_sg_aclk 的频率。同样,m_axi_sg_aclk 的频率必须小于或等于 m_axi_mm2s_aclkm_axi_s2mm_aclk 中较慢的时钟。在同步模式下,所有时钟输入应连接到相同的时钟信号。此参数在Vivado IP Integrator中根据连接到 axi_dma 的时钟自动设置。

启用Scatter Gather Engine: 勾选此选项将启用Scatter Gather模式,并在AXI DMA中包含Scatter Gather Engine。取消勾选此选项将启用直接寄存器模式,并从AXI DMA中排除Scatter Gather Engine。禁用Scatter Gather Engine会将Scatter/Gather引擎的所有输出端口连接到零,并将所有输入端口保留为开放状态。

启用Micro DMA: 勾选此选项将生成高度优化的DMA,资源使用率较低。此设置适用于传输少量数据的应用程序。DMA将根据所选的配置进行编程。例如,每个事务或每个BD最大传输的字节数不能超过以下值:MMap Data_width * Burst_length/8。同样,此模式下不实现4K边界检查,限制寻址到突发边界。缓冲区长度寄存器的宽度由"Width of Buffer Length Register"参数指定。对于多通道模式,该值应设置为23。

地址宽度(32 - 64): 指定地址空间的宽度,可以是32到64之间的任意值。

启用多通道DMA: 勾选此选项将启用DMA的多通道功能,并允许选择MM2S和S2MM通道的通道数。此功能即将停用,更多信息请参阅AXI多通道直接内存访问文档(PG288)。

启用控制/状态流: 勾选此选项将启用AXI4控制和状态流。AXI4控制流允许用户应用程序元数据与MM2S通道关联,并将其传输到目标IP。AXI4状态流允许用户应用程序元数据与S2MM通道关联,并从目标IP接收。如果控制/状态流启用,则与MM2S Scatter/Gather帧启动描述符的用户应用程序字段0至4(TXSOF = 1)相关联的数据将通过m_axis_mm2s_cntrl流接口传输,同时在m_axis_mm2s流接口上传输相关联的数据包。同样,S2MM Scatter/Gather帧结束描述符的用户应用程序字段0至4将填充接收到的状态数据包。这些条件由更新的描述符的状态字中的接收帧结束(RXEOF = 1)指示。

启用读通道选项: 以下选项仅影响AXI DMA核的MM2S通道。

启用通道: 此选项启用或禁用MM2S通道。启用MM2S通道允许从内存到AXI4-Stream的读取传输。禁用MM2S通道将排除AXI DMA核的逻辑。MM2S通道的输出被连接到零,输入被AXI DMA忽略。

通道数: 此选项指定通道数,范围从1到16。

内存映射数据宽度: AXI MM2S内存映射读取数据总线的位宽。有效值为32、64、128、256、512和1,024。

流数据宽度: AXI MM2S AXI4-Stream数据总线的位宽。该值必须等于或小于内存映射数据宽度。有效值为8、16、32、64、128、512和1,024。

最大突发大小: 突发分区粒度设置。该设置指定了MM2S通道AXI4-Memory Map一侧的突发周期的最大大小。有效值为2、4、8、16、32、64、128和256。

允许非对齐传输: 勾选此选项将启用MM2S数据重新对齐引擎(DRE)。启用时,DRE允许在MM2S内存映射数据路径上对齐数据到字节(8位)级别。对于MM2S通道,数据从内存读取。如果启用DRE,则数据读取可以从任意缓冲区地址字节偏移开始,并且读取的数据对齐,使得从AXI4-Stream读取的第一个字节是第一个有效字节。

启用写通道选项: 以下选项仅影响AXI DMA核的S2MM通道。

启用通道: 此选项启用或禁用S2MM通道。启用S2MM通道允许从AXI4-Stream到内存的写入传输。禁用S2MM通道将排除AXI DMA核的逻辑。S2MM通道的输出被连接到零,输入被AXI DMA忽略。

通道数: 此选项启用您选择的通道数量,范围从1到16。

内存映射数据宽度: AXI S2MM内存映射写入数据总线的位宽。有效值为32、64、128、256、512和1,024。

流数据宽度: AXI S2MM AXI4-Stream数据总线的位宽。该值必须等于或小于内存映射数据宽度。有效值为8、16、32、64、128、512和1,024。

最大突发大小: 该设置指定了S2MM通道AXI4-Memory Map一侧的突发周期的最大大小。有效值为2、4、8、16、32、64、128和256。

允许非对齐传输: 勾选此选项将启用S2MM数据重新对齐引擎(DRE)。启用时,DRE允许在S2MM内存映射数据路径上对齐数据到字节(8位)级别。对于S2MM通道,数据写入内存。如果启用DRE,则数据写入可以从任意缓冲区地址字节偏移开始,并且写入的数据对齐,使得接收到的S2MM AXI4-Stream的第一个有效字节被写入指定的非对齐地址偏移处。

在状态流中使用RxLength: 如果启用了控制/状态流,则勾选此选项将允许AXI DMA使用由S2MM目标IP在状态数据包的App4字段中提供的接收长度字段。这样可以给AXI DMA预先确定的接收字节数,使其能够命令要传输的确切字节数。此选项提供对需要更高吞吐量的系统的更高带宽解决方案。在此配置下,S2MM目标IP可以提供状态数据包APP4中接收长度字段中指定的所有数据字节。

启用单AXI4数据接口: 此选项仅适用于在Vivado IP Integrator中使用。您可以使用此选项将两个AXI4接口(MM2S和S2MM)合并为单个接口。此选项不影响资源或性能。

坑:

1、

只有使用ila或system ila选择native时才可能会出现这种错误。

出现原因:是因为Ila中检测的某些信号,时钟频率可能高于ila的clk。
解决方法:
在.xdc中添加create_clock -period 16 -name clk -add [get_ports clk_0]
其中,clk_0是外部时钟,clk是Ila的时钟。
16ns是ila检测信号中最高时钟频率的周期数,
即Ila的时钟接连到检测信号中最高的时钟频率
 

2、

 

 问题出在我的fifo1的master clk是直接和外部接口相连的,后来改到连接在fifo0的slave输入时钟就好了。

Vitis

代码v1.0

main.c

#include "xaxidma.h"
#include "xparameters.h"
#include "xdebug.h"

#if defined(XPAR_UARTNS550_0_BASEADDR)
#include "xuartns550_l.h"       /* to use uartns550 */
#endif

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

/*
 * Device hardware build related constants.
 */

#define DMA_DEV_ID		XPAR_AXIDMA_0_DEVICE_ID

#ifdef XPAR_PS7_DDR_0_S_AXI_BASEADDR
#define DDR_BASE_ADDR		XPAR_PS7_DDR_0_S_AXI_BASEADDR
#elif defined (XPAR_MIG7SERIES_0_BASEADDR)
#define DDR_BASE_ADDR	XPAR_MIG7SERIES_0_BASEADDR
#elif defined (XPAR_MIG_0_BASEADDR)
#define DDR_BASE_ADDR	XPAR_MIG_0_BASEADDR
#elif defined (XPAR_PSU_DDR_0_S_AXI_BASEADDR)
#define DDR_BASE_ADDR	XPAR_PSU_DDR_0_S_AXI_BASEADDR
#endif

#ifndef DDR_BASE_ADDR
#warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, \
		 DEFAULT SET TO 0x01000000
#define MEM_BASE_ADDR		0x01000000
#else
#define MEM_BASE_ADDR		(DDR_BASE_ADDR + 0x1000000)
#endif

#define TX_BUFFER_BASE		(MEM_BASE_ADDR + 0x00100000)
#define RX_BUFFER_BASE		(MEM_BASE_ADDR + 0x00300000)
#define RX_BUFFER_HIGH		(MEM_BASE_ADDR + 0x004FFFFF)

#define MAX_PKT_LEN		1024

#define TEST_START_VALUE	0xC

#define NUMBER_OF_TRANSFERS	10

/**************************** Type Definitions *******************************/


/***************** Macros (Inline Functions) Definitions *********************/


/************************** Function Prototypes ******************************/

#if (!defined(DEBUG))
extern void xil_printf(const char *format, ...);
#endif

int XAxiDma_SimplePollExample(u16 DeviceId);
static int CheckData(void);

/************************** Variable Definitions *****************************/
/*
 * Device instance definitions
 */
XAxiDma AxiDma;


/*****************************************************************************/
/**
* The entry point for this example. It invokes the example function,
* and reports the execution status.
*
* @param	None.
*
* @return
*		- XST_SUCCESS if example finishes successfully
*		- XST_FAILURE if example fails.
*
* @note		None.
*
******************************************************************************/
int main()
{
	int Status;

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

	/* Run the poll example for simple transfer */
	Status = XAxiDma_SimplePollExample(DMA_DEV_ID);

	if (Status != XST_SUCCESS) {
		xil_printf("XAxiDma_SimplePoll Example Failed\r\n");
		return XST_FAILURE;
	}

	xil_printf("Successfully ran XAxiDma_SimplePoll Example\r\n");

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

	return XST_SUCCESS;

}

#if defined(XPAR_UARTNS550_0_BASEADDR)
/*****************************************************************************/
/*
*
* Uart16550 setup routine, need to set baudrate to 9600, and data bits to 8
*
* @param	None.
*
* @return	None
*
* @note		None.
*
******************************************************************************/
static void Uart550_Setup(void)
{

	/* Set the baudrate to be predictable
	 */
	XUartNs550_SetBaud(XPAR_UARTNS550_0_BASEADDR,
			XPAR_XUARTNS550_CLOCK_HZ, 9600);

	XUartNs550_SetLineControlReg(XPAR_UARTNS550_0_BASEADDR,
			XUN_LCR_8_DATA_BITS);

}
#endif

/*****************************************************************************/
/**
* The example to do the simple transfer through polling. The constant
* NUMBER_OF_TRANSFERS defines how many times a simple transfer is repeated.
*
* @param	DeviceId is the Device Id of the XAxiDma instance
*
* @return
*		- XST_SUCCESS if example finishes successfully
*		- XST_FAILURE if error occurs
*
* @note		None
*
*
******************************************************************************/
int XAxiDma_SimplePollExample(u16 DeviceId)
{
	XAxiDma_Config *CfgPtr;
	int Status;
	int Tries = NUMBER_OF_TRANSFERS;
	int Index;
	u8 *TxBufferPtr;
	u8 *RxBufferPtr;
	u8 Value;

	TxBufferPtr = (u8 *)TX_BUFFER_BASE ;
	RxBufferPtr = (u8 *)RX_BUFFER_BASE;

	/* Initialize the XAxiDma device.
	 */
	CfgPtr = XAxiDma_LookupConfig(DeviceId);
	if (!CfgPtr) {
		xil_printf("No config found for %d\r\n", DeviceId);
		return XST_FAILURE;
	}

	Status = XAxiDma_CfgInitialize(&AxiDma, CfgPtr);
	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;
	}

	/* Disable interrupts, we use polling mode
	 */
	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
						XAXIDMA_DEVICE_TO_DMA);
	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
						XAXIDMA_DMA_TO_DEVICE);

//	Value = TEST_START_VALUE;
//
//	for(Index = 0; Index < MAX_PKT_LEN; Index ++) {
//			TxBufferPtr[Index] = Value;
//
//			Value = (Value + 1) & 0xFF;
//	}
	/* Flush the buffers before the DMA transfer, in case the Data Cache
	 * is enabled
	 */
	Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);
	Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN);

	for(Index = 0; Index < Tries; Index ++) {


		Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr,
					MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}

		Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) TxBufferPtr,
					MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);

		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}

		while ((XAxiDma_Busy(&AxiDma,XAXIDMA_DEVICE_TO_DMA)) ||
			(XAxiDma_Busy(&AxiDma,XAXIDMA_DMA_TO_DEVICE))) {
				/* Wait */
		}

//		Status = CheckData();
//		if (Status != XST_SUCCESS) {
//			return XST_FAILURE;
//		}

	}

	/* Test finishes successfully
	 */
	return XST_SUCCESS;
}



/*****************************************************************************/
/*
*
* This function checks data buffer after the DMA transfer is finished.
*
* @param	None
*
* @return
*		- XST_SUCCESS if validation is successful.
*		- XST_FAILURE otherwise.
*
* @note		None.
*
******************************************************************************/
static int CheckData(void)
{
	u8 *RxPacket;
	int Index = 0;
	u8 Value;

	RxPacket = (u8 *) RX_BUFFER_BASE;
	Value = TEST_START_VALUE;

	/* Invalidate the DestBuffer before receiving the data, in case the
	 * Data Cache is enabled
	 */
	Xil_DCacheInvalidateRange((UINTPTR)RxPacket, MAX_PKT_LEN);

	for(Index = 0; Index < MAX_PKT_LEN; Index++) {
		if (RxPacket[Index] != Value) {
			xil_printf("Data error %d: %x/%x\r\n",
			Index, (unsigned int)RxPacket[Index],
				(unsigned int)Value);

			return XST_FAILURE;
		}
		Value = (Value + 1) & 0xFF;
	}

	return XST_SUCCESS;
}

坑:

DMA中断错误

发现在运行后uart串口只会输出entering main,说明运行错误,采用debug模式,打断点运行

 

 这部分Int_Id循环不变化一直为0

 这部分要是一直step over就会产生error,如果一步一步step into就没有error,但也不会有done信号,所以在while部分就会陷入死循环,应该是在运行过程中会产生中断,进入中断后被判断为error,但是single step debug就不会遇到中断,原理没弄懂,但现象应该就是这样。

我看了好像是因为

以上参数用于在中断控制器中对特定的 IRQ 源进行设置。这样可以调整中断的优先级和触发类型,以满足系统的需求。请注意,具体的设置过程需要参考硬件平台和中断控制器的相关文档。

 这部分要是一直step over就会产生error,如果一步一步step into就没有error,但也不会有done信号,所以在while部分就会陷入死循环,应该是在运行过程中会产生中断,进入中断后被判断为error,但是single step debug就不会遇到中断,原理没弄懂,但现象应该就是这样。

我看了好像是因为

static void RxIntrHandler(void *Callback)
{
	u32 IrqStatus;
	int TimeOut;
	XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

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

	/* Read pending interrupts */
	IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);

	/* Acknowledge pending interrupts */
	XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);

	/*
	 * If no interrupt is asserted, we do not do anything
	 */
	if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) {
		return;
	}

	/*
	 * If error interrupt is asserted, raise error flag, reset the
	 * hardware to recover from the error, and return with no further
	 * processing.
	 */
	if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) {

		Error = 1;

		xil_printf("\r\n--- !!!() --- \r\n");

		/* Reset could fail and hang
		 * NEED a way to handle this or do not call it??
		 */
		XAxiDma_Reset(AxiDmaInst);

		TimeOut = RESET_TIMEOUT_COUNTER;

		while (TimeOut) {
			if(XAxiDma_ResetIsDone(AxiDmaInst)) {
				break;
			}

			TimeOut -= 1;
		}

		return;
	}

	/*
	 * If completion interrupt is asserted, then set RxDone flag
	 */
	if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) {

		RxDone = 1;
	}
}

输出error还是done是根据判断中断类型来得到的,可是我输出的中断不是由dma产生的,而是根据自己写的ip核产生,所以无法通过dma自带的函数进行判断,大概是这样把?

解决方案(未验证):

将自己生成的中断信号和中断处理函数联系后,使用以下函数

(中断信号:在fifo满的时候输出单时钟周期的高电平,其余时刻输出低电平)

XScuGic_Connect(IntcInstancePtr, RxIntrId, //产生的中断信号对应地址ID
				(Xil_InterruptHandler)DMA_RxIntrHandler,
				AxiDmaPtr);

不调用XAxiDma_IntrGetIrq、XAxiDma_IntrAckIrq这两个函数来判断,因为产生的中断不是由dma产生的,所以调用上述函数会报错,运行不会进入下个阶段,而是死掉,应该修改中断处理函数。

由于上述的问题,所以直接大修了vivado bd和vitis的代码,bd换成v2.0,在下一篇中写吧。

其他:

通常在DMA接收数据之前,会使用Xil_DCacheInvalidateRange函数来使DMA接收到的数据缓存失效,以确保从系统内存中读取最新的接收数据。而在DMA发送数据之前,会使用Xil_DCacheFlushRange函数来确保要发送的数据已经写回到系统内存,从而避免发送旧数据。这样保证了数据传输的正确性和完整性。Xil_DCacheFlushRange当ddr不变,cache更新时,将cache的新数据写入ddr中,当cache不变,ddr更新时,将ddr中的新数据写入cache。

滤波

为什么这部分不能少 

分配地址如果有地址移动,就会可能出错

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AXI-stream FIFOAXI4-Stream Data FIFO 和 AXI Data FIFO 是三种常见的FIFO(First-In-First-Out)内存结构,用于在AXI(Advanced eXtensible Interface)总线上进行数据缓存和传输。它们的主要区别在于它们所支持的AXI接口版本和功能。 1. AXI-stream FIFO: AXI-stream FIFO 是最简单的FIFO结构,用于在AXI-stream接口中进行数据缓存和传输。它主要用于流式数据传输,如音频、视频等连续数据流。AXI-stream FIFO只有一个输入和一个输出接口,数据按照输入的顺序存储,并按照相同的顺序输出。它不支持数据帧的划分和标记。 2. AXI4-Stream Data FIFO: AXI4-Stream Data FIFO 是在AXI4-Stream接口规范下定义的FIFO结构。与AXI-stream FIFO相比,它具有更多的功能和扩展性。它支持数据帧的划分和标记,可以将连续的数据流划分为多个数据帧,并通过标记信号进行标识。AXI4-Stream Data FIFO还支持流控制信号,如有效性信号(TVALID)、空闲信号(TREADY)和结束信号(TLAST),用于控制数据的传输速率和状态。 3. AXI Data FIFO: AXI Data FIFO 是在AXI接口规范下定义的FIFO结构。它是更高级别的FIFO,支持AXI接口的全部特性和功能。除了数据缓存和传输外,它还支持读写地址突发传输、带宽控制、容错和错误检测等功能。AXI Data FIFO可以用于连接多个AXI总线设备,实现高速数据传输和存储。 总结起来,AXI-stream FIFO 是最简单的FIFO结构,适用于流式数据传输;AXI4-Stream Data FIFOAXI4-Stream接口规范下扩展了功能,支持数据帧划分和标记;AXI Data FIFO 是最高级别的FIFO结构,支持完整的AXI接口特性和功能。选择使用哪种FIFO结构,需要根据具体应用需求和所使用的接口规范来决定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值