EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
引言 根据SRAM工艺FPGA在每次上电后需要进行配置,通常情况下FPGA的配置文件由片外专用的EPROM来加载。这种传统配置方式是在FPGA的功能相对稳定的情况下采用的。在系统设计要求配置速度高,容量大,以及远程升级时,这种方法就显得很不实际也不方便。本文介绍了通过ARM柯林斯对编程器件进行配置的的设计实现状语从句:。 1配置原理与方式 1.1配置原理 在FPGA正常工作时,配置数据存储在SRAM单元中,这个SRAM单元也被称为配置存储器(配置RAM)。由于SRAM是易失性的存储器,因此FPGA在上电之后,外部电路需要将配置数据在芯片配置完成后,内部的寄存器以及I / O管脚必须进行初始化。等初始化完成以后,芯片才会按照用户设计的功能正常工作。 1.2配置方式 根据FPGA在配置电路中的角色,其配置数据可以使用3种方式载入到目标器件中: ·FPGA主动(Active)方式; ·FPGA被动(Passive)方式; ·JT 2 g T4 a) M6 O" O p) N% V5 R: o
| AG方式;
" ]4 }! f; M* _ 在FPGA主动方式下,由目标FPGA来主动输出控制和同步信号(包括配置时钟)给专用的一种串行配置芯片,在配置芯片收到命令后,就把配置数据发到FPGA,完成配置过程。在被动方式下,由系统中的其他设备发起并控制配置过程,FPGA只输出一些状态信号来配合配置过程。被动方式包括被动串行PS(被动串行),快速被动并行FPP(快速被动并行)。 ,被动并行同步PPS(被动并行串行),被动并行异步PPA(被动并行异步),以及异步串行PSA(被动串行异步)。JTAG是IEEE 1149.1边界扫描测试的标准接口。从JTAG接口进行配置可以使用Altera的下载电缆,通过Quartus工具下载,也可以采用模仿来JTAG顺序进行配置。 2硬件电路设计 AT91ARM9200对EP1C6配置的硬件电路示意图如图1所示。 在配置FPGA时,首先需要将年nCONFIG拉低(至少40us),然后拉高。当nCONFIG被拉高后,FPGA的nSTATUS也将变高,表示这时已经可以开始配置,外部电路就可以用DCLK当最后一个比特数据写入以后,CONFIG_DONE管脚被FPGA释放,被外部的上拉电阻拉高,FPGA随即进入初始化状态。 ![]()
图1 ARM配置FPGA电路原理图 3软件设计 本文在设计时使用Linux系统,软件编写和调试是在ADS下。主要程序如下: 静态AT91PS_PIO pioc; 内联void pioc_out_0(int掩码) { pioc-> PIO_CODR =掩码; } 内联void pioc_out_1(int掩码) { pioc-> PIO_SODR =掩码; } 内联int pioc_in(int掩码) { 返回pioc-> PIO_PDSR&mask; } 内联void xmit_byte(char c) { 我 对于(i = 0; i <8; i ++) { 如果(c&1) pioc_out_1(DATA0); 其他 pioc_out_0(DATA0); pioc_out_0(DCLK); pioc_out_1(DCLK); c >> = 1; } } 无效pioc_setup() { pioc-> PIO_PER = DATA0 | nCONFIG | DCLK | 状态| CONF_DONE; pioc-> PIO_OER = DATA0 | nCONFIG | DCLK; pioc-> PIO_ODR = nSTATUS | CONF_DONE; pioc-> PIO_IFER = nSTATUS | CONF_DONE; pioc-> PIO_CODR = DATA0 | nCONFIG | DCLK; pioc-> PIO_IDR = DATA0 | nCONFIG | DCLK | 状态| CONF_DONE; pioc-> PIO_MDDR = DATA0 | nCONFIG | DCLK; pioc-> PIO_PPUDR = DATA0 | nCONFIG | DCLK | 状态| CONF_DONE; pioc-> PIO_OWDR = DATA0 | nCONFIG | DCLK | 状态| CONF_DONE; } int pioc_map() { int fd; off_t addr = 0xFFFFF800; // PIO控制器C 静态void * base; 如果((fd =打开(“ / dev / mem”,O_RDWR | O_SYNC))== -1) { printf(“无法打开/dev/mem。\n”); 返回0;& C: y% Z; ^$ c' c1 R) G
} printf(“ / dev / mem已打开。\ n”); base = mmap(0,MAP_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,fd,addr&〜MAP_MASK); 如果(base ==(void *)-1) { printf(“无法映射。\ n”); 返回0; } printf(“内存映射到地址%p。\ n”,基数); pioc = base +(addr和MAP_MASK); 返回1; } int main(int argc,char ** argv) { FILE *文件; 字符数据[16]; int nbytes,我;? 如果(argc!= 2) { printf(“%s \ n”,argv [0]); 返回-1; } file = fopen(argv [1],“ r”); 如果(!文件) { printf(“找不到文件%s。\ n”,argv [1]); 返回-1; } 如果(!pioc_map()) 返回-1; pioc_setup(); pioc_out_0(nCONFIG); 对于(i = 0; i <10000 && pioc_in(nSTATUS); i ++){} 如果(i == 10000) { printf(“ nSTATUS = 1,然后再尝试配置。\ n”); 返回-1; } pioc_out_1(nCONFIG); for(i = 0; i <10000 &&!pioc_in(nSTATUS); i ++){} 如果(i == 10000) { printf(“等待nSTATUS的超时= 1. \ n”); 返回-1; } 而((nbytes = fread(数据,sizeof(字符),sizeof(数据),文件))> 0) { 如果(pioc_in(CONF_DONE)) { printf(“传输数据时,CONF_DONE =1。\ n”); 返回-1; } 如果(!pioc_in(nSTATUS)) { printf(“ nSTATUS = 0,同时传输数据。\ n”); 返回-1; ' ?, C- x T6 R( t' x
} 对于(i = 0; i <nbytes; i ++) xmit_byte(data ); } 对于(i = 0; i <10000 &&!pioc_in(CONF_DONE); i ++) { 如果(!pioc_in(nSTATUS)) { printf(“ nSTATUS = 0,同时传输数据。\ n”); 返回-1; } pioc_out_0(DATA0); pioc_out_0(DCLK); pioc_out_1(DCLK); } 如果(i == 10000) { printf(“超时等待CONF_DONE = 1. \ n”); 返回-1; 1 U# G& k% C# x/ \2 _
( F. t: ~" m; k1 V } 返回0; } 4结论 这种方法充分利用了ARM的速度快,灵活的特点,节省了开发成本,又满足了一些特殊的系统设计要求。本方法也适用于其他的初步
/ J9 n' k/ B% u w% h1 x6 U, ] |