APP(1171)
1,下载并安装VVD2013.3。
2,下载并解压1171设计文件。
3,找到目录:C:\Users\admin\AppData\Roaming\Xilinx\Vivado
4,如果目录中有类似project_1这种文件夹,备份好后删除掉。
5,把解压好的1171中 - kintexSubsystemFiles子目录复制过来。
6,开始菜单,运行TCL命令行;运行vivado -sourcee:/kintexsubsystemfiles/kintexgenerationscript.tcl
7,等待VVD启动,并生成SubSystem设计;也可以使用默认配置,直接生成BIT文件。
APP中包含的演示内容:
1,从Script生成VVD SubSystem 框图
2,PCIe Endpoint 配置
3,DMA通过PCIe的传输
4,动态地址映射
5,DMA(SG)操作。
Overview
主要用到AXI_CDMA, AXI_PCI Express,AXI Internonnect等IP。用BRAM临时存储DMA传输时用到的address translation vectors。
AXI_Interconnect Address Map
AXI Port | Instance | Base Address | High Address | Size |
AXI_DDR3_MEN | MIG | 0x0000 0000 | 0x7FFF FFFF | 2GB |
AXI_PCIe_DM | axi_pcie_1 AXI:BAR1 | 0x8000 0000 | 0x807F FFFF | 8MB |
AXI_PCIe_SG | axi_pcie_1 AXI:BAR0 | 0x8080 0000 | 0x80FF FFFF | 8MB |
Translation_BRAM | translation_bram | 0x8100 8000 | 0x8100 0FFF | 32KB |
AXI_PCIe_CTL | axi_pcie_1 | 0x8100 8000 | 0x8100 BFFF | 16KB |
AXI_CDMA_LITE | axi_cdma_1 | 0x8100 C000 | 0x8100 FFFF | 16KB |
PCIe to AXIBar Config Address
从host接收PCIe downstream
PCIe BAR0一共64KB,对应上面表中后3项:BRAM,AXI_PCIe_CTL,AXI_CDMA_LITE。
PCIe BAR | Interface | PCIe BAR Offset From Base Address | AXI Address | Size |
0 | Translation_BRAM | 0x0000 0000 | 0x8100 0FFF | 32KB |
0 | AXI_PCIe_CTL | 0x0000 8000 | 0x8100 BFFF | 16KB |
0 | AXI_CDMA_LITE | 0x0000 C000 | 0x8100 FFFF | 16KB |
<BAR0 Base Address> + < Offset of specified Interface > + < Register Offset in Interface>
例:假设BAR0在PC端映射的地址为:0x0000 0000_DEF0 0000
BRAM 0x0D10对应:0x0000 0000_DEF0 0D10
AXI_PCIe_CTL 0x20C 对应:0x0000 0000_DEF0 820C
AXI_CMDA_LITE 0x0004对应:0x0000 0000_DEF0 C004
PCIe AXI Master端不需要读写AXI_PCIe_SG, AXI_PCIe_DM, AXI_DDR3_MEM,因为DMA会读写到AXI Slave。
根据实际应用,还可以添加最多2个PCie BAR。
AXI to PCIe Bar Config Address
产生PCIe upstream到host
AXI BAR有2个:
AXI BAR0 - 8MB, [SG]DMA (AXI_PCIe_SG port),通过这port, DMA读取、处理PC端的descriptors。
AXI BAR1 - 8MB, Data Mover (AXI_PCIe_DM port),通过这个port,DMA读写PCIe数据。
CDMA IP的最大传输数据量为8M。
AXI BAR可以做64bit动态地址翻译,默认对应关系为:
AXI BAR | AXI Address | Host PCIe Address |
BAR0 | 0x8080 0000 | 0x0000 0000_A000 0000 |
BAR1 | 0x8000 0000 | 0x0000 0000_C000 0000 |
这个对应关系可以在AXI_PCIe_CTL (0x8100 8000)中的相应寄存器中更改:
Offset | Bits | Register Name | Description | Default Value |
0x208 | 31:0 | AXI BAR 2 PCIe BAR 0_U | AXI BAR0 Upper Address for AXI_PCIe_SG. Host Address [63:32] | 0x0000 0000 |
0x20C | 31:0 | AXI BAR 2 PCIe BAR 0_L | AXI BAR0 Lower Address for AXI_PCIe_SG. Host Address [31:0] | 0xA000 0000 |
0x210 | 31:0 | AXI BAR 2 PCIe BAR 1_U | AXI BAR1 Upper Address for AXi_PCIe_DM. Host Address [63:32] | 0x0000 0000 |
0x214 | 31:0 | AXI BAR 2 PCIe BAR 1_L | AXI BAR1 Lower Address for AXi_PCIe_DM. Host Address [31:0] | 0xC000 0000 |
根据实际应用,可以再添加最多4个AXI BAR。
Scatter Gather DMA
[SG]DMA是一种自动化的DMA,它使用transfer descriptors,其中包含预先定义好的一系列指令;由PCIe host通过驱动和软件把一系列指令写入内存驻留数据结构。这些指令被组织成descriptor chain,其中每一个descriptor都描述一个单独的数据传输并包含一个指向下一个descripitor的指针。整个chain中的最后一个descriptor一般指向第一个descriptor。
Scatter Gather Transfer Decriptor Difition
descriptor 由8个32bit组成,共32Byte;必须64Byte对齐。相对于系统内存中Transfer Descriptor的起始地址,Descriptor的offset只能是0x00,0x40,0x80,0xC0。
Address Offset | Register Name | Bit | Field Name | Description |
0x00 | Next Descriptor Ptr | 31:6 | Next Descriptor Ptr | 指向下一个Descriptor首字节的指针。 必须是64Byte对齐的:0x00、0x40、0x80、0xC0。 该指针是从AXI_PCIe_SG 开始,经AXI PCIe映射到host地址空间的的Offset。 |
5:0 | Reserved | 000000 确保指针是64Byte对齐的。 | ||
0x04 | Reserved | |||
0x08 | Source Address | 31:0 | SA | DMA传输,读取数据的起始地址。 |
0x0C | Reserved | |||
0x10 | Destination Address | 31:0 | DA | DMA传输,写入数据的起始地址。 由于DMA被配置成64bit数据位宽,DA地址的最后3位需要与SA的最后3位相同。 |
0x14 | Reserved | |||
0x18 | Transfer Cotrol | 31:23 | Reserced | |
22:0 | Bytes To Transfer (BTT) | 需要做DMA传输的字节数:1-0x007F FFFF。 设置为0会引起DMA内部错误。 | ||
0x0C | Transfer Status | 31 | Transfer Complete | 0:Descriptor没有执行完,Host不能更改寄存器。 1:Descriptor已经执行完,Host可以更改寄存器。 |
30 | DMA Decode Error | 0:No Errors 1:AXI Decode Error - Data Mover发现没有被映射到Slave Device。 | ||
29 | DMA Slave Error | 0:No Errors 1:CDMA Data Mover在read/write时发现Slave Device有错误。 | ||
28 | DMA Internal Error | 0:No Errors 1:CDMA Data Mover内部错误或者BTT被设为0。 | ||
27:0 | Reserved |
Host驱动应该确保Transfer Status设置为0000;并且在该次Descriptor完成之前,不更改Transfer Status中的值;当AXI CDMA引擎完成操作以后,会主动更新Transfer Status中的值,供Host驱动查询。
Host驱动需要Relocate上面设置,并清空Transfer Status,为进行下一次DMA做准备。
在本例SubSystem中,使用了2类Descriptor:
Address Translation Description Descriptor 和 Target Data Transfer Descriptor
Descriptor 使用的 Address 必须是AXI Interconnector 映射的地址,而不是Host中的地址空间!
Address Translation Description Descriptor 通过写AXI_PCIe_CTL 来Update AXI to PCIe Translation Vector。其中包括:
1. Source Address:对应于BRAM中 (0x8100 0000 - 0x8100 7FFF)
2. Destination Address:对应AXI_PCIe_CTL (AXI: BAR1)寄存器(0x8100 8210 和 0x8100 8214)
3. Control Value:一个8Byte的数据传输 (0x0000 0008)
工作时,DMA引擎把8ByteTranslation Vector从Translation BRAM 复制到 Translation Registors (可通过AXI_PCIe_CTL访问)。
在Descriptor被执行前,必须update Translation Vector 和 Block RAM;错误的设置可能导致获取非法内存地址。
Target Data Transfer Descriptor用于PCIe和目标设备(本例中DDR3)之间的数据传输。
1. SA和DA地址可以是:AXI_PCIe_DM(0x8000 0000)或者DDR3(0x0000 0000)
2. DMA Controller寄存器可以是: 1 - 0x007F FFFF
工作时,Descriptor在PCIe和DDR3之间进行数据传输。
在Descriptor被执行前,必须update PCIe Translation Vector。可以直接Update,也可以通过Address Translation Descriptor。
Scatter Gather DMA Operation
以下过程使用了一个descriptor chain,来实现(SG)DMA操作流程。
1. 设置DMA模式为SG;Enable中断。
写AXI_CDMA_LITE寄存器(AXI 0x8100 C000 或者 PCIe:BAR0 offset 0x0000 C000)
2. 在Host内存中创建Descriptor Chain。
需要包括:Address Translation Descriptor 和 Target Data Transfer Descriptor
3. Update AXI_PCIe_SG port 的 PCIe Translation Vector。
写AXI:BARO translation 寄存器,
位于AXI 0x8100 8208 - 0x8100 820C (AXI_PCIe_CTL port ) 或者PCIe:BAR0 offset 0x0000 8208 - 0x0000 820C。
写入这些寄存器的值,应该与之前在Host内存中建立Descriptor Chain 的 8MB Memory Base Address 一致。
4. 向 Translation BRAM 写入 Translation Vector。
BRAM 地址:AXI 0x8100 0000 - 0x8100 7FFF 或者 PCIe:BAR0 offset 0x0000 0000 - 0x0000 7FFF。
写入BRAM的值,应该与Host内存中(需要DMA引擎进行传输之数据)的8MB Memory 一致。
5. 向 DMA_CURDESC_PNTR 寄存器写入 pointer
DMA_CURDESC_PNTR地址:AXI 0x8100 C0008 或者 PCIe:BAR0 offset 0x0000 0008。
6. 向 DMA_TAILDESC_PNTR 寄存器写入 pointer
DMA_TAILDESC_PNTR 地址:AXI 0c8100 C010 或者 PCIe:BAR0 offset 0x0000 C010。
写入Tail Desc Pointer以后,DMA 启动,开始处理Descriptors。
7. DMA SG 工作中,直至 DMA_TAILDESC_PNTR 或者 是之前已经完成的descriptor。
下面是操作实例:把64KB数据从PCIe写入DDR,再从DDR读回PCIe
1. 设置DMA模式为SG;Enable中断。
32bit Write 0x0A000100 到 PCIe:BAR0 offset 00000 000C。
2. Description Chain
PCIe Address Translation for AXI_PCIe_SG:0x0000 0001 0000 0000
PCIe Address Translation for ACI_PCIe_DM:Set Dynamically by Descriptors 1 and 3
Descriptor1 | Descriptor2 | Descriptor3 | Descriptor4 |
Address: 0x0000 0001 0000 0000 | Address:: 0x0000 0001 0000 0040 | Address: 0x0000 0001 0000 0080 | Address: 0x0000 0001 0000 00C0 |
NEXTDESC_PNTR: 0x0000 0001 0000 0040 | NEXTDESC_PNTR: 0x0000 0001 0000 0080 | NEXTDESC_PNTR: 0x0000 0001 0000 00C0 | NEXTDESC_PNTR: 0x0000 0001 0000 0000 |
SA:0x8100 0000 (Translation BRAM) | SA:0x8000 0000 (AXI_PCIe_DM) | SA:0x8100 0008 (Translation BRAM) | SA:0x8100 0000 (DDR) |
DA:0x8100 8210 (AXI_PCIe_CTL) | DA:0x0010 0000 (DDR) | DA:0x8100 8210 (AXI_PCIe_CTL) | DA:0x8011 0000 (AXI_PCIe_DM) |
Control: 0x0000 0008 (64bit transfer) | Control: 0x0001 0008 (64bit transfer) | Control: 0x0000 0008 (64bit transfer) | Control: 0x0001 0008 (64bit transfer) |
Status: 0x0000 0000 (Not Proceed) | Status: 0x0000 0000 (Not Proceed) | Status: 0x0000 0000 (Not Proceed) | Status: 0x0000 0000 (Not Proceed) |
Translation Descriptor | Target Data Transfer Descriptor | Translation Descriptor | Target Data Transfer Descriptor |
3. Update AXI_PCIe_SG port 的 PCIe Translation Vector。
64bit Write 0x0000 0001 0000 0000 到 AXI_PCIe_SG @ PCIe:Bar0 offset 0x0000 8208 。
4. 向 Translation BRAM 写入 Translation Vector。
a. 64bit Write 0x0000 CCC0 C000 0000 到 PCIe:BAR0 offset 0x0000 0000;在descriptor1 和 descriptor2 之间update。
b. 64bit Write 0x0000 DDD0 D000 0000 到 PCIe:BAR0 offset 0x0000 0008;在descriptor3 和 descriptor4 之间update。
5. 向 DMA_CURDESC_PNTR 寄存器写入 pointer
32bit Write 0x8080 0000 到 DMA_CURDESC_PNTR @ PCIe:BAR0 offset 0x0000 0000 0000 C008。
pointer = AXI_PCIe_SG Base Address + [Host] Descriptor Offset From 0x0000 0001 0000 0000 (step2 中的地址)。
6. 向 DMA_TAILDESC_PNTR 寄存器写入 pointer
32bit Write 0x8080 00C0 到 DMA_TAILDESC_PNTR @ PCIe:BAR0 offset 0x0000 0000 0000 C010。
pointer = AXI_PCIe_SG Base Address + [Host] Descriptor Offset From 0x0000 0001 0000 0000 (step2 中的地址)。
这时,DMA启动
7. DMA 继续工作,直到 DMA_TAILDESC_PNTR @ 0x0000 0001 0000 00C0 执行完。
注:
在descriptor 1、2 操作过程中,不能更改descriptor 3、4
当descriptor 1、2 完成操作,而descriptor 3、4 还在执行过程中,可以reallocate descriptor 1、2 从而实现 Continous DMA