FPGA driver for the DragonEngine

Compilation

You have to activated the 'DragonEngine FPGA driver' option of the build process, in Kernel Settings/Character devices. You also have to created a device file, the easiest way is to modified the file uClinux-dist/vendors/Exys/de2/Makefile and add a line :

        fpga,c,61,0

in the DEVICES list. Then rebuild with make.

Usage

The driver is designed to:

Loading/checking a .bit file from a shell command line

you may load .bit file directly from a shell command line as follow :

# cat de2pio.bit > /dev/fpga

or, if the .bit file is compressed with gzip :

# zcat de2pio.bit.gz > /dev/fpga

The driver will parse the .bit file and displays error if it can not initialize the fpga, to check if the file has been correctly loaded, use :

# cat /proc/de2fpga
FPGA status: ok
file: de2pio.ncd
part: 2s50tq144
date: 2001/05/14
time: 13:19:27

It should display the .bit file informations, status could be unknown if the fpga has not been intialized though the driver or error if there was an error in the previous load.

Opening the fpga from a C program

Here is a simple program to open the fpga under uClinux :

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/de2fpga.h>

#define BIT(x) (1<<(x))

int main(int argc, char *argv[])
{
        int fd;
        struct de2fpga_info fpgainfo;
        short *fpgaregs;
        
        fd = open("/dev/fpga", O_RDONLY);
        if (fd < 0) {
                perror("Error opening fpga\n");
                return 1;
        }

        if (ioctl(fd, DE2FPGA_PARAMS_GET, &fpgainfo) < 0) {
                perror("Unable to retrieve fpga information");
        }
        else {
                printf("FPGA status : %s\n", fpgainfo.status ==
                        DE2FPGA_STS_OK ? "ok" : fpgainfo.status ==
                        DE2FPGA_STS_UNKNOWN ? "unknown" : "error");
                printf("file: %s\n", fpgainfo.buf+fpgainfo.file);
                printf("part: %s\n", fpgainfo.buf+fpgainfo.part);
                printf("date: %s\n", fpgainfo.buf+fpgainfo.date);
                printf("time: %s\n", fpgainfo.buf+fpgainfo.time);
        }

        fpgaregs = mmap(0, 16*2, PROT_READ|PROT_WRITE, 0, fd, 0);
        
        if (fpgaregs == MAP_FAILED) {
                perror("Unable to mmap fpga");
                return 1;
        }

        printf("fpga regs at 0x%08x\n", fpgaregs);

        /*
         * here you can read or write the FPGA pseudo-registers
         * to control the IO pin.
         *
         */

        fpgaregs[4] = 0xffff; /* set port C as input */
        if (fpgaregs[5] & BIT(4)) {
                /* port C bit 4 is high */
        }
        else {
                /* port C bit 4 is low */
        }

        fpgaregs[2] = 0; /* set port B as output */
        fpgaregs[3] |= BIT(5); /* set port B bit 5 high */
        fpgaregs[3] &= ~BIT(5); /* set port B bit 5 low */

        /*
         * once you are done...
         *
         */
        close(fd);

        return 0;
}

You can check from your program that the fpga has been initialized, you may even check if a specific .bit file has been loaded. The mmap call set the fpgaregs variable which can be use as an array to read/write the pseudo registers in other part of your program.

sig