本文是用于总结PCIE ip例程的学习成果。主要是从ip的设置,ip核的例程代码构成及其来源两方面介绍pcie的使用情况。
《pg054-7series-pcie》
《PCI_Express_Base_Specification_Revision_3.0》
编译环境:vivado 2017.4
选用FPGA:xc7k325t-2ffg900i
本例程主要是使用Basic模式,下面是IP设置情况。
这一页主要是BAR的设置,即办卡内存的大小设置,数量设置,与使用位数设置;
这里选择64bit,则程序中选择使用的为4DW头,若没勾选则使用的是3DW头;
这一页主要是PCIE device的buff能力的设置与设备类型的总结;基本上可以不做改变;
这一页主要是中断的选择,常用的是下面的MSI中断;
这里例程的代码结构是PIO形式的,所谓PIO就是Programmed Input/Output,更通俗的解释就是从机模式,无论是读写都是需要CPU发送信号过来,FPGA这边根据接收到的命令进行读或者写。
此外本例程是每次只发送一个数据长度的数据,即一个包只发送32bit的数据。
这里用3DW头,64bit数据位宽作为讲解。4DW头、128bit数据位宽的类容基本类似,类推即可。
由上图可以知道PCIE的例程是由两部分组成,一个是support模块,一个是app部分。主要结构如下图所示:
Support模块主要是由PCIE的ip与时钟两部分组成,这一部分是不用修改的,直接沿用即可,所以这里不做过多介绍。
APP模块主要是由3部分组成:
在实际运用过程中PIO_RX模块是很可能改变的一个模块,我们并不是要把接收到的数据存储在mem中,也可能将其发送到其他地方,比如说通过DAC发给其他设备,因此这里作为一个重点讲解。
RX里的代码主要是分两部分编写,首先识别是哪一种包,然后根据包的类型接收数据。
其代码流程如下图所示:
其包头类型识别状态机说明如下图所示:
接收包的数据格式如下图所示:
需要注意的是这个“endpoint integrated block byte order”中的包格式只是32位的格式,即这个头是3DW的头。若是64位的格式(4DW)则途中的data[31:0]换成address[63:32],数据放到下一个时钟去(这也是PIO_RX_MEM_WR64_DW3状态的来源)。
其包头类型的划分依据如下所示:
PIO_TX模块也是实际使用中很可能改变的模块,因为在实际使用中不一定只是上传内存中的数据,还可能是上传其他地方过来的数据,比如上传ADC采集到的数据。
TX部分代码得到了整合,无论是回传带数据的格式包还是不带数据的包格式都相同,因为可以用用有效位区分开。
其代码流程如下图所示:
其回传数据的包头依据如下图所示:
回传数据的帧头部分代码如下图所示:
其回传的数据包部分如下所示:
下面我们来说说代码中的信号来源:
代码中的req_tc,req_td,req_ep,req_attr,req_len,req_rid,req_tag都比较清楚,它们是来自RX模块从CPU那边接收过来的数据。
rd_data:是我们要回传的数据。
completer_id:是来至于cfg_completer_id = { cfg_bus_number, cfg_device_number, cfg_function_number };即ip的cfg_status输出的状态;
byte_count:是根据length与byte enables计算的。其计算的依据是:
其计算的代码为:
lower_addr:是来至于接收到的请求地址的5位+(1st DW BE)计算出来的值。
其计算依据为:
其代码组成为:
需要注意的是:
2017.4版本vivado基于K7的FPGA 产生的IP其数据(s_axis_tx_tdata,m_axis_rx_tdata)中的高32位低32位与《PCI_Express_Base_Specification _Revision_3.0》中的包格式相反;