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安装。过程中可能会提醒驱动没有正确的数字签名,是否安装,点击是。

扫描二维码关注公众号,回复: 13238212 查看本文章

二,调用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 包)

 

 

猜你喜欢

转载自blog.csdn.net/wangjie36/article/details/121369426
今日推荐