ZTEX

 
Products
Series 2 FPGA Boards
  USB-FPGA Module 2.16
  USB-FPGA Module 2.13
  USB-FPGA Module 2.04
  USB-FPGA Module 2.01
  FPGA Module 2.00
  Debug Board
  Series 1 Adapter
  Cluster Board
  FX3 preview
Series 1 FPGA Boards
  USB-FPGA Module 1.11
  USB-FPGA Module 1.15
  USB-FPGA Module 1.15x
  USB-FPGA Module 1.15y
  Experimental Board 1.3
  Experimental Board 1.2
  Analog Experimental Board
  Power Supply Module
  Reference designs
Microcontroller Boards
  USB-XMEGA Board
To the ZTEX Shop ZTEX Shop
 SDK and Examples 
  Overview
  Documentation
  Downloads
  Example
  Release history
  ZTEX Wiki
 
  BTCMiner - Bitcoin Miner
OS Discount Program
 
Downloads
 
Contact
Impressum
Terms and Conditions
RoHS
 

Twitter Google+
    Home / Products         SDK    
    To the ZTEX Shop Shop   
    Wiki / Forums         Downloads    
    deutsch     englisch    

SDK for ZTEX FPGA Boards - Example

The SDK package contains a lot of useful examples, e.g. for interfacing memory, for high speed USB transfers via EZ-USB FX2 and for accessing Flash memory.

The following very simple example runs on ZTEX USB-FPGA Boards and gives an impression of the benefits of the macro approach of the ZTEX EZ-USB FX2 SDK.

The firmware (defined in ucecho.c) declares Endpoint 2 and Endpoint 4 (both 512 bytes, double buffered, bulk transfer, belong to interface 0). All data that is written to Endpoint 4 is converted to uppercase by the FPGA and can be read back from Endpoint 2.

The Bitstream for the FPGA configuration is defined in fpga/ucecho.vhd. The FPGA reads one byte per clock cycle from port PC, converts it to uppercase and writes it to port PB.

The host software (defined in UCEcho.java) sends user strings to the device and reads them back. Uploading of the firmware (ucecho.ihx) to the EZ-USB FX2 Microcontroller and uploading of the Bitstream (fpga/ucecho.bin) to the FPGA is manged using the Java API.

The example is a part of the package and may serve a good starting point for own projects.

Firmware: ucecho.c

This is the C source code for the firmware:

#include[ztex-conf.h]   // Loads the configuration macros, see ztex-conf.h for the available macros
#include[ztex-utils.h]  // include basic functions

// Cypress vendor ID and product ID may only (!) be used for experimental purposes
SET_VPID(0x4b4,0x8613);         

// define endpoints 2 and 4, both belong to interface 0 (in/out are from the point of view of the host)
EP_CONFIG(2,0,BULK,IN,512,2);    
EP_CONFIG(4,0,BULK,OUT,512,2);   

// identify as ZTEX USB FPGA Module 1.2  (Important for FPGA configuration)
IDENTITY_UFM_1_2(1.0.0.0,0);     

// give them a nice name
#define[PRODUCT_STRING]["ucecho for USB FPGA MODULE 1.2"]

// this is called automatically after FPGA configuration
#define[POST_FPGA_CONFIG][POST_FPGA_CONFIG
        OEC = 255;
]

// include the main part of the firmware kit, define the descriptors, ...
#include[ztex.h]


void main(void) 
{
    WORD i,size;
    
// init everything
    init_USB();

    EP2CS &= ~bmBIT0;   // stall = 0
    SYNCDELAY; 
    EP4CS &= ~bmBIT0;   // stall = 0

    SYNCDELAY;          // first two packages are waste
    EP4BCL = 0x80;      // skip package, (re)arm EP4
    SYNCDELAY;
    EP4BCL = 0x80;      // skip package, (re)arm EP4

    while (1) { 
        if ( !(EP4CS & bmBIT2) ) {                              // EP4 is not empty
            size = (EP4BCH << 8) | EP4BCL;
            if ( size>0 && size<=512 && !(EP2CS & bmBIT3)) {    // EP2 is not full
                for ( i=0; i<size; i++ ) {
                    IOC = EP4FIFOBUF[i];        // data from EP4 is converted to uppercase by the FPGA ...
                    EP2FIFOBUF[i] = IOB;        // ... and written back to EP2 buffer
                } 
                EP2BCH = size >> 8;
                SYNCDELAY; 
                EP2BCL = size & 255;            // arm EP2
            }
            SYNCDELAY; 
            EP4BCL = 0x80;                      // skip package, (re)arm EP4
        }
    }
}

Bitstream: fpga/ucecho.vhd

This is the VHDL source for the FPGA bitstream:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--
entity ucecho is
   port(
      pc      : in unsigned(7 downto 0);
      pb      : out unsigned(7 downto 0);
      CLK     : in std_logic
   );
end ucecho;
--
--
--signal declaration
architecture RTL of ucecho is
--
begin
    dpUCECHO: process(CLK)
    begin
         if CLK' event and CLK = '1' then
    if ( pc >= 97 ) and ( pc <= 122)
    then
pb <= pc - 32;
    else
pb <= pc;
    end if;
end if;
    end process dpUCECHO;
--
end RTL;

Java host software: UCEcho.java

This is the Java source code for the host software:

import java.io.*;
import java.util.*;

import ch.ntb.usb.*;

import ztex.*;

// *****************************************************************************
// ******* ParameterException **************************************************
// *****************************************************************************
// Exception the prints a help message
class ParameterException extends Exception {
    public final static String helpMsg = new String (
                "Parameters:\n"+
                "    -d <number>       Device Number (default: 0)\n" +
                "    -f                Force uploads\n" +
                "    -p                Print bus info\n" +
                "    -h                This help" );
    
    public ParameterException (String msg) {
        super( msg + "\n" + helpMsg );
    }
}

// *****************************************************************************
// ******* Test0 ***************************************************************
// *****************************************************************************
class UCEcho extends Ztex1v1 {

// ******* UCEcho **************************************************************
// constructor
    public UCEcho ( ZtexDevice1 pDev ) throws UsbException {
        super ( pDev );
    }

// ******* claimInterface ******************************************************
// claims interface 0
    public void claimInterface ( ) throws UsbException{
        if ( LibusbJava.usb_claim_interface(handle(), 0) < 0 )
            throw new UsbException("Claiming interface 0 failed: " + LibusbJava.usb_strerror());
    }

// ******* releaseInterface ****************************************************
// releases interface 0
    public void releaseInterface ( ) {
        LibusbJava.usb_release_interface(handle(), 0);
    }
    
// ******* echo ****************************************************************
// writes a string to Endpoint 4, reads it back from Endpoint 2 and writes the output to System.out
    public void echo ( String input ) throws UsbException {
        byte buf[] = input.getBytes(); 
        int i = LibusbJava.usb_bulk_write(handle, 4, buf, buf.length, 1000);
        if ( i<0 )
            throw new UsbException("Error sending data: " + LibusbJava.usb_strerror());
        System.out.println("Send "+i+" bytes: `"+input+"'" );

        try {
            Thread.sleep( 10 );
        }
            catch ( InterruptedException e ) {
        }

        buf = new byte[1024];
        i = LibusbJava.usb_bulk_read(handle, 2, buf, 1024, 1000);
        if ( i<0 )
            throw new UsbException("Error receiving data: " + LibusbJava.usb_strerror());
        System.out.println("Read "+i+" bytes: `"+new String(buf,0,i)+"'" );  
    }
    
// ******* main ****************************************************************
    public static void main (String args[]) {
    
        int devNum = 0;
        boolean force = false;
        
        try {
// init USB stuff
            LibusbJava.usb_init();

// scan the USB bus
            ZtexScanBus1 bus = new ZtexScanBus1( ZtexDevice1.cypressVendorId, ZtexDevice1.cypressProductId, true, false, 1);
            if ( bus.numberOfDevices() <= 0) {
                System.err.println("No devices found");
                System.exit(0);
            }
            
// scan the command line arguments
            for (int i=0; i<args.length; i++ ) {
                if ( args[i].equals("-d") ) {
                    i++;
                    try {
                        if (i>=args.length) throw new Exception();
                        devNum = Integer.parseInt( args[i] );
                    } 
                    catch (Exception e) {
                        throw new ParameterException("Device number expected after -d");
                    }
                }
                else if ( args[i].equals("-f") ) {
                    force = true;
                }
                else if ( args[i].equals("-p") ) {
                    bus.printBus(System.out);
                    System.exit(0);
                }
                else if ( args[i].equals("-h") ) {
                        System.err.println(ParameterException.helpMsg);
                        System.exit(0);
                }
                else throw new ParameterException("Invalid Parameter: "+args[i]);
            }
            

// create the main class            
            UCEcho ztex = new UCEcho ( bus.device(devNum) );
            
// upload the firmware if necessary
            if ( force || ! ztex.valid() || ! ztex.dev().productString().equals("ucecho for USB FPGA MODULE 1.2")  ) {
                ztex.uploadFirmware( "ucecho.ihx", force );
            }
            
// upload the bitstream if necessary
            if ( force || ! ztex.getFpgaConfiguration() ) {
                System.out.println("FPGA configuration time: " + ztex.configureFpga( "fpga/ucecho.bin" , force ) + " ms");
            } 


// claim interface 0
            ztex.claimInterface();
            
// read string from stdin and write it to USB device
            String str = "";
            BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
            while ( ! str.equals("quit") ) {
                System.out.print("Enter a string or `quit' to exit the program: ");
                str = reader.readLine();
                ztex.echo(str);
                System.out.println("");
            }
            
// release interface 0
            ztex.releaseInterface();    
            
        }
        catch (Exception e) {
            System.out.println("Error: "+e.getLocalizedMessage() );
        } 
   } 
   
}

C host software: UCEcho.c

It is also possible to access the device with other programming languages. In this case the firmware must be loaded using the FWLoader utility included in the SDK.

The C source code of the host software is:

/*!
   UCEcho -- C host software for ucecho examples
   Copyright (C) 2009-2010 ZTEX GmbH
   http://www.ztex.de

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3 as
   published by the Free Software Foundation.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, see http://www.gnu.org/licenses/.
!*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <usb.h>

#define BUFSIZE  256

struct usb_device *device;
usb_dev_handle *handle;
char buf[BUFSIZE];

// find the first ucecho device
struct usb_device *find_device ()
{
    struct usb_bus *bus_search;
    struct usb_device *device_search;

    bus_search = usb_busses;
    while (bus_search != NULL)
    {
        device_search = bus_search->devices;
        while (device_search != NULL)
        {
            if ( (device_search->descriptor.idVendor == 0x221a) && (device_search->descriptor.idProduct == 0x100) ) 
            {
                handle = usb_open(device_search);
                usb_get_string_simple(handle, device_search->descriptor.iProduct, buf, BUFSIZE);
                if ( ! strncmp("ucecho", buf , 6 )  )
                    return device_search;
                usb_close(handle);
            }
            device_search = device_search->next;
        }
        bus_search = bus_search->next;
    }
    
    return NULL;
}

// main
int main(int argc, char *argv[])
{
    usb_init();                                         // initializing libusb
    usb_find_busses();                                  // ... finding busses
    usb_find_devices();                                 // ... and devices

    device = find_device();                             // find the device (hopefully the correct one)

    if ( device == NULL ) {                             // nothing found
        fprintf(stderr, "Cannot find ucecho device\n");
        return 1;
    }

    if (usb_claim_interface(handle, 0) < 0) {
        fprintf(stderr, "Error claiming interface 0: %s\n", usb_strerror());
        return 1;
    }
    
    while ( strcmp("QUIT", buf) ) {
        // read string from stdin
        printf("Enter a string or `quit' to exit the program: ");
        scanf("%s", buf);
        
        // write string to ucecho device 
        int i = usb_bulk_write(handle, 0x04, buf, strlen(buf)+1, 1000);
        if ( i < 0 ) {
            fprintf(stderr, "Error sending data: %s\n", usb_strerror());
            return 1;
        }
        printf("Send %d bytes: `%s'\n", i , buf);

        // read string back from ucecho device 
        i = usb_bulk_read(handle, 0x82, buf, BUFSIZE, 1000);
        if ( i < 0 ) {
            fprintf(stderr, "Error readin data: %s\n", usb_strerror());
            return 1;
        }
        printf("Read %d bytes: `%s'\n", i , buf);

    }

    usb_release_interface(handle, 0);
    usb_close(handle);
    return 0;
}

Example call

It follows an example call with output:

stefan@ws2:/drv_a2/usb-fpga/ztex-1.1/examples/usb-fpga-1.2/ucecho$ java -cp UCEcho.jar UCEcho
FPGA configuration time: 1353 ms
Enter a string or `quit' to exit the program: Hello world!
Send 12 bytes: `Hello world!'
Read 12 bytes: `HELLO WORLD!'

Enter a string or `quit' to exit the program: quit
Send 4 bytes: `quit'
Read 4 bytes: `QUIT'


[Home]  [Impressum]   
© ZTEX GmbH