电子说
仿真与实际应用场景的差别
通常我们都会用Modelsim、Questa等工具对工程进行仿真验证,在仿真的时候可能关注的点没有那么的多,检查到对端收到包没有问题,一般情况下就认为已经完成调试,可以上板给host、birdge或者switch下的其他PCIE设备进行发包,不过在实际应用的过程中,如果想用FPGA作为Endpoint主动发包去读写其他设备,还有一个功能需要打开:Bus Master Enable,下图1是PCIE协议对此功能的定义。
图1
这个功能决定了Endpoint能否向远端设备发起读写请求,只有使能了此功能,FPGA作为Endpoint时,才能够向远端设备成功发起读写访问。Bus Master Enable在PCIE的配置空间命令寄存器04h中,此功能可以通过setpci指令打开。
如何使用PCIE的RQ接口来产生读写请求
在介绍如何控制端口信号产生读写请求之前,需要先介绍下描述符(如下图2所示),描述符类似与包头的功能,描述符的大小是128bit,这个是固定的,其内包含了地址类型、地址、请求类型、数字数等字段,在传输时第一拍先传输的是描述符,传完描述符之后才会传后面的数据,使用128bit或者大于128Bit数据端口的用户对这一点可能没有疑问,但是使用64bit数据端口的用户会可能会有疑问,128bit的描述符,64bit的数据端口一拍传不完,如果使用的是64bit的端口,描述符会传两拍,在传输的前两拍都是描述符。
图2
描述符的前两个字段是address type,这个字段比较简单,其标志了地址是否经过了转换,如果用户要自己产生读写请求可以把此字段设置为0,address就是用户要访问的地址,在填写地址之前要确认好此地址是否可读写,避免读到读清寄存器。Dword Count表示的是描述符后跟的数据的Dword数,一般来讲数据的长度都是双字的整数倍,如果长度不是双字的整数倍,就需要使用firstbe,或者lastbe,这两个被放在了tuser字段,下面的篇幅会对其进行介绍。接下来是Request Type,Request Type字段的定义如下图3所示:
图3
根据所发送包的类型选择相应数字填充data字段即可,接下来说一下Requester ID和Completer ID这两个字段,如果用户使用的是基于地址的方式对包进行路由,这两个字段的数值不需要特别关注,重点字段已介绍完,描述符其他字段的含义可参考Xilinx的PG343(Versal ACAP Integrated Block for PCI Express v1.0 LogiCORE IP Product Guide)。
本篇参考的是Xilinx的PG343,接下来会对Versal的 PCIE IP进行介绍,以下提及的端口的data的bit数都是512bit,如果想了解其他bit位数据的接口如何使用,可以参考PG343,与512bit的数据端口区别不大。
产生读写请求所使用的接口是PCIE IP的Requester Request Interface,接口的定义如下图4所示:
图4
之前的篇幅中提到的描述符就在s_axis_rq_tdata中传输,前128bit是描述符,后面跟的是数据,类似与tlast、tkeep和tready等字段,本篇blog不再进行赘述,可以参照AMBA总线,或者上图的描述,下面重点介绍s_axis_rq_tuser字段,手册上称其为边带信号,部分字段的定义如下图5所示:
图5
首先介绍下first_be和last_be,first_be指的是数据的第一个双字中有几个byte是有效的,一个双字是4byte,所示只用4bit就可以识别出一个双字中有效的byte数,在IP界面,把straddle模式打开时,可以一拍传输两个TLP,在512bit数据接口,其first_be字段的长度为8bit,前4bit表示的是第一个TLP包中的第一个双字中有效的byte,后4个bit表示的是第二个TLP包中的第一个双字中有效的byte。is_sop的值表明了此拍的有或者没有以及有几个新的TLP,is_sop表明这一拍有没有TLP结束或者有几个TLP结束。
No straddle模式使用注意事项
在使用no straddle模式时,在发送1DW的memory write时,虽然上图中说的是在使用no straddle模式时,is_eop是可选的,但是在实际使用的时候,特别是有1DW的memory write或者有1DW为结尾的memory write,需要把is_eop的数值设置为1。下图6是memory write的发包格式,在生成包时可以参考如下图6格式:
图6
下下面的两张图是发包的仿真图,图7为End point的Requester request接口的仿真图,图8为root port的Completer Request接口的仿真图,整体的流程就是End point通过自己的Requester request接口把memory write TLP发送到root port的Completer Request接口。
先看Requester request接口所发送的包的rq_tuser字段,410000f中的f表示第一个TLP的firstbe全有效,10000表示此拍数据没有第二个TLP且这一拍数据只有1DW,last_be全为0,10000中的1即为图中的第四行2‘b01, //is SOP,表示这个一拍是一个TLP的开始,4为图中的2‘01 //is eop? 2’b00sop1 ptr两行,表示此拍数据只有一个TLP,且此TLP在此拍结束。
接下来对Requester request接口所发送的包的rq_tdata进行说明,rq_tdata的前两个bit表明了地址有没有经过转换,数据的地址为BE7 1CBD 975D 4000,rq_tdata中的801表示此数据位memory写,且Dword count 为1.
图7
接下来对RP的Completer Request接口接收到的数据进行简要分析,可以看到m_axis_cq_tdata与s_axis_rq_tdata的字段完全相同,m_axis_tuser中的firstbe为0F,lastbe为00,这一点与发送端的情况一致,End point此次发送的数据包被Root port成功接收。
图8
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !