vivado PCIE接口使用

vivado中,有三种方式可以实现PCIE功能:

PCIE IP核所做的工作主要有两点,一个是将TLP包转换成AXI协议;另一个是支持DMA操作。


 

一,调用7 Series Integrated Block for PCI Express IP核,这是最基础的PCIE IP核,比较复杂。

1,在IP Catalog找到XDMA,使用简化设置

2,通道数选择4,AXI数据位宽选择128位,DMA Interface选择AXI Memory Mapped,PCIE参考时钟100MHz,AXI时钟125MHz。

 3,设置PCIE的BAR空间,勾中PCIe to AXI-Lite Master Interface,选择Size,然后一路默认生成好IP核。IP核生成完成后,右键选择Open IP Example Design,进入Example Design项目。在xdc中约束PCIE的参考时钟和复位引脚的管脚和IO电平后,点击Generate Bitstream,等待bit文件生成。解压xdma_driver_win_installers_x64_2018_2.zip,选择的Win版本XDMADriverInstaller.msi安装。过程中可能会提醒驱动没有正确的数字签名,是否安装,点击是。

二,调用AXI Memory Mapped To PCI Express IP核,对7 Series Integrated Block for PCI Express进一步封装,使用Example Design直接运行,但需要添加DMA IP核实现DMA数据传输。

1,PCIE basics

2,PCIE link config

 3,PCIE ID

 4,PCIE BARS

5,PCIE misc

 6,AXI BARS

 7,AXI system

 

`timescale 1 ps / 1 ps

module zc706_pcie_wrapper
   (DDR_addr,
    DDR_ba,
    DDR_cas_n,
    DDR_ck_n,
    DDR_ck_p,
    DDR_cke,
    DDR_cs_n,
    DDR_dm,
    DDR_dq,
    DDR_dqs_n,
    DDR_dqs_p,
    DDR_odt,
    DDR_ras_n,
    DDR_reset_n,
    DDR_we_n,
    FIXED_IO_ddr_vrn,
    FIXED_IO_ddr_vrp,
    FIXED_IO_mio,
    FIXED_IO_ps_clk,
    FIXED_IO_ps_porb,
    FIXED_IO_ps_srstb,
    mmcm_lock,
    pcie_7x_mgt_rxn,
    pcie_7x_mgt_rxp,
    pcie_7x_mgt_txn,
    pcie_7x_mgt_txp,
    perst_n,
    ref_clk_clk_n,
    ref_clk_clk_p);
  inout [14:0]DDR_addr;
  inout [2:0]DDR_ba;
  inout DDR_cas_n;
  inout DDR_ck_n;
  inout DDR_ck_p;
  inout DDR_cke;
  inout DDR_cs_n;
  inout [3:0]DDR_dm;
  inout [31:0]DDR_dq;
  inout [3:0]DDR_dqs_n;
  inout [3:0]DDR_dqs_p;
  inout DDR_odt;
  inout DDR_ras_n;
  inout DDR_reset_n;
  inout DDR_we_n;
  inout FIXED_IO_ddr_vrn;
  inout FIXED_IO_ddr_vrp;
  inout [53:0]FIXED_IO_mio;
  inout FIXED_IO_ps_clk;
  inout FIXED_IO_ps_porb;
  inout FIXED_IO_ps_srstb;
  output mmcm_lock;
  input [3:0]pcie_7x_mgt_rxn;
  input [3:0]pcie_7x_mgt_rxp;
  output [3:0]pcie_7x_mgt_txn;
  output [3:0]pcie_7x_mgt_txp;
  input perst_n;
  input [0:0]ref_clk_clk_n;
  input [0:0]ref_clk_clk_p;

  wire [14:0]DDR_addr;
  wire [2:0]DDR_ba;
  wire DDR_cas_n;
  wire DDR_ck_n;
  wire DDR_ck_p;
  wire DDR_cke;
  wire DDR_cs_n;
  wire [3:0]DDR_dm;
  wire [31:0]DDR_dq;
  wire [3:0]DDR_dqs_n;
  wire [3:0]DDR_dqs_p;
  wire DDR_odt;
  wire DDR_ras_n;
  wire DDR_reset_n;
  wire DDR_we_n;
  wire FIXED_IO_ddr_vrn;
  wire FIXED_IO_ddr_vrp;
  wire [53:0]FIXED_IO_mio;
  wire FIXED_IO_ps_clk;
  wire FIXED_IO_ps_porb;
  wire FIXED_IO_ps_srstb;
  wire mmcm_lock;
  wire [3:0]pcie_7x_mgt_rxn;
  wire [3:0]pcie_7x_mgt_rxp;
  wire [3:0]pcie_7x_mgt_txn;
  wire [3:0]pcie_7x_mgt_txp;
  wire perst_n;
  wire [0:0]ref_clk_clk_n;
  wire [0:0]ref_clk_clk_p;

  zc706_pcie zc706_pcie_i
       (.DDR_addr(DDR_addr),
        .DDR_ba(DDR_ba),
        .DDR_cas_n(DDR_cas_n),
        .DDR_ck_n(DDR_ck_n),
        .DDR_ck_p(DDR_ck_p),
        .DDR_cke(DDR_cke),
        .DDR_cs_n(DDR_cs_n),
        .DDR_dm(DDR_dm),
        .DDR_dq(DDR_dq),
        .DDR_dqs_n(DDR_dqs_n),
        .DDR_dqs_p(DDR_dqs_p),
        .DDR_odt(DDR_odt),
        .DDR_ras_n(DDR_ras_n),
        .DDR_reset_n(DDR_reset_n),
        .DDR_we_n(DDR_we_n),
        .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
        .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
        .FIXED_IO_mio(FIXED_IO_mio),
        .FIXED_IO_ps_clk(FIXED_IO_ps_clk),
        .FIXED_IO_ps_porb(FIXED_IO_ps_porb),
        .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
        .mmcm_lock(mmcm_lock),
        .pcie_7x_mgt_rxn(pcie_7x_mgt_rxn),
        .pcie_7x_mgt_rxp(pcie_7x_mgt_rxp),
        .pcie_7x_mgt_txn(pcie_7x_mgt_txn),
        .pcie_7x_mgt_txp(pcie_7x_mgt_txp),
        .perst_n(perst_n),
        .ref_clk_clk_n(ref_clk_clk_n),
        .ref_clk_clk_p(ref_clk_clk_p));
endmodule

管脚约束:

#GPIO LEDs
set_property PACKAGE_PIN A17 [get_ports mmcm_lock]
set_property IOSTANDARD LVCMOS18 [get_ports mmcm_lock]

# PCI Express reset (perst)
set_property PACKAGE_PIN AK23 [get_ports perst_n]
set_property IOSTANDARD LVCMOS18 [get_ports perst_n]

# PCI Express reference clock 100MHz
set_property PACKAGE_PIN N8 [get_ports {ref_clk_clk_p[0]}]
set_property PACKAGE_PIN N7 [get_ports {ref_clk_clk_n[0]}]
create_clock -period 10.000 -name ref_clk_clk_p -waveform {0.000 5.000} [get_ports ref_clk_clk_p]

# MGT locations
set_property PACKAGE_PIN P5 [get_ports {pcie_7x_mgt_rxn[0]}]
set_property PACKAGE_PIN P6 [get_ports {pcie_7x_mgt_rxp[0]}]
set_property PACKAGE_PIN N3 [get_ports {pcie_7x_mgt_txn[0]}]
set_property PACKAGE_PIN N4 [get_ports {pcie_7x_mgt_txp[0]}]

set_property PACKAGE_PIN T5 [get_ports {pcie_7x_mgt_rxn[1]}]
set_property PACKAGE_PIN T6 [get_ports {pcie_7x_mgt_rxp[1]}]
set_property PACKAGE_PIN P1 [get_ports {pcie_7x_mgt_txn[1]}]
set_property PACKAGE_PIN P2 [get_ports {pcie_7x_mgt_txp[1]}]

set_property PACKAGE_PIN U3 [get_ports {pcie_7x_mgt_rxn[2]}]
set_property PACKAGE_PIN U4 [get_ports {pcie_7x_mgt_rxp[2]}]
set_property PACKAGE_PIN R3 [get_ports {pcie_7x_mgt_txn[2]}]
set_property PACKAGE_PIN R4 [get_ports {pcie_7x_mgt_txp[2]}]

set_property PACKAGE_PIN V5 [get_ports {pcie_7x_mgt_rxn[3]}]
set_property PACKAGE_PIN V6 [get_ports {pcie_7x_mgt_rxp[3]}]
set_property PACKAGE_PIN T1 [get_ports {pcie_7x_mgt_txn[3]}]
set_property PACKAGE_PIN T2 [get_ports {pcie_7x_mgt_txp[3]}]

SDK测试:

#include "xparameters.h"	/* Defines for XPAR constants */
#include "xaxipcie.h"		/* XAxiPcie level 1 interface */
#include "stdio.h"
#include "xil_printf.h"
/************************** Constant Definitions ****************************/
#define AXIPCIE_DEVICE_ID 	XPAR_AXIPCIE_0_DEVICE_ID
#define PCIE_CFG_CMD_IO_EN	0x00000001 /* I/O access enable */
#define PCIE_CFG_CMD_MEM_EN	0x00000002 /* Memory access enable */
#define PCIE_CFG_CMD_BUSM_EN	0x00000004 /* Bus master enable */
#define PCIE_CFG_CMD_PARITY	0x00000040 /* parity errors response */
#define PCIE_CFG_CMD_SERR_EN	0x00000100 /* SERR report enable */
//PCIe Configuration registers offsets
#define PCIE_CFG_ID_REG			0x0000 /* Vendor ID/Device ID offset */
#define PCIE_CFG_CMD_STATUS_REG		0x0001 /*
						* Command/Status Register
						* Offset
						*/
#define PCIE_CFG_PRI_SEC_BUS_REG	0x0006 /*
						* Primary/Sec.Bus Register
						* Offset
						*/
#define PCIE_CFG_CAH_LAT_HD_REG		0x0003 /*
 						* Cache Line/Latency Timer/
 						* Header Type/
 						* BIST Register Offset
 						*/
#define PCIE_CFG_BAR_0_REG		0x0004 /* PCIe Base Addr 0 */

#define PCIE_CFG_FUN_NOT_IMP_MASK	0xFFFF
#define PCIE_CFG_HEADER_TYPE_MASK	0x00EF0000
#define PCIE_CFG_MUL_FUN_DEV_MASK	0x00800000
#define PCIE_CFG_MAX_NUM_OF_BUS		256
#define PCIE_CFG_MAX_NUM_OF_DEV		1
#define PCIE_CFG_MAX_NUM_OF_FUN		8
#define PCIE_CFG_PRIM_SEC_BUS		0x00070100
#define PCIE_CFG_HEADER_O_TYPE		0x0000
#define PCIE_CFG_BAR_0_ADDR		0x00001111
// Macros for reading link speed and width from the core
#define	 XAxiPcie_IsGen3(InstancePtr) 	\
	(XAxiPcie_ReadReg((InstancePtr)->Config.BaseAddress, 	\
	XAXIPCIE_PHYSC_OFFSET) & 0x00001000) ? 1 : 0

#define	 XAxiPcie_IsGen2(InstancePtr) 	\
	(XAxiPcie_ReadReg((InstancePtr)->Config.BaseAddress, 	\
	XAXIPCIE_PHYSC_OFFSET) & 0x00000001) ? 1 : 0

#define	 XAxiPcie_LinkWidth(InstancePtr) 	\
	((XAxiPcie_ReadReg((InstancePtr)->Config.BaseAddress, 	\
	XAXIPCIE_PHYSC_OFFSET) & XAXIPCIE_PHYSC_LINK_WIDTH_MASK) >> 1)
/**************************** Type Definitions ******************************/
/***************** Macros (Inline Functions) Definitions ********************/
/************************** Function Prototypes *****************************/
int PcieInitRootComplex(XAxiPcie *AxiPciePtr, u16 DeviceId);
void PCIeEnumerateFabric(XAxiPcie *AxiPciePtr);
static void __attribute__ ((noinline)) UtilDelay(unsigned int Seconds);
/************************** Variable Definitions ****************************/
/* Allocate PCIe Root Complex IP Instance */
XAxiPcie AxiPcieInstance;
/****************************************************************************/
/**
* This function is the entry point for PCIe Root Complex Enumeration Example
* @return 	- XST_SUCCESS if successful
*		- XST_FAILURE if unsuccessful.
*
* @note 	None.
*
*****************************************************************************/
int main(void)
{
	int Status;
	// Allow time for link-up
	UtilDelay(1);
	xil_printf("=============================\r\n");
	xil_printf("PCIe Gen2 Enumeration Example\r\n");
	xil_printf("=============================\r\n");
	/* Initialize Root Complex */
	Status = PcieInitRootComplex(&AxiPcieInstance, AXIPCIE_DEVICE_ID);
	if (Status != XST_SUCCESS)
   {
		xil_printf("Failed to initialize AXI PCIe Root port\r\n");
		return XST_FAILURE;
	}

	/* Scan PCIe Fabric */
	PCIeEnumerateFabric(&AxiPcieInstance);
	return XST_SUCCESS;
}
/****************************************************************************/
/**
* This function returns the negotiated PCIe link speed once link-up is achieved
* @param	AxiPciePtr is a pointer to an instance of XAxiPcie data
*		structure represents a root complex IP.
* @return	- 1 if Gen1
*           - 2 if Gen2
*           - 3 if Gen3
*		- 0 if unsuccessful.
*
* @note 	None.
******************************************************************************/

int get_pcie_link_speed(XAxiPcie *AxiPciePtr)
{
	int is_gen2;
	int is_gen3;
	is_gen2 = XAxiPcie_IsGen2(AxiPciePtr);
	is_gen3 = XAxiPcie_IsGen3(AxiPciePtr);
	if((is_gen2 == 0) && (is_gen3 == 1))
		return(3);
	if((is_gen2 == 1) && (is_gen3 == 0))
		return(2);
	if((is_gen2 == 0) && (is_gen3 == 0))
		return(1);
	return(0);
}

/****************************************************************************/
/**
* This function returns the negotiated PCIe link width once link-up is achieved
* @param	AxiPciePtr is a pointer to an instance of XAxiPcie data
*		structure represents a root complex IP.
* @return	- link width (1,2,4 or 8)
* @note 	None.
******************************************************************************/
int get_pcie_link_width(XAxiPcie *AxiPciePtr)
{
	int i;
	int link_width;
	int result;
	link_width = XAxiPcie_LinkWidth(AxiPciePtr);
	result = 1;
	for(i = 0; i < link_width; i++)
		result = result * 2;
	return(result);
}


/****************************************************************************/
/**
* This function initializes a AXI PCIe IP built as a root complex
* @param	AxiPciePtr is a pointer to an instance of XAxiPcie data
*		structure represents a root complex IP.
* @param 	DeviceId is AXI PCIe IP unique ID
* @return	- XST_SUCCESS if successful.
*		- XST_FAILURE if unsuccessful.
* @note 	None.
******************************************************************************/
int PcieInitRootComplex(XAxiPcie *AxiPciePtr, u16 DeviceId)
{
	int Status;
	u32 HeaderData;
	u32 InterruptMask;
	u8  BusNumber;
  	u8  DeviceNumber;
	u8  FunNumber;
	u8  PortNumber;

	XAxiPcie_Config *ConfigPtr;
	ConfigPtr = XAxiPcie_LookupConfig(DeviceId);
	Status = XAxiPcie_CfgInitialize(AxiPciePtr, ConfigPtr,ConfigPtr->BaseAddress);
	if (Status != XST_SUCCESS) 
    {
		xil_printf("Failed to initialize PCIe Root Complex""IP Instance\r\n");
		return XST_FAILURE;
	}

	if(!AxiPciePtr->Config.IncludeRootComplex) 
   {
		xil_printf("Failed to initialize...AXI PCIE is configured"" as endpoint\r\n");
		return XST_FAILURE;
	}

	/* Make sure link is up. */
	Status = XAxiPcie_IsLinkUp(AxiPciePtr);
	if (Status != TRUE ) 
   {
		xil_printf("Link:\r\n  - LINK NOT UP!\r\n");
		return XST_FAILURE;
	}
	xil_printf("Link:\r\n  - LINK UP, Gen%d x%d lanes\r\n",
		get_pcie_link_speed(AxiPciePtr),get_pcie_link_width(AxiPciePtr));
	xil_printf("Interrupts:\r\n");
	/* See what interrupts are currently enabled */
	XAxiPcie_GetEnabledInterrupts(AxiPciePtr, &InterruptMask);
	xil_printf("  - currently enabled: %8X\r\n", InterruptMask);

	/* Make sure all interrupts disabled. */
	XAxiPcie_DisableInterrupts(AxiPciePtr, XAXIPCIE_IM_ENABLE_ALL_MASK);

	/* See what interrupts are currently pending */
	XAxiPcie_GetPendingInterrupts(AxiPciePtr, &InterruptMask);
	xil_printf("  - currently pending: %8X\r\n", InterruptMask);

	/* Just if there is any pending interrupt then clear it.*/
	XAxiPcie_ClearPendingInterrupts(AxiPciePtr,
						XAXIPCIE_ID_CLEAR_ALL_MASK);

	/ * Read enabled interrupts and pending interrupts
	 * to verify the previous two operations and also
	 * to test those two API functions
	 */

	xil_printf("Cleared pending interrupts:\r\n");

	XAxiPcie_GetEnabledInterrupts(AxiPciePtr, &InterruptMask);
	xil_printf("  - currently enabled: %8X\r\n", InterruptMask);

	XAxiPcie_GetPendingInterrupts(AxiPciePtr, &InterruptMask);
	xil_printf("  - currently pending: %8X\r\n", InterruptMask);

	/*
	 * Read back requester ID.
	 */
	XAxiPcie_GetRequesterId(AxiPciePtr, &BusNumber,
				&DeviceNumber, &FunNumber, &PortNumber);

	xil_printf("Requester ID:\r\n");
	xil_printf("  - Bus Number: %02X\r\n"
			"  - Device Number: %02X\r\n"
	 			"  - Function Number: %02X\r\n"
	 				"  - Port Number: %02X\r\n",
	 		BusNumber, DeviceNumber, FunNumber, PortNumber);


	/* Set up the PCIe header of this Root Complex */
	XAxiPcie_ReadLocalConfigSpace(AxiPciePtr,
					PCIE_CFG_CMD_STATUS_REG, &HeaderData);

	HeaderData |= (PCIE_CFG_CMD_BUSM_EN | PCIE_CFG_CMD_MEM_EN |
				PCIE_CFG_CMD_IO_EN | PCIE_CFG_CMD_PARITY |
							PCIE_CFG_CMD_SERR_EN);

	XAxiPcie_WriteLocalConfigSpace(AxiPciePtr,
					PCIE_CFG_CMD_STATUS_REG, HeaderData);

	/*
	 * Read back local config reg.
	 * to verify the write.
	 */

	xil_printf("PCIe Local Config Space:\r\n");

	XAxiPcie_ReadLocalConfigSpace(AxiPciePtr,
					PCIE_CFG_CMD_STATUS_REG, &HeaderData);

	xil_printf("  - %8X at register CommandStatus\r\n", HeaderData);

	/*
	 * Set up Bus number
	 */

	HeaderData = PCIE_CFG_PRIM_SEC_BUS;

	XAxiPcie_WriteLocalConfigSpace(AxiPciePtr,
					PCIE_CFG_PRI_SEC_BUS_REG, HeaderData);

	/*
	 * Read back local config reg.
	 * to verify the write.
	 */
	XAxiPcie_ReadLocalConfigSpace(AxiPciePtr,
					PCIE_CFG_PRI_SEC_BUS_REG, &HeaderData);

	xil_printf("  - %8X at register Prim Sec. Bus\r\n", HeaderData);

	/* Now it is ready to function */

	return XST_SUCCESS;
}

/*****************************************************************************/
/**
* This function enumerates its PCIe system and figures out the nature of each
* component there like end points,bridges,...
*
* @param 	AxiPciePtr is a pointer to an instance of XAxiPcie
*		data structure represents a root complex IP.
*
* @return 	None.
*
* @note 	None.
*
******************************************************************************/
void PCIeEnumerateFabric(XAxiPcie *AxiPciePtr)
{

	u32 ConfigData;
	u32 PCIeHeaderType;
	u32 PCIeMultiFun;
	u32 PCIeBusNum;
	u32 PCIeDevNum;
	u32 PCIeFunNum;
	u16 PCIeVendorID;
	u32 RegVal;

	xil_printf("Enumeration of PCIe Fabric:\r\n");

	/* Scan PCIe Fabric */

	for (PCIeBusNum = 0; PCIeBusNum < PCIE_CFG_MAX_NUM_OF_BUS;
								PCIeBusNum++) {
		for (PCIeDevNum = 0; PCIeDevNum < PCIE_CFG_MAX_NUM_OF_DEV;
								PCIeDevNum++) {
			for (PCIeFunNum = 0;
				PCIeFunNum < PCIE_CFG_MAX_NUM_OF_FUN;
								PCIeFunNum++) {

				/* Vendor ID */
				XAxiPcie_ReadRemoteConfigSpace(
					AxiPciePtr,PCIeBusNum,
					PCIeDevNum, PCIeFunNum,
					PCIE_CFG_ID_REG, &ConfigData);

				PCIeVendorID = (u16) (ConfigData & 0xFFFF);

				if (PCIeVendorID ==
						PCIE_CFG_FUN_NOT_IMP_MASK) {
					if (PCIeFunNum == 0)
					/*
					 * We don't need to look
					 * any further on this device.
					 */
					break;
				}
				else {
					xil_printf("PCIeBus %02X:\r\n"
						"  - PCIeDev: %02X\r\n"
						"  - PCIeFunc: %02X\r\n",
						PCIeBusNum, PCIeDevNum,
								PCIeFunNum);

					xil_printf("  - Vendor ID: %04X \r\n",
								PCIeVendorID);

					/* Header Type */
					XAxiPcie_ReadRemoteConfigSpace(
						AxiPciePtr, PCIeBusNum,
						PCIeDevNum, PCIeFunNum,
						PCIE_CFG_CAH_LAT_HD_REG,
						&ConfigData);

					PCIeHeaderType = ConfigData &
						PCIE_CFG_HEADER_TYPE_MASK;

					PCIeMultiFun = ConfigData &
						PCIE_CFG_MUL_FUN_DEV_MASK;

					if (PCIeHeaderType ==
						PCIE_CFG_HEADER_O_TYPE) {
						/* This is an End Point */
						xil_printf("  - End Point\r\n");

						/*
						 * Initialize this end point
						 * and return.
						 */

						XAxiPcie_ReadRemoteConfigSpace(
							AxiPciePtr,
							PCIeBusNum, PCIeDevNum,
							PCIeFunNum,
						PCIE_CFG_CMD_STATUS_REG,
								&ConfigData);

						ConfigData |=
						(PCIE_CFG_CMD_BUSM_EN |
							PCIE_CFG_CMD_MEM_EN);

						XAxiPcie_WriteRemoteConfigSpace
							(AxiPciePtr,
							PCIeBusNum, PCIeDevNum,
							PCIeFunNum,
						PCIE_CFG_CMD_STATUS_REG,
								ConfigData);

						/*
						 * Write Address to
						 * PCIe BAR0
						 */
						ConfigData =
						(PCIE_CFG_BAR_0_ADDR |
							PCIeBusNum |
							PCIeDevNum |
							PCIeFunNum);

						XAxiPcie_WriteRemoteConfigSpace
						(AxiPciePtr,
						PCIeBusNum, PCIeDevNum,
						PCIeFunNum, PCIE_CFG_BAR_0_REG,
						ConfigData);

						xil_printf("  - End Point has been"
							" enabled\r\n");

					}
					else {
						/* This is a bridge */
						xil_printf("  - Bridge\r\n");
					}
				}

				if ((!PCIeFunNum) && (!PCIeMultiFun)) {
					/*
					 * If it is function 0 and it is not a
					 * multi function device, we don't need
					 * to look any further on this devie
					 */
					break;
				}
			}  /* Functions in one device */
		}  /* Devices on the same bus */
	}  /* Buses in the same system */

	xil_printf("End of Enumeration\r\n");

	/* Bridge enable */
	XAxiPcie_GetRootPortStatusCtrl(AxiPciePtr, &RegVal);
	RegVal |= XAXIPCIE_RPSC_BRIDGE_ENABLE_MASK;
	XAxiPcie_SetRootPortStatusCtrl(AxiPciePtr, RegVal);
	return;
}


static void __attribute__ ((noinline)) UtilDelay(unsigned int Seconds)
{
#if defined (__MICROBLAZE__) || defined(__PPC__)
	static int WarningFlag = 0;
	if (((mfmsr() & 0x20) == 0) && (!WarningFlag)) 
    {
		WarningFlag = 1;
	}

#define ITERS_PER_SEC   (XPAR_CPU_CORE_CLOCK_FREQ_HZ / 6)
    asm volatile ("\n"
			"1:               \n\t"
			"addik r7, r0, %0 \n\t"
			"2:               \n\t"
			"addik r7, r7, -1 \n\t"
			"bneid  r7, 2b    \n\t"
			"or  r0, r0, r0   \n\t"
			"bneid %1, 1b     \n\t"
			"addik %1, %1, -1 \n\t"
			:: "i"(ITERS_PER_SEC), "d" (Seconds));
#else
    sleep(Seconds);
#endif
}

三,调用DMA/Bridge Subsystem for PCI Express (PCIe) IP核,别名XDMA,对PCIE和DMA一起进行了封装,也可以直接使用Example Design直接运行。

四,发送和接收

1,TLP FPGA 发送端(FPGA 应答主机的 TLP 包)

 

2,TLP FPGA 接收端(FPGA 接收主机的 TLP 包)

 

 

 

 

 

Guess you like

Origin blog.csdn.net/wangjie36/article/details/121369426