13.3 PCI接口芯片PCI9054与FPGA的接口设计
13.3.1 PCI9054的特性
PCI接口芯片犹如一个硬核一样,完成了PCI局部总线端的总线交互,避免了用户直接对PCI局部总线进行复杂的操作。同时它为可编程逻辑器件提供了完备的本地总线接口,使用户可以较为方便地实现总线交互的功能,节省了开发的周期。
PCI9054是由美国PLX公司生产的先进的PCI桥接芯片。它采用了先进的PLX数据流水线结构技术,支持突发传输速率132MB/s。PCI9054具有如下一些特性。
· 兼容PCI 协议v2.2。
· 具有电源管理功能。
· 本地总线具有两个独立的DMA通道。
· 具有6个可编程FIFO用于无等待突发传送。
· 支持3.3V、5V芯片和接口电平标准。
· 本地时钟支持最高50MHz。
如图13.7所示为PCI9054的内部结构图。
图13.7 PCI9054内部结构图
13.3.2 PCI9054工作模式
PCI9054的本地总线时钟可与PCI总线时钟异步,本地总线有3种工作模式:M模式、C模式和J模式,可通过模式选择控制引脚MODE[1:0]进行控制,如表13.1所示。
表13.1 PCI9054工作模式
模 式 |
说 明 |
M |
32位地址/32位数据,非复用方式,用于直接连接MPC850或MPC860 |
C |
32位地址/32位数据,非复用方式 |
J |
32位地址/32位数据,复用方式 |
本系统采用的是C模式(MODE[1:0]= 00)。事实上,C模式能够满足绝大多数的应用需求,而且C模式的本地总线操作时序最简单,逻辑控制相对容易,其开发难度相对较低,因此,如无特殊需求,建议采用C模式。
要实现PCI9054 C模式与FPGA的接口设计,首先要明确PCI信号采集设备对于主机来说是主控设备(MASTER)还是目标设备(TARGET),还要明确是memory操作还是I/O操作。主控设备可以控制总线驱动地址、数据及控制信号;目标设备不能启动总线操作,只能通过主控设备来发起并驱动相应的信号。
在本系统设计中,PCI本地总线端使用的是FPGA而不是上位机,因此PCI9054对于PCI局部总线来讲是目标设备,由主机上其他设备作为主控设备进行PCI总线的操作。对于PCI本地总线来讲是PCI9054又是主控设备,通过PCI9054提供的本地接口启动本地端地址、数据及控制总线的操作。
首先作为PCI局部总线的目标设备,PCI局部总线通过控制C/BE[3:0]#来发起不同的操作。如表13.2所示为作为目标设备的PCI9054局部总线命令编码表。
表13.2 PCI目标设备命令编码表
命 令 类 型 |
C/BE[3:0]码型 |
I/O读 |
0010 |
I/O写 |
0011 |
存储器读 |
0110 |
存储器写 |
0111 |
配置读 |
1010 |
配置写 |
1011 |
存储器重复读 |
1100 |
PCI双地址周期 |
1101 |
存储器按行读 |
1110 |
存储器写无效 |
1111 |
在实际的操作中,用户通过应用程序对PCI设备进行操作时,PCI9054完成了将命令类型从PCI局部总线向本地总线的传递,并且这个过程对于用户来说是不可见的。用户只需要在本地总线端,即FPGA上实现对应命令类型的逻辑设计即可。因此,在FPGA内部需要对所有的命令操作进行相应的设计。
在本系统的PCI操作中,包含了I/O读、写,存储器读、写,配置读、写等操作,其中的存储器读、写操作使用的是Scatter/Gather DMA传输方式。在FPGA中通过判断PCI9054传递的地址映射空间类型和大小来区分主机需要进行的操作类型。
首先来认识一下PCI设备的空间配置情况。
13.3.3 PCI设备空间配置
通常PCI设备一般有配置空间、存储器空间和I/O空间3类资源。配置空间是必须的,根据设计需要,后两种资源可以只包含其中之一。
定义配置空间的目的在于为PCI设备提供一套适当的配置措施,使之满足现行的和可预见的系统配置机构。配置空间是一个容量为256字节并具有特定记录结构或模型的地址空间。在实际的系统配置中,PCI9054的配置空间通过烧写在EEPROM中的内容进行配置。
PCI9054有Space 0和Space 1两个地址空间,
两个地址空间都可以配置成存储器空间和I/O空间。存储器空间和I/O空间的配置既有相同之处,也有很大的区别。其相同点为两者都以字节为单位进行空间配置。不同之处有以下几点。
· 存储器空间支持0~4GB的空间映射,I/O空间只支持0~256字节的空间映射。
· 存储器空间支持8/16/32位总线位宽操作,I/O空间只支持32位总线位宽操作。
· 存储器空间支持单一周期和突发模式读写操作,I/O空间只支持单一周期读写操作。
· 编写驱动时,存储器空间用程序指针进行访问,I/O空间则用专用的函数进行访问。
用户应根据实际的操作需求选择合适的空间配置方式和参数,以便获得正确、高效的总线传输性能。例如进行数据流的传输时,最好使用存储器空间,采用DMA读写方式;进行参数配置或寄存器值读取时,使用I/O空间,采用I/O读写方式。
13.3.4 PCI9054与FPGA接口设计
如上所述,FPGA需要根据PCI9054传递的地址映射空间类型和大小来区分主机需要进行的操作类型。因此主机必须与FPGA达成一个一致的操作类型与地址映射空间协议,保证各个操作之间不会产生地址空间的重叠。
下面介绍一下进行I/O操作及DMA操作时,PCI9054与FPGA之间的接口设计。
1.I/O操作
如图13.8所示为PCI9054进行目标设备I/O读写时的结构图。其中,左图为读结构图,右图为写结构图。每个图中的左半部分为PCI9054与PCI局部总线的交互,右半部分为PCI9054与FPGA之间的交互。右半部分包含的控制线、地址线及数据线就是进行I/O操作时需要在FPGA内进行的接口设计。
图13.8 PCI9054目标设备I/O读写结构图
首先,PCI局部总线端的主机或其他设备作为主设备发起对PCI9054的I/O操作,此时PCI9054的局部总线端是目标设备。同时PCI9054的本地总线端又作为主设备向FPGA发起I/O操作,FPGA作为目标设备接受总线控制。
如图13.9所示为PCI9054目标设备Local总线存取过程图。可以看到,存取过程主要是进行地址的映射过程。首先进行Local端和PCI端的寄存器配置,再通过PCI9054内部的两个目标设备FIFO进行存取,主机根据寄存器的值即可得到映射位置上的数据。
图13.9 PCI9054目标设备Local总线存取过程
如图13.10所示为PCI9054目标设备Local总线I/O典型波形图。它描述了I/O操作时FPGA内的时序,也是用户需要进行设计的时序。
该波形图表述了下面几个交互过程。
· 主设备(主机或其他设备)发起Local总线占用请求LHOLD信号,FPGA应答产生LHOLDA信号允许该请求。
· 主设备获得允许后,发起操作起始信号ADS#,并提供Local总线读写方向信号LW/R#以及地址信号LA[31:2]。
· FPGA获得起始信号后,发出总线准备好信号READY#,并执行相应的操作。
· 主设备完成操作后,发起操作结束信号BLAST#,FPGA捕获后,改变READY#的状态。
· 主设备捕获READY#状态改变后,释放Local总线占用信号LHOLD。
· FPGA应答总线释放,结束操作。
图13.10 PCI9054目标设备Local总线I/O典型波形图
下面是这个交互过程中对应的Verilog代码,其中分配的I/O空间大小为64字节,通过对LA[4]译码实现操作类型的区分。
always @(posedge LCLK)
LHOLDA <= LHOLD; //总线请求及应答
always @(posedge LCLK or negedge RESET_)begin
if(!RESET_) //PCI9054复位
READY1_ <= 1'b1;
else if(!ADS_ & LWR_ & BLAST_ & LA[31:4]==28'h0000_001)
READY1_ <= 1'b0; //起始状态,通过地址线判断操作类型
else if(ADS_ & LWR_ & BLAST_ & !READY1_)begin
//TODO //中间状态,可执行相应的操作
READY1_ <= 1'b0;
end
else if(ADS_ & LWR_ & !BLAST_ & !READY1_)begin
//TODO //结束状态,可执行相应的操作
READY1_ <= 1'b1;
end
else
READY1_ <= 1'b1; //无操作状态
end
2.DMA
如图13.11所示为PCI9054进行目标设备DMA读写时的结构图。其中,左图为PCI-to-Local结构图,右图为写结构图。每个图中左右两部分完成的交互功能同I/O操作一样。
不同的是,进行DMA操作时,不管是与PCI局部总线还是PCI本地总线交互,PCI9054始终是主设备。主机或FPGA只需发出DMA开始信号后,即可由PCI9054完成DMA的所有操作。可见,DMA操作可以大幅度减轻主机端CPU的负担。
PCI9054支持Block(块)DMA和Scatter/Gather DMA两种传输模式,前者使用连续的内存块进行地址映射,后者可以通过自动添加的指针链,使用不连续的内存块实现大块内存的地址映射,可提高系统内存的使用效率。
如图13.12所示为Scatter/Gather DMA模式存取过程图。可以看到,DMA存取过程同样也是进行地址的映射过程。在这种模式下增加的是描述指针寄存器,通过它实现零散内存的连续化。
图13.11 PCI9054目标设备DMA读写结构图
图13.12 Scatter/Gather DMA模式存取过程
如图13.13所示为PCI9054目标设备Local总线DMA典型波形图。它描述了DMA操作时FPGA内的时序,也是用户需要进行设计的时序。
图13.13 PCI9054目标设备Local总线DMA典型波形图
该波形图表述了下面几个交互过程。
· 主设备(主机或其他设备)发起Local总线占用请求LHOLD信号,FPGA应答产生LHOLDA信号允许该请求。
· 主设备获得允许后,发起操作起始信号ADS#,并提供Local总线读写方向信号LW/R#以及地址信号LA[31:2]。
· FPGA获得起始信号后,发出总线准备好信号READY#,并执行相应的操作;此时LA地址会根据LBE字节使能的设置每读写一次(周期)递增一次,如图中LA地址所示。
· 主设备完成操作后,发起操作结束信号BLAST#,FPGA捕获后,改变READY#状态。
· 主设备捕获READY#状态改变后,释放Local总线占用信号LHOLD。
· FPGA应答总线释放,结束操作。
下面是这个交互过程中对应的Verilog代码,其中分配的DMA空间大小为1MB,通过对LA[20]译码实现操作类型的区分。
always @(posedge LCLK)
LHOLDA <= LHOLD; //总线请求及应答
always @(posedge LCLK or negedge RESET_)begin
if(!RESET_) //PCI9054复位
READY2_ <= 1'b1;
else if(!ADS_ & LWR_ & BLAST_ & LA[31:20]== 12'h001)
READY2_ <= 1'b0; //起始状态,通过地址线判断操作类型
else if(ADS_ & LWR_ & BLAST_ & !READY2_)begin
//TODO //中间状态,可执行相应操作
READY2_ <= 1'b0;
end
else if(ADS_ & LWR_ & !BLAST_ & !READY2_)begin
//TODO //结束状态,可执行相应操作
READY2_ <= 1'b1;
end
else
READY2_ <= 1'b1; //无操作状态
End