tag 标签: BMD

相关博文
  • 热度 5
    2019-8-15 11:16
    3307 次阅读|
    0 个评论
    32位存储器写任务
    完成剩下的DS端口模型任务函数学习,本文来看看存储32bit写,首先复习下32-bit地址存储器写TLP的头部格式,如下图所示: 图1:32位地址存储器写TLP头部格式 接下来我们来看DS端口模型里是如何使用这个函数的,在启动DMA操作之前都需要对DMA进行复位,这时候需要Host使用存储写操作往设备控制状态寄存器使能复位,具体实现代码如下(下述代码先写1启动复位,再写0,释放复位): DATA_STORE = 8'h01; //reset DATA_STORE = 8'h00; DATA_STORE = 8'h08; //data width path DATA_STORE = 8'h14; //fpga family TSK_TX_MEMORY_WRITE_32(DEFAULT_TAG,DEFAULT_TC, 10'd1,BAR_INIT_P_BAR +8'h00, 4'h0, 4'hF, 1'b0); TSK_TX_CLK_EAT(10); DEFAULT_TAG = DEFAULT_TAG + 1; DATA_STORE = 8'h00; //reset TSK_TX_MEMORY_WRITE_32(DEFAULT_TAG,DEFAULT_TC, 10'd1,BAR_INIT_P_BAR +8'h00, 4'h0, 4'hF, 1'b0); TSK_TX_CLK_EAT(10); DEFAULT_TAG = DEFAULT_TAG + 1; 至于BMD各个设计描述寄存器请查阅xapp1052文档,这里给出各个寄存器地址的截图: 图2:BMD设计描述寄存器地址 ( 注 :很重要,对于初学者来说,理解PCIe应用里各种地址有点困难。图2中寄存器地址是FPGA逻辑为DMA操作定义的寄存器,DMA引擎依据这些寄存器来采取对应的操作,这些寄存器可以通过存储器读写来进行访问。而配置寄存器则是与PCIe核相关,这些寄存器的相对地址和这里的寄存器地址甚至名称都可能一样,但是完全不是一个概念,配置寄存器只能通过Type0/1配置寄存器读写程序访问,且一般是驱动程序发起,电脑上电时BIOS也会发起。) 个人理解,上述寄存器用户可以随意定义,前提是要知会驱动程序以及软件设计人员,上中下层级协调一致即可。当然,对应FPGA设计者来说如果是基于BMD的设计,没有必要从头再来另搞一套,除非用户自己设计自己的DMA控制器。 下面来分析TSK_TX_MEMORY_WRITE_32这个函数,下图对函数输入参数进行了简单说明 对应前面调用该函数时,可以看到,写数据长度是1,即一个DW数据。 LastDW BE和First DW BE这两个字段的使用规则如下。 如果传送的数据长度在一个对界的双字(DW)之内,则Last DW BE字段为0b0000,而First DW BE的对应位置1;如果数据长度超过1DW,Last DW BE字段一定不能为0b0000。PCIe总线使用LastDW BE字段为0b0000表示所传送的数据在一个对界的DW之内。 如果传送的数据长度超过1DW,则First DW BE字段至少有一个位使能。不能出现First DW BE为0b0000的情况。 如果传送的数据长度大于等于3DW,则在First DW BE和Last DW BE字段中不能出现不连续的置1位。 如果传送的数据长度在1DW之内时,在First DW BE字段中允许有不连续的置1位。此时PCIe总线允许在TLP中传送1个DW的第1,3字节或者第0,2字节。 如果传送的数据长度为2DW之内时,则First DW BE字段和Last DW BE字段允许有不连续的置1位 根据以上规则,在发起BDM的DMA操作的时候,多次用该函数,而每次仅对一个寄存器进行写,故只有1个DW数据,所以 Last DW BE字段为0b0000,而First DW BE的对应位置1。此外,函数的地址参数是BAR的基地址+对应寄存器地址(即偏移地址,图2中各个寄存器地址)。
  • 热度 1
    2019-8-6 11:21
    2049 次阅读|
    0 个评论
    BMD64与BMD128比较
    结合排查之前pio_writeReadBack_test0测试出现的问题,需要参考前人写的相关博客,大部分都是基于BMD64,而我的示例是基于BMD128。 pio_writeReadBack_test0测试HOST发起一个MEM32写,然后再启动MEM32读回,所以先要探究MEM32写,分析 BMD RX 引擎(用于接收、解析TLP ) 。下图是https://blog.csdn.net/ningjinghai11/article/details/80924209博文中给出的BMD64模式下的MEM32写时序仿真图,可以看到存储器写请求TLP有2个,所以相应的bmd_64_rx_state分别有MEM_WR32_QW1和MEM_WR32_WT两个状态对应。 而我在仿真BMD128模式时,由于数据位宽为128bit,所以存储器写只有一个128bit的TLP就足够,而bmd_rx_state只一个MEM_WR32_WT就结束并进入RST状态,具体时序图如下: ( 注 :BMD_MEM_RD32_FMT_TYPE 和BMD_MEM_WR32_FMT_TYPE 两种标头对应的TLP是以PIO的模式传输,所以只会传输一个DW数据,再加上3DW标头;所以在BMD64模式下,一共两帧数据,而在上一个状态已经传输了一帧,本状态传输最后一帧数据,所以需要判断trn_reof_n 帧结束信号,同样需要主、从设备都准备好,即trn_rsrc_rdy_n 和trn_rdst_rdy_n 同时有效才能传输。而在BMD128模式下,只需一帧数据就足够了。这可以从上面两个时序图中可以清晰看出来。) 下面比较下BMD64和BMD128的RX引擎中对几个状态机的定义。 先来看看BMD64: //接收引擎关键状态机的8个状态 `define BMD_64_RX_RST 8'b00000001//接收引擎复位状态 `define BMD_64_RX_MEM_RD32_QW1 8'b00000010//存储器读状态 `define BMD_64_RX_MEM_RD32_WT 8'b00000100//等待存储器读结束 `define BMD_64_RX_MEM_WR32_QW1 8'b00001000//存储器写状态 `define BMD_64_RX_MEM_WR32_WT 8'b00010000//等待存储器写结束 `define BMD_64_RX_CPL_QW1 8'b00100000//不带数据的完成 `define BMD_64_RX_CPLD_QW1 8'b01000000//带数据完成 `define BMD_64_RX_CPLD_QWN 8'b10000000//带数据完成 //接收引擎4种标头 `define BMD_MEM_RD32_FMT_TYPE 7'b00_00000//存储器读请求:TLP头大小为3个双字,不带数据 `define BMD_MEM_WR32_FMT_TYPE 7'b10_00000//存储器写请求:TLP头大小为3个双字,带数据 `define BMD_CPL_FMT_TYPE 7'b00_01010//完成报文:TLP头大小为3个双字,不带数据;包括存储器、配置和I/O写完成 `define BMD_CPLD_FMT_TYPE 7'b10_01010//带数据完成报文:TLP头大小为3个双字;包括存储器读、配置读、I/O读和原子读操作完成 先来看看BMD128: //定义了8种关键状态机状态 `define BMD_128_RX_RST 8'b00000001 `define BMD_128_RX_MEM_RD32_STRAD 8'b00000010 `define BMD_128_RX_MEM_RD32_WT 8'b00000100 `define BMD_128_RX_MEM_WR32_STRAD 8'b00001000 `define BMD_128_RX_MEM_WR32_WT 8'b00010000 `define BMD_128_RX_CPL_STRAD 8'b00100000 `define BMD_128_RX_CPLD_STRAD 8'b01000000 `define BMD_128_RX_CPLD_QWN 8'b10000000 //定义了4种标头 `define BMD_MEM_RD32_FMT_TYPE 7'b00_00000 `define BMD_MEM_WR32_FMT_TYPE 7'b10_00000 `define BMD_CPL_FMT_TYPE 7'b00_01010 `define BMD_CPLD_FMT_TYPE 7'b10_01010