1、导言
在体系上电时,需求从外部载入所要运转的程序,此进程被称为程序加载。大都情况下,从外部专用的 读入程序。这种办法速度慢,并且只能加载固定的程序。明显,当体系需求容量大并且 FPGA要加载的程序能够依据需求有挑选的加载时不能选用这种办法。本文完结了一种依据外部处理器的加载办法,速度快,并且能够依据设置给FPGA加载相应的程序。
关于 公司的 FPGA芯片,有五种加载办法:JTAG方式,串行从方式,串行主方式,并行从方式和并行主方式。JTAG方式常用于调试时,将主机好的程序加载到FPGA,优先级高于几种方式。加载方式取决于 FPGA上加载方式管脚(M0,M1,M2)的设置。
用外部处理器给 FPGA加载程序时,能够选用串行从方式、并行从方式,甚至于 JTAG方式。本文挑选并行从方式,原因在于更高的装备速率。
2、 FPGA程序数据的发生
FGPA的程序加载便是要把好的程序文件按必定的时序写入FPGA。而 的开发环境能够依据用户的挑选发生多种文件格局,以不同的后缀名区别。不同的文件格局包括了不同的信息,有不同的用处。
本文挑选了.bin格局的文件。此文件是只包括有程序数据的二进制文件。发生此文件,要在bitgen 参数里添加-g :yes 选项。
此外,需求阐明的是,一般的微处理器 D0位是最低有用位,而 的 FPGA在接纳程序数据时,D0位是最高有用位。因而,在按字节读取.bin格局的文件之后,需求有一个转化的进程。如从文件读到一个字节,0x7D,即二进制的 0111 1101,需转化为:1011 1110。
加载进程开端时,就要从.bin文件序按字节读出数据,然后在 CCLK的上升沿写入 FPGA。在.bin文件中的数据都被写入 FPGA后,CCLK需求多出四个时钟周期,以使得 FPGA完结发动进程。
3、硬件规划
在FPGA上,与装备有关的管脚分为两类:专用管脚,包括_B,HSWAP_EN,TDI, TMS,,TCK,TDO,CCLK,DONE,和M0-M2。还有一类是可复用管脚,这类管脚在装备阶段作为装备管脚,装备完毕后能够装备为通用一般的IO管脚,也能够持续作为装备管脚。在并行从方式下,涉及到的装备管脚和功用如下:
CS_B:片选信号,低有用; RDWR_B:写信号,低有用; BUSY:FPGA忙指示,高有用,一般只要在并行加载时钟速率大于50M时才有或许用到;D0-D7:数据线; _B:芯片被复位后,此管脚为输出信号,输出低电平指示FPGA正在自行复位内部
寄存器。复位完毕后,此管脚浮空,处于输入状况。因而需求上拉电阻,指示复位完毕。内部寄存器复位完毕后,此管脚若被拉低,则会推延FPGA的程序加载进程。在程序加载进程中,此管脚又变回输入状况,对外输出低电平指示加载的程序数据存在CRC校验过错。
_B:异步复位信号,下降沿有用,此信号为低电平时复位FPGA,复位后,FPGA芯片处于内部寄存器自行复位进程,_B被FPGA芯片拉低,此进程完毕后,FPGA不再驱动_B管脚,INIT_B管脚处于浮空状况,此刻,INIT_B有上拉电阻时,INIT_B出现高电平,顺次能够指示FPGA的内部寄存器自行复位完毕。程序加载状况。
DONE:加载成功指示。 CCLK:程序加载时,数据在此信号的上升沿被写入FPGA。在本规划中,ARM芯片选用的是 SUMSUN公司的,与 FPGA装备管脚相连的是此芯片的通用 IO管脚 D组。硬件衔接如图[1]所示。在 ARM的程序中,ARM管脚在程序加载的各阶段的输入输出设置如下:首要,设置 GPD[10](与 FPGA的 INIT_B相连)、GPD[11](与 FPGA的 BUSY相连)为输入管脚,以监督 FPGA内部寄存器自行复位完毕和忙闲状况。其次,设置GPD[12](与 FPGA的 _B相连)为输出状况,并使其输出低脉冲,使 FPGA复位。然后顺次设置 GPD[8](与 FPGA的 CS_B相连)、GPD[9](与 FPGA的 RDWR_B相连)、GPD[14] (与 FPGA的 CCLK相连)为输出管脚,并使其输出低电平,使 FPGA处于被选可接受数据状况;接着设置D[0..7]为输出状况。
至此,ARM中的程序开端轮询GPD[10]的状况,检测到此信号为高时,有两种挑选,其一是因为需求而推延 FPGA的程序加载,能够经过设置 GPD[10]为输出,并使其输出为低电平直至程序加载开端。其二是开端给 FPGA加载程序,FPGA在 CCLK的上升沿接纳数据,在给 FPGA加载程序的进程中,程序需求监督GPD[10]管脚的状况,一旦为低,FPGA指示程序数据加载 CRC校验犯错。此刻需求复位FPGA,从头加载。
4、嵌入式 的驱动完结
本文以模块方式完结了运转于上的驱动程序,源文件如下(有关寄存器
的设置参阅的数据手册,以下源代码未包括头文件):
#define GPIO_va_ 0x0F6000000
//依据S3C2410 上的Linux内核IO操控寄存器首地址映射后的虚拟地址
#define ARM_GPDCON PIO_va_+0x30);
#define ARM_GPDUP PIO_va_+0x38);
#define ARM__wr(addr,) *(volatile unsigned int*)(addr)=)
//界说输出
#define FPGA_CS 8
#define FPGA_RW 9
#define FPGA_PROG 12
#define FPGA_CCLK 14
//界说操作
#define ARM_GPDDAT (*(volaTIle u32 *)(GPIO_va_base+0x34))
#define set_register_bit(x) ARM_GPDDAT=(1《《x)|ARM_GPDDAT
#define _register_bit(x) ARM_GPDDAT=(~(1《《x))&ARM_GPDDAT
//界说输入
#define FPGA_INIT ((ARM_GPDDAT》》10)&1)
#define FPGA_BUSY ((ARM_GPDDAT》》11)&1)
#define FPGA_DONE ((ARM_GPDDAT》》13)&1)
#define FPGA 211
//界说主设备号,和mknod /dev/ c 211 0匹配
typedef __t;
staTIc __t fpga_s[257];
buf[1000000];
int fpga_(struct inode *, struct file *);
ssize_t fpga_write(struct file *, *,size_t ,loff_t *);
int fpga_(struct inode*, struct file *);
//初始化ARM的D组通用IO管脚
void _fpga(void){
ARM__wr(GPIO_va_base+0x30,0x55555555);
//FPGA_BUSY FPGA_DONE FPGA_INIT be set input
ARM__wr(GPIO_va_base+0x34,0xFFFF);
ARM_port_wr(GPIO_va_base+0x30,0x51055555);
ARM_port_wr(GPIO_va_base+0x38,0);// put up
set_register_bit(FPGA_CCLK);//set GCLK
}
staTIc struct file_operaTIons fpga_ctl_fops= {
: fpga_,
write: fpga_write,
: fpga_,};
int _(void) {
printk(“,word,Now preparing FPGA.。。.。。\n”);
printk(“register FPGA.。。.。。\n”);
register_chrdev(FPGA, “fpga”, &fpga_ctl_fops);
printk(“Done!\n”);
printk(“,word,success!\n”);
0;
}
int fpga_open(struct inode *inode, struct file *filp){
int minor;
minor = MINOR(inode-》i_rdev);
_fpga();
fpga_[minor]++;
printk(“FPGA is ready.\n”);
0;
}
ssize_t fpga_write(struct file *, char *buffer,size_t count,loff_t
*ppos){
int i;
if(__(buf,buffer,count)){
printk(“error \n”);
-EFAULT;
}
printk(“%d s have been received!\n”,count);
printk(“The is:%d\n”,count);
for(i=0;i《count;i++){
ARM_GPDDAT=(ARM_GPDDAT&0x3F00)|buf[i];
set_register_bit(FPGA_CCLK);
}
printk(“data write finished\n”);
for(i=0;i《4;i++){
set_register_bit(FPGA_CCLK);
_register_bit(FPGA_CCLK);
}
return count;
}
int fpga_release(struct inode *inode, struct file *filp){
int minor;
minor = MINOR(inode-》i_rdev);
if (fpga_[minor])
fpga_[minor]–;
printk(“Goodbye cruel world\n”);
return 0;
}
void cleanup_(void){
printk(“Goodbye cruel world\n”);
}
5、完毕语
本文的立异点:依据ARM-Linux渠道,完结了一种FPGA的程序加载方式,加载速度快,灵敏高效。