FPGA-FAQ    0028

Downloading a Bitstream under Linux





Vendor Xilinx & Linux
FAQ Entry Author Brittle & Iwo Mergler & Jan Panteltje
FAQ Entry Editor Philip Freidin
FAQ Entry Date Last updated 2006/03/22

Q. How can I download a FPGA from a Linux System

A. Brittle posted the following as his solution

Thanks to the good ppl. in this news group, I can finally download the 
bit stream to FPGA under Linux. I am here to share the experience (maybe 
somebody have done it before but I could not find). 


Environment: 
1. Software 
 Linux with kernel 2.2.17 (others whould work also) 
 GNU gcc-2.95.2 
2. Hardware 
 Xilinx FPGA (I tried XCV600HQ240 and V1000EHQ240) 
 Xilinx Parallel Cable III (DB25M head) 
 six flying lead 


Procedure: 
1. connect the flying lead to Parallel Cable 
 only the FPGA side is connected (i.e. VCC, GND, D/P, DIN, CCLK, /PROG) 
2. connect the cable to a Linux computer and connect the leads to FPGA pins 
  VCC <--> VCC 
  GND <--> GND 
  D/P <--> DONE 
  DIN <--> DIN 
  CCLK <--> CCLK 
  /PROG <--> /PROG 
 note that the /INT pin in FPGA is not connected 
3. download and compile the source file (at the end of the document) 
 use the following command (-O2 is a must) 
 gcc -Wall -O2 -o w w.c 
4. get ready the bitstream (*.bit) in the same directory of the program 
 here assume the file name is "design.bit" 
5. just involve the program after power up the FPGA 
 make sure you are root when runing the command 
 if the "DONE!" is printed, your design is downloaded correctly 


Important: 
1. I have only test it on Virtex/VirtexE FPGA chips. This should also work 
 on VirtexII. Other families may not work (should not work since the 
 programming requirements are differents) 
2. The Parallel Cable III is not a must. you can make you only cable, check 
 it out in the reference 
3. Since the lack of /INT input to Linux host, the download process will not 
 be interrupted by error(s). The initial stage is also not safe. But 
 if Xilinx makes the cable and thinks it will work, who others will 
 care that? 
4. The DONE signal will tell the condition of program at the end. Since it's 
 release only when CRC checking is passed, it can be trusted. 
5. The download speed is quite fast (4-5 sec for XCV600HQ240 design) on a 
 PIII700 PC. 
6. User must be root to download the bitstream since the program use inb() and 
 outb() to access the port directly. But you still have the choice to 
 setuid and avoid logging in as root every time. 
7. EPP mode is selected for this program. But it really don't matter. You can 
 still run it in other modes. 
8. This porgam is for development use only. Use it on your own risk. 


Reference: 
1. http://www.xilinx.com/support/programr/files/0380507.pdf 
2. XAP137, XAP138, XAP138, XAP501 
3. news from Alan Nishioka 
<--begin--> 
However,  the format is pretty simple.  It uses keys and lengths to 
divide the file. 

2 bytes     length 0x0009 (big endian) 
9 bytes     some sort of header (the length given above) 
2 bytes     length 0x0001 

1 byte      key 0x61 
2 bytes     length 0x000a 
10 bytes   string giving design name 

1 byte      key 0x62 
2 bytes     length 0x000c 
12 bytes   string giving part name 

1 byte       key 0x63 
2 bytes      length 0x000b 
11 bytes    string giving date 

1 byte        key 0x64 
2 bytes      length 0x0009 
9 bytes      string giving time 

1 byte                  key 0x65 
2 bytes                 length 0x000c9090 
8233440 bytes     raw bit stream starting with 0xffffffff aa995566 sync 
word documented below. 
<--end--> 

4. Linux Device Driver p236 Fig.8 
   Reg bit # Direction DB25 pin # 
 Data Reg 0 - 7  ---->  2 - 9 
 Status Reg 3  <----  15 
 Status Reg 4  <----  13 
5. http://www.beyondlogic.org/epp/epp.htm 

Source Code: 
<--begin--> 
#include  
#include  
#include  /* needed for ioperm() */ 
#include  
//#include  /* for outb() and inb() */ 

#define DATA 0x378 
#define STATUS DATA+1 
#define CONTROL DATA+2 

int main(void) { 
 FILE *bitfile; 
 union { 
  unsigned int i; 
  unsigned short s[2]; 
  char c[4]; 
 } head_len; 
 unsigned char head_key; 
 char buf[2035464]; 

 unsigned int i; 
 int j; 
 unsigned char tmp; 
  

 bitfile = fopen("design.bit", "r"); 
 fread(&(head_len.c[1]), 1, 1, bitfile); 
 fread(&(head_len.c[0]), 1, 1, bitfile); 
 fread(buf, head_len.s[0], 1, bitfile); 
 fread(&(head_len.c[1]), 1, 1, bitfile); 
 fread(&(head_len.c[0]), 1, 1, bitfile); 

 head_key = 0; 
 while (head_key != 0x65) { 
  fread(&head_key, 1, 1, bitfile); 
  fread(&(head_len.c[3]), 1, 1, bitfile); 
  fread(&(head_len.c[2]), 1, 1, bitfile); 
  if (head_key == 0x65) { 
   fread(&(head_len.c[1]), 1, 1, bitfile); 
   fread(&(head_len.c[0]), 1, 1, bitfile); 
   fread(buf, head_len.i, 1, bitfile); 
  } 
  else { 
   fread(buf, head_len.s[1], 1, bitfile); 
   printf("%s\n", buf); 
  } 
 } 

 fclose(bitfile); 
  
 if (iopl(3)) { 
  printf("cannot access port!\n"); 
  exit(1); 
 } 

 outb(0x04, CONTROL); 

 // sense VCC 
 tmp = inb(STATUS); 
 tmp = (tmp >> 3) & 1; 
 if (!tmp) { 
  printf("cabel not found\n"); 
  exit(0); 
 } 
 else 
  printf("cabel detected\n"); 

 // clear config 
 outb(0x10, DATA); 
 printf("configuration memory cleared\n"); 
 outb(0x14, DATA); 

 printf("start loading %d bytes\n", head_len.i); 
 for (i = 0; i < head_len.i; i++) { 
  for (j = 7; j >= 0; j--) { 
   tmp = (buf[i] >> j) & 1; 
   outb(tmp | 0x14, DATA); 
   outb(tmp | 0x16, DATA); 
  } 
 } 
 printf("finish loading\n"); 

 // Done 
 tmp = inb(STATUS); 
 tmp = (tmp >> 4) & 1; 
 if (tmp) 
  printf("DONE!\n"); 
 else 
  printf("FAILED!\n"); 
  

 return (0); 
} 
<--end--> 

Good Luck! 


A. Iwo Mergler posted the following Thu, 21 Nov 2002

Here is a function for configuration of Flex10K, 
running under Linux. My program does serial 
configuration through PCI, so the rest is probably 
not relevant to you. 

This source won't compile directly, but if you regard 
it as pseudo-code, it should be easy to do include this in 
your own program. The 'progress' argument is a function 
callback to implement progress bars. The function reads 
data taken directly from the *.TTF file created by MaxPlus2. 

To access the parallel port under Linux, you can either 
directly access the hardware (iopl, needs root) or use the 
parport driver. 

Kind regards, 

Iwo 

=============== 

long int Altera_Config(long int bytes,void (*Progress)(int percent)) 
{ 
   long i,to,tick,tc; 
   unsigned char b,v; 
   int percent; 
   T_nCONF(0); 
   T_CLK(0); 
   T_DTA(1); 
   usleep(1*1000); 
   T_nCONF(0); 
   usleep(1*1000); 
   T_nCONF(1); 
   for (to = timeout; to > 0; to--) 
   { 
     usleep(1 * 1000); 
     if (T_nSTAT() != 0) break; 
   } 
   if (to == 0) return(-1); 
   tick = bytes / 100; tc = tick; percent = 1; 
   for (i = 0; i <= bytes; i++) 
   { 
     tc--; 
     if (tc == 0) 
     { 
       Progress(percent++); 
       tc = tick; 
     } 
     v = SOF[i]; 
     if (T_nSTAT() == 0) 
     { 
       return(i + 1); /* Point of failure */ 
     } 
     for (b = 0; b < 8; b++) 
     { 
       if (Bit(0,v)) T_DTA(1); else T_DTA(0); 
       T_CLK(0); T_CLK(1); 
       v >>= 1; 
     } 
   } 
   /* more clocks required... */ 
   for (i = 0; i < 40; i++) 
   { 
     T_CLK(1); 
     T_CLK(0); 
   } 
   /* Wait for CONFIG_DONE */ 
   for (to = timeout; to > 0; to--) 
   { 
     usleep(1 * 1000); 
     if (T_CONF_DONE() != 0) break; 
   } 
   if (to == 0) return(-1); 

   return(0); 
}



A. Jan Panteltje Thu, 17 June 2004

I have taken the above source, added a makefile, and added a way
to add the bit filename in the command line, also added some
error checking.

================================== impact-fl.c

#include 
#include 
#include  /* needed for ioperm() */
//#include 
#include  /* for outb() and inb() */

#define DATA 0x378
#define STATUS DATA + 1
#define CONTROL DATA + 2


int main(int argc, char **argv)
{
FILE *bitfile;

union
{
unsigned int i;
unsigned short s[2];
char c[4];
} head_len;

unsigned char head_key;
char buf[2035464];

unsigned int i;
int j;
unsigned char tmp;

if(argc < 2)
	{
	fprintf(stderr, "Usage:  impact-fl bitfile\n");

	exit(1);
	}

bitfile = fopen(argv[1], "r");
if(! bitfile)
	{
	fprintf(stderr, "Could not open file %s for read, aborting.\n", argv[1]);

	exit(1);
	}

fread(&(head_len.c[1]), 1, 1, bitfile);
fread(&(head_len.c[0]), 1, 1, bitfile);
fread(buf, head_len.s[0], 1, bitfile);
fread(&(head_len.c[1]), 1, 1, bitfile);
fread(&(head_len.c[0]), 1, 1, bitfile);

head_key = 0;

while (head_key != 0x65)
	{
	fread(&head_key, 1, 1, bitfile);
	fread(&(head_len.c[3]), 1, 1, bitfile);
	fread(&(head_len.c[2]), 1, 1, bitfile);
	if (head_key == 0x65)
		{
		fread(&(head_len.c[1]), 1, 1, bitfile);
		fread(&(head_len.c[0]), 1, 1, bitfile);
		fread(buf, head_len.i, 1, bitfile);
		}
	else
		{
		fread(buf, head_len.s[1], 1, bitfile);
		printf("%s\n", buf);
		}
	}

fclose(bitfile);
 
if (iopl(3))
	{
	printf("Cannot access port!\n");

	exit(1);
	}

outb(0x04, CONTROL);

// sense VCC
tmp = inb(STATUS);
tmp = (tmp >> 3) & 1;
if(!tmp)
	{
	printf("cable not found\n");
	exit(0);
	}
else
  printf("cable detected\n");

// clear config
outb(0x10, DATA);
printf("configuration memory cleared\n");
outb(0x14, DATA);

printf("start loading %d bytes\n", head_len.i);

for(i = 0; i < head_len.i; i++)
	{
	for(j = 7; j >= 0; j--)
		{
		tmp = (buf[i] >> j) & 1;
		outb(tmp | 0x14, DATA);
		outb(tmp | 0x16, DATA);
		}
	}
printf("finished loading\n");

// Done
tmp = inb(STATUS);
tmp = (tmp >> 4) & 1;
if (tmp)
	 printf("DONE!\n");
else
  printf("FAILED!\n");
 
exit(0);
} /* end function main */



================================== INSTALL

parport used is 0x378, change in source if needed.

To compile and install:

make
make install
make clean


Usage:
impact-fl bitfile

================================== Makefile

CFLAGS = -O2 

.c.o:
	gcc $(CFLAGS) -c $<

OBJECT = impact-fl.o


LIBRARY =

a.out : $(OBJECT)
	gcc -o impact-fl  $(OBJECT) $(LIBRARY)
		
# DEPENDENCIES

impact-fl.o : impact-fl.c


install:
	cp impact-fl /usr/local/bin/

clean:
	rm ./impact-fl.o

==================================

FPGA-FAQ FAQ Root