====== SD card support on FX2 based Series 2 FPGA Boards ====== ZTEX uses the FX3S on its FPGA Boards. These boards have native SD card support (including SDIO). On FX2 based based Series 2 FPGA Boards there is no SD socket. Users that miss it (e.g. because they previously used Series 1 Boards) can easily add a (micro)SD socket to their application circuit. This page described how this is done and how firmware support is activated. This is explained best by an example: A SD card is connected to an [[http://www.ztex.de/usb-fpga-2/usb-fpga-2.01.e.html|USB-FPGA Module 2.01]] as follows | ^ External I/O || ^ FX2 I/O ^^ ^ Signal ^ pin ^ FPGA pin ^ direction ^ pin ^ FPGA pin ^ | CS | B13 | K15 | ← (in) | PC1 | N12 | | DI | B14 | J13 | ← (in) | PC2 | P12 | | CLK | B18 | J14 | ← (in) | PC3 | N5 | | DO | B19 | H15 | → (out) | PA2 | H15 | The HDL code for routing the signals is: # ... NET "pa2" LOC = "B10" | IOSTANDARD = LVCMOS33 ; # PA2 NET "pc1" LOC = "N12" | IOSTANDARD = LVCMOS33 ; # PC1/GPIFADR1 NET "pc2" LOC = "P12" | IOSTANDARD = LVCMOS33 ; # PC2/GPIFADR2 NET "pc3" LOC = "N5" | IOSTANDARD = LVCMOS33 ; # PC3/GPIFADR3 NET "b13" LOC = "K15" | IOSTANDARD = LVCMOS33 ; NET "b14" LOC = "J13" | IOSTANDARD = LVCMOS33 ; NET "b18" LOC = "J14" | IOSTANDARD = LVCMOS33 ; NET "b19" LOC = "H15" | IOSTANDARD = LVCMOS33 ; # ... (.ucf constraints file) and // ... module top ( // ... input pc1,pc2,pc3, b19, output b13,b14,b18, pa2 ); // ... assign b13 = pc1; assign b14 = pc2; assign b18 = pc3; assign pa2 = b19; // ... endmodule (verilog HDL file). In order to enable firmware support the following lines have to be inserted between ''#include[ztex-conf.h]'' and ''#include[ztex.h]'' ENABLE_FLASH2; // enables SD support as secondary Flash #define[MMC_PORT][C] // Port for input signals, valid values: A..D #define[MMC__PORT_DO][A] // Port for output signals (valid values: A..D, // can be omitted if equal to input port) #define[MMC_BIT_CS][1] // Pin number for CS signal, i.e. PC1 #define[MMC_BIT_DI][2] // Pin number for DI signal, i.e. PC2 #define[MMC_BIT_DO][2] // Pin number for DO signal, i.e. PA2 #define[MMC_BIT_CLK][3] // Pin number for CLK signal, i.e. PC3 From the firmware the SD card now can be accessed using the functions ''flash2_read_init'', ''flash2_read'', ''flash2_read_finish'',''flash2_write_init'', ''flash2_write'', ''flash2_write_finish''. The syntax is is the same as of ''flash_read_*'' and ''flash_write_*'' functions. From host software the SD card can be accessed using then functions [[http://www.ztex.de/firmware-kit/docs/java/ztex/Ztex1v1.html#flash2Enabled()|flash2*]] (which are equivalent to the [[http://www.ztex.de/firmware-kit/docs/java/ztex/Ztex1v1.html#flashEnabled()|functions for primary flash]]). Their usage can be explained with ''flashdemo'' example ported to secondary flash. The firmware code is: #include[ztex-conf.h] // Loads the configuration macros, see ztex-conf.h for the available macros #include[ztex-utils.h] // include basic functions and variables // select ZTEX USB FPGA Module 2.01 as target (required for FPGA configuration) IDENTITY_UFM_2_01(10.18.0.0,0); // enable Flash support ENABLE_FLASH; ENABLE_FLASH_BITSTREAM; ENABLE_FLASH2; // enables SD support as secondary Flash #define[MMC_PORT][C] // Port for input signals, valid values: A..D #define[MMC__PORT_DO][A] // Port for output signals (valid values: A..D, // can be omitted if equal to input port) #define[MMC_BIT_CS][1] // Pin number for CS signal, i.e. PC1 #define[MMC_BIT_DI][2] // Pin number for DI signal, i.e. PC2 #define[MMC_BIT_DO][2] // Pin number for DO signal, i.e. PA2 #define[MMC_BIT_CLK][3] // Pin number for CLK signal, i.e. PC3 // this product string is also used for identification by the host software #define[PRODUCT_STRING]["Flash2 demo for UFM 2.01"] __code char flash2_string[] = "Hello World!"; // include the main part of the firmware kit, define the descriptors, ... #include[ztex.h] void main(void) { __xdata DWORD sector; init_USB(); // init everything if ( flash2_enabled ) { flash2_read_init( 0 ); // prepare reading sector 0 flash2_read((__xdata BYTE*) §or, 4); // read the number of last sector flash2_read_finish(flash2_sector_size - 4); // dummy-read the rest of the sector + finish read operation sector++; if ( sector > flash2_sectors || sector == 0 ) { sector = 1; } flash2_write_init( 0 ); // prepare writing sector 0 flash2_write((__xdata BYTE*) §or, 4); // write the current sector number flash2_write_finish_sector(flash2_sector_size - 4); // dummy-write the rest of the sector + CRC flash2_write_finish(); // finish write operation flash2_write_init( sector ); // prepare writing sector sector flash2_write((__xdata BYTE*) flash2_string, sizeof(flash2_string)); // write the string flash2_write_finish_sector(flash2_sector_size - sizeof(flash2_string)); // dummy-write the rest of the sector + CRC flash2_write_finish(); // finish write operation } while (1) { } // twiddle thumbs } and the host software is defined by 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 Device Number (default: 0)\n" + " -f Force uploads\n" + " -p Print bus info\n" + " -ue Upload Firmware to EEPROM\n" + " -re Reset EEPROM Firmware\n" + " -w Enable certain workarounds\n" + " -h This help" ); public ParameterException (String msg) { super( msg + "\n" + helpMsg ); } } // ***************************************************************************** // ******* Test0 *************************************************************** // ***************************************************************************** class FlashDemo extends Ztex1v1 { // ******* FlashDemo *********************************************************** // constructor public FlashDemo ( ZtexDevice1 pDev ) throws UsbException { super ( pDev ); } // ******* main **************************************************************** public static void main (String args[]) { int devNum = 0; boolean force = false; boolean workarounds = false; try { // init USB stuff LibusbJava.usb_init(); // scan the USB bus ZtexScanBus1 bus = new ZtexScanBus1( ZtexDevice1.ztexVendorId, ZtexDevice1.ztexProductId, 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) 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("-w") ) { workarounds = true; } else if ( args[i].equals("-h") ) { System.err.println(ParameterException.helpMsg); System.exit(0); } else if ( !args[i].equals("-re") && !args[i].equals("-ue") ) throw new ParameterException("Invalid Parameter: "+args[i]); } // create the main class FlashDemo ztex = new FlashDemo ( bus.device(devNum) ); ztex.certainWorkarounds = workarounds; // upload the firmware if necessary if ( force || ! ztex.valid() || ! ztex.dev().productString().equals("Flash2 demo for UFM 2.01") ) { System.out.println("Firmware upload time: " + ztex.uploadFirmware( "flashdemo.ihx", force ) + " ms"); } for (int i=0; i0 ); System.out.println(); } byte[] buf = new byte[ztex.flash2SectorSize()]; ztex.flash2ReadSector(0,buf); // read out the last sector; int sector = (buf[0] & 255) | ((buf[1] & 255) << 8) | ((buf[1] & 255) << 16) | ((buf[1] & 255) << 24); System.out.println("Last sector: "+sector); ztex.flash2ReadSector(sector,buf); // read out the string int i=0; while ( buf[i] != '\0'&& i < ztex.flash2SectorSize() ) i++; System.out.println("The string: `" + new String(buf,0,i)+ "'"); } catch (Exception e) { System.out.println("Error: "+e.getLocalizedMessage() ); } } }