Altera 公司生产的具有ICR 功能的FPGA 器件有FLEX6000、FLEX10K、APEX 和ACEX等系列。它们的配置方式可分为PS(被动串行)、PPS(被动并行同步)、PPA(被动并行异步)、PSA(被动串行异步)和JTAG(Joint Test Action Group)等五种方式。这五种方式都能适用于单片机配置。PS 方式因电路简单,对配置时钟的要求相对较低,而被广泛应用。下图是PS 配置方式的时序图。
CPU 仅需要利用5 个I/O 脚与FPGA 相连,就实现了PS 方式的硬件连接,具体信号见下表(信号方向从CPU 侧看):
信号名
I/O
说明
Data
O
configuration data
DCLK
O
configuration clock
nCONFIG
O
device reset (a low to high transition starts the configuration within the device)
CONF_DONE
I
Status bit (gets checked after configuration, will be high if configuration complete)
nSTATUS
I
Status bit indicating an error during configuration if low
被动串行工作过程:当nconfig 产生下降沿脉冲时启动配置过程,在dclk 上升沿,将数据移入目标芯片。在配置过程中,系统需要实时监测,一旦出现错误,nSTATUS 将被拉低,系统识别到这个信号后,立即重新启动配置过程。配置数据全部正确地移入目标芯片内部后,CONF_DONE 信号跳变为高,此后,DCLK 必须提供几个周期的时钟(具体周期数与DCLK的频率有关),确保目标芯片被正确初始化,进入用户工作模式。
Altera 的MAX+PLUS II 或Quartus II 开发工具可以生成多种配置或编译文件,用于不同配置方法的配置系统,而对于不同系列的目标器件配置数据的大小也不同,配置文件的大小一般有.rbf 文件决定。.rbf 文件即二进制文件。该文件包括所有的配置数据,一个字节的 .rbf文件有8 位配置数据,每一字节在配置时最低位最先被装载。微处理器可以读取这个二进制文件,并把它装载到目标器件中。Altera 提供的软件工具不自动生成 .rbf 文件,须按照下面的步骤生成:
① 在MAX+PLUS II 编译状态,选择文件菜单的变换SRAM 目标文件命令;
② 在变换SRAM 目标文件对话框,指定要转换的文件并且选择输出文件格式为.rbf(Sequential),然后确定。
配置操作过程:
CPU 按下列步骤操作I/O 口线,即可完成对FPGA 的配置:
1、nCONFIG="0"、DCLK="0",保持2μS 以上。
2、检测nSTATUS,如果为"0",表明FPGA 已响应配置要求,可开始进行配置。否则报错。正常情况下,nCONFIG="0"后1μS 内nSTATUS 将为"0"。
3、nCONFIG="1",并等待5μS。
4、Data0 上放置数据(LSB first),DCLK="1",延时。
5、DCLK="0",并检测nSTATUS,若为"0",则报错并重新开始。
6、准备下一位数据,并重复执行步骤4、5,直到所有数据送出为止。
7、此时Conf_done 应变成"1",表明FPGA 的配置已完成。如果所有数据送出后,Conf_done不为"1",必须重新配置(从步骤1 开始)。
8、配置完成后,再送出10 个周期的DCLK,以使FPGA 完成初始化。
FPGA 配置电路:
1、JTAG 接口:
JTAG 接口可以用来调试FPGA,下载速度比较快,而且支持SignalTAP。但是不能用来编程EPCS 芯片。建议调试阶段采用JTAG 模式。电缆可以采用ByteBlaster (MV) 也可以用用ByteBlaster II。
2、AS 接口
AS 接口主要是用来编程EPCS 芯片,同时也可以用来调试。具体过程是首先编程EPCS,然后通过EPCS 配置FPGA,运行程序。需要考虑的是EPCS 的编程次数是有限制的,虽然比EPC 系列要多,但是太频繁的擦除和写入对芯片还是有一定影响的。所以,我们建议在调试结束后,程序固化的时候才使用AS 方式。 如果采用这种方式,必须采用ByteBlasterII。电缆才行。
3、采用CPLD 或者单片机配置FPGA
可以通过这些配置引脚由CPLD 来对FPGA 进行配置。利用单片机配置FPGA 的电路图如下:
与上图对应的用单片机配置FPGA 的C 程序如下:
/* 用8031 加载ALtera 的FPGA,也可用于Xilinx 的FPGA 的加载 */
void load_epld(void)
{
unsigned char data i;
unsigned int data j;
unsigned char xdata * data pt;
SCON = 0x0; /* 设置8031 工作在方式0,同步串行方式 */
CONFIG = 0; /* 初始化FPGA */
i=4 /* 注意8031 的工作频率和速度,对于Xilinx 的FPGA,初始化的时间要长一些,具体查下各个FPGA 的参数 */
while(STATUS!=0) {
i--;
if(i==0) {
CONFIG = 0;
FPGA_Init_Error(); /* FPGA 初始化错误处理程序,自己编制 */
}
}
CONFIG = 1; /* 初始化FPGA 完毕 */
i=10; /* 注意8031 的工作频率和速度,各个FPG 的初始化的时间不一样,具体查下各个FPGA 的参数 */
while(STATUS!=1) {
i--;
if(i==0) {
CONFIG = 0; /* 错误时,使FPGA 处于初始化状态,保证电路处于安全状态 */
FPGA_Init_Error(); /* FPGA 初始化错误处理程序,自己编制 */
}
}
pt=(unsigned char xdata *)EPLD_DATA; /* EPLD_DATA 为FPGA 的存放地址 */
for(j=0; j < EPLD_Number; j++) { /* EPLD_Number 为FPGA 的加载字节数,当大于64K */
SBUF = *pt++; /* 字节时,要采用页面切换的方式 */
while(!TI); /* 等待1 个字节加载完毕 */
TI=0;
if(STATUS!=1) { /* 加载过程中,检查加载是否正确 */
CONFIG = 0; /* 错误时,使FPGA 处于初始化状态,保证电路处于安全状态 */
FPGA_Load_Error(); /* FPGA 加载错误处理程序,自己编制 */
}
}
if(CFG_DOWN!=1) { /* FPGA 数据加载完毕,检查加载是否正确 */
CONFIG = 0; /* 错误时,使FPGA 处于初始化状态,保证电路处于安全状态 */
FPGA_Done_Error(); /* FPGA 加载错误处理程序,自己编制 */
}
}