尹凯
摘要:本文实现了一种基于SSP接口的FPGA被动配置方法,对FPGA的被动串行配置进行了详细讨论,给出了硬件电路设计和SSP接口的操作方法。
关键词:SSP;FPGA被动配置;Linux
1. 引言
FPGA在上电之后,需要从外部电路获取配置数据并载入到内部的配置SRAM中才能正常工作。本文主要讨论了一种基于外部处理器SSP接口发送配置数据的方法,既可以保证配置速度又简化了硬件连接。
2.FPGA配置方式
Altera公司的Cyclone系列FPGA支持三种配置方式:AS模式(主动串行模式)、PS模式(被动串行模式)和JTAG模式。这三种配置方式由模式选择管脚(MSEL1、MSEL0)的电平值决定,其主要区别是配置过程中FPGA所处的地位和加载配置数据的方式不同。本文使用其中的PS模式,实现外部處理器对FPGA的串行配置。
2.1PS配置过程
PS模式中主要用到的FPGA配置管脚包括:
lDCLK:配置时钟;
lDATA0:配置数据;
lnCONFIG:配置命令;
lnSTATUS:配置状态指示;
lCONF_DONE:配置完成指示。
在PS模式下FPGA处于从属地位,接收来自外部的配置命令、配置时钟和配置数据,并给出配置状态信号以及配置完成指示信号,时序波形如下图所示。
外部控制器(ARM、单片机等)控制整个配置过程。在配置期间,配置数据在DCLK管脚的时钟信号上升沿通过DATA0管脚锁存至FPGA中。FPGA要求每字节数据从LSB(最低有效位)开始发送,比如配置文件包含的字节顺序为0x02 0x1B,那么串行二进制流的发送顺序就是0100-0000 1101-1000。
2.2PS配置文件
Altera的开发环境QuartusII编译后自动生成的sof和pof格式的配置文件,不能用于PS模式,需要进行格式转化将sof文件转换为rbf文件。
3.SSP接口电路设计
在本设计中,外部处理器使用的是MARVELL公司的PXA270,通过配置其GPIO管脚的复用功能实现SSP(同步串行协议)通信接口,处理器与FPGA配置管脚的连接关系如下图所示。
3.1GPIO工作模式
对于具有复用功能的GPIO管脚,通过GPIO控制器的相应寄存器来配置其工作模式。根据我们所选用GPIO管脚的编号范围(GPIO23~GPIO27),使用的寄存器名称及作用如下:
lGPLR0(GPIO电平状态寄存器0)
读取GPIO管脚的电平状态,每一位对应一个GPIO管脚。
lGPSR0(GPIO输出设置寄存器0)
控制GPIO管脚输出高电平,每一位对应一个GPIO管脚。
lGPCR0(GPIO输出清除寄存器0)
控制GPIO管脚输出低电平,每一位对应一个GPIO管脚。
lGPDR0(GPIO方向寄存器0)
配置GPIO管脚为输出或者输入,每一位对应一个GPIO管脚。
lGAFR0_U(GPIO复用功能寄存器0)
配置GPIO管脚复用功能,每两位对应一个GPIO管脚。
GPIO管脚的工作模式配置及寄存器取值如下表所示,各寄存器的物理地址详见处理器的数据手册。
3.2SSP接口时序
PXA270的SSP接口支持多种通信协议,包括TI的同步串行协议、Motorola的SPI协议、NI的Microwire协议等。这里使用Motorola的SPI通信协议,其接口时序如下图所示。根据GPIO管脚的工作模式配置,我们只使用其中的SSPSCLK和SSPTXD信号用于发送FPGA的配置时钟和配置数据。
这里需要注意的是,处理器的SSP接口在发送字节数据时是从MSB(最高有效位)开始发送,而FPGA要求每字节数据从LSB(最低有效位)开始发送,所以在配置程序中需要增加一个数据格式转换过程。
4.Linux上配置程序实现
配置程序运行在Linux的用户空间,rbf文件存放在与处理器相连的Flash指定分区中,rbf文件名作为参数传递给配置程序并通过文件访问函数进行读取,配置程序的实现流程如下图所示。
其中PS模式配置流程的具体操作步骤如下:
1)设置nCONFIG=0,保持2us以上;
2)检测nSTATUS,若为0表示FPGA已响应配置请求,否则出错;
3)设置nCONFIG=1,等待不超过40us;
4)检测nSTATUS,若为1表示FPGA可以开始进行配置;
5)在DCLK的每个上升沿,通过DATA0输入比特流数据;
6)待所有数据发送完毕后,CONF_DONE应变为1,表示FPGA配置完成。
对nCONFIG、nSTATUS和CONF_DONE管脚的操作,通过读写相应GPIO寄存器即可实现,这里主要对SSP控制器的操作进行说明。
1.1SSP接口初始化
SSP接口初始化使用到的SSP寄存器如下:
a)SSCR0_1(SSP1控制寄存器0)
b)SSCR1_1(SSP1控制寄存器1)
通过SSCR0_1寄存器配置SSP接口的工作模式,数据位数、时钟频率;通过SSCR1_1寄存器配置SSP接口的极性、相位等参数。最后通过SSCR0_1寄存器使能SSP1接口。初始化代码如下:
static void set_ssp_reg(void)
{
//----Control Register 0----//
int sscr0 = read_reg(SSP_SSCR0);
sscr0 &= ~FRF; //Motorola
sscr0 &= ~MOD;
sscr0 |= (TIM | RIM);
//16-bit data
sscr0 &= ~(0xF);
sscr0 |= DSS;
sscr0 &= ~EDSS;
//Clock 6.5MHz
sscr0 &= ~ACS;
sscr0 &= ~NCS;
sscr0 &= ~ECS;
sscr0 &= ~(0xFFF << 8);
sscr0 |= SCR;
write_reg(SSP_SSCR0, sscr0);
//----Control Register 1----//
int sscr1 = read_reg(SSP_SSCR1);
sscr1 &= ~(0x3fc0);
sscr1 |= TFT; //Set TX fifo level
sscr1 |= RFT; //Set RX fifo level
sscr1 &= ~RWOT; //Tx Rx mode
sscr1 &= ~SPH; //Phase
sscr1 &= ~SPO; //Polarity
sscr1 &= ~LBM;
sscr1 &= ~TIE;
sscr1 &= ~RIE;
write_reg(SSP_SSCR1, sscr1);
//----Control Register 0----------------//
sscr0 = getmem(SSP_SSCR0);
sscr0 |= SSE;
putmem(SSP_SSCR0, sscr0);
}
1.2SSP接口數据发送
SSP接口数据发送使用到的SSP寄存器如下:
a)SSSR_1(SSP1状态寄存器)
b)SSDR_1(SSP1数据寄存器)
通过SSSR_1寄存器读取当前发送FIFO的状态,如果发送FIFO不满,则在SSDR_1寄存器中写入新数据,直到配置数据发送完成。发送代码如下:
static int ssp_xmit(u16 b)
{
while(!(getmem(SSP_SSSR) & TNF));
putmem(SSP_SSDR, b);
return 0;
}
5. 结束语
本文主要实现了基于外部处理器SSP接口的FPGA被动串行配置,具有接口简单、加载速度快、通用性强等特点。基于linux实现的配置程序方便移植和使用,通过分时加载不同的配置文件可以实现FPGA的动态配置。
参考文献
[1] Marvell Inc.Marvell PXA270 Processor Developers Manual, 2009
[2] Altera Inc.Cyclone III Device Handbook, 2012
[3]王黎明.深入浅出XScale嵌入式系统.北京航空航天大学出版社, 2011