====== 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() );
}
}
}