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
==================================
|