Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Programming Digilent Nexys 2 from Linux

329 views
Skip to first unread message

Andy Ross

unread,
Mar 30, 2009, 7:46:23 PM3/30/09
to
I recently bought a Digilent Nexys 2 board, and after a few days of
research got to the point where I can successfully program it over USB
from a Linux host without the use of a separate (and expensive!) JTAG
interface. Google told me even before I purchased the board that this
is a very common requirement; it seems that I'm not the only one
interested in linux-hosted FPGA development. The pieces to make this
work were all there, happily (see the README in the download below for
details -- the chain of responsibility here is long); it just took
work to assemble them correctly.

For those interested, I wrote a quick perl script to automate the
process, available at: [url]http://plausible.org/andy/nexys2prog.tar.gz
[/url]

This wraps the multi-step mess (device detection/configuration, SVF
generation, and JTAG download) as fully as possible, most importantly
by doing the USB bus enumeration and dynamically reprogramming the
Nexys 2 with a patched usb_jtag firmware blob in the script itself.
The user just specifies the Xilinx bitstream file as the sole
argument.

Installation is as simple as I could make it, requiring only Xilinx
ISE, two binary packages (fxload and libftdi -- both available via apt-
get on Ubuntu Intrepid) and one source install (UrJTAG -- just a
simple "./configure;make;make install" will do).

Hopefully this will help other newbies with the learning curve. Let
me know if something doesn't work, or if there are questions.

emeb

unread,
Mar 31, 2009, 7:42:56 PM3/31/09
to

Thanks for putting that together! I've been googling unsuccessfully
for all that info since buying my Nexsys 2 a few months ago. derp derp
derp.

Eric

Ronan Paixão

unread,
Apr 1, 2009, 5:23:13 PM4/1/09
to

That's great! Any idea if that works for a Nexys (not version 2)? I'm
trying to get it working but so far I wasn't able to. The program
detects if the cable is present or not, and appears to change the
board's firmware somehow, since until the board is powered down, its
lsusb output changes from:
Bus 007 Device 033: ID 1443:0005
to:
Bus 007 Device 034: ID 16c0:06ad VOTI
but the program doesn't show anything else.

Do you have any idea of what's happening, since it appears both the
nexys 1 and 2 have the same programming interface?

Andy Ross

unread,
Apr 1, 2009, 6:12:11 PM4/1/09
to
On Apr 1, 2:23 pm, Ronan Paixão <ronanpai...@yahoo.com.br> wrote:
> Do you have any idea of what's happening, since it appears both the
> nexys 1 and 2 have the same programming interface?

The script was written specifically for the Nexys 2, as obviously
that's all I have available to test with and I'm still new enough at
this stuff (FPGA work, not software development, that is) that I'm
more likely to hurt things than help by guessing at inappropriate
abstractions. But looking really briefly at the schematics, it seems
like it should work in principle. The JTAG pinout on the FX2 chip
looks identical, and obviously you're seeing the firmware reload work
successfully.

First off, run the script with a "-v" to enable verbose mode and see
what the underlying error is.

The one thing I see that will need to be changed is the path to the
BDSL files on line 236; the Nexys has (I think) a Spartan 3, not a 3E,
and Xilinx spreads these files out all over their tree. Try this:

--- nexys2prog
+++ nexys2prog
@@ -233,7 +233,7 @@
sub play_svf {
open JTAG, ">$TMPID.jtag" or die "cannot write to $TMPID.jtag";
# Just the BSDL directories needed for the 2 chips on the
Nexys2...
- print JTAG "bsdl path $XILINX/spartan3e/data;$XILINX/xcf/data\n";
+ print JTAG "bsdl path $XILINX/spartan3e/data;$XILINX/spartan3/
data;$XILINX/xcf/data\n";
print JTAG "cable usbblaster\n";
print JTAG "detect\n";
print JTAG "part 1\n";

Another potential gotcha is that the iMPACT script generator is
specifying an XCF04S and not the 02 part that seems to be on the
Nexys. But as this is just being fed a bypass command, I can't see
why it would matter. And now that I'm understanding JTAG better, I'm
not sure why this chip needs to be specified at all just to generate
SVF, when the real bypass command is actually done by UrJTAG at
runtime...

Let me know how things work out. Now that I have a better handle on
things and am getting out of the "blind stitchwork" phase, I'm
starting to think about nicer interfaces. One thing to note is that a
Xilinx bitstream file embeds its part identifier, so there's really no
need to know anything about the board design a priori -- we could just
scan the JTAG bus for a matching part number, regardless of where it
lives on the chain, and program that. Likewise extending the FX2
interface to handle other known FX2 parts (the KNJN Saxo boards, which
I almost bought, or the Digilent cable), or even arbitrary JTAG
interfaces that can be detected, is possible.

Then again, the whole point here is to allow me to play with FPGAs and
learn something, not do tool integration that won't teach me anything
new. :)

John Eaton

unread,
Apr 2, 2009, 12:40:40 AM4/2/09
to
Andy,

Sure hope this works. I'm tried of having to reboot into windows to burn
code into my boards.

Does this reprogram the 8051? Does that mean if I use it I cannot go
back and use the digilent adept software?

John Eaton

emeb

unread,
Apr 2, 2009, 1:17:43 AM4/2/09
to
I'm pretty sure that the Digilent 8051 code is loaded from flash at
power-up and this process reloads new open-source code from USB which
is lost at the next power down or reset. You should be OK using this
with Adept as long as you cycle power.

Eric

Andy Ross

unread,
Apr 2, 2009, 11:56:14 AM4/2/09
to
emeb wrote:
> I'm pretty sure that the Digilent 8051 code is loaded from flash at
> power-up and this process reloads new open-source code from USB
> which is lost at the next power down or reset. You should be OK
> using this with Adept as long as you cycle power.

Yes, that's exactly right. The FX2 chip has a built-in loader that
works irrespective of what the boot configuration was. Once the
device reboots (you have to unplug it from the USB bus, it's not
controlled by the FPGA power switch) it restreams its firmware from
the I2C EEPROM and acts like a Digilent device again.

It should be noted that I've only done the integration work here.
There were *lots* of people involved in making this work. Here's the
relevant section of the README in the package. (One credit that I've
since realized I missed is that the usb_jtag firmware is itself based
on similar 8051 code from the GNU Radio folks).

Xilinx, of course, provides a Linux version of their free (as-in-
beer)
ISE WebPack product [1]. But Digilent uses a proprietary protocol
for
their USB interface, and they neither document it nor provide tools
other than a (decidedly clunky) Windows GUI [2] to use it.

Nonetheless the USB hardware on the device is open. The Cypress FX2
USB chip on the board, which itself is a 8051 microcontroller, is
fully programmable from across the USB bus [3] and that interface is
supported from linux thanks to the work of the linux-hotplug project
[4]. The sdcc project provides a free C compiler [5] for the 8051,
which Kolja Waschk used to write a firmware suite named
"usb_jtag" [6]
for a FX2-based USB/JTAG cable that allows it to be used as a
compatible replacement for an Altera USB Blaster -- a cable based on
a
different USB interface part from FTDI, which is supported under
linux
by the libftdi project [7]. The UrJTAG project [8], which is a
currently-maintained fork of the mostly-abandonware openwince-jtag
project, provides a high level JTAG interface (using libftdi as one
of
many drivers) that can be used to program the FPGA using SVF files
from the Xilinx iMPACT tool. The Nexys 2 board enters the picture
at
last when Sune Mai, in posts on fpga4fun.com [9] and on the UrJTAG
mailing list [10], ported Waschk's usb_jtag firmware to the Nexys 2
by
simply changing the 8051 port assignments of the JTAG pins (the FX2
on
the Digilent board is wired differently than the usb_jtag cable, but
is otherwise compatible) and by fixing a integer overflow bug the
upstream code had with handling large bitstream files. Neither
change
has been merged into Kolja's code, unfortunately.

Finally, Morgan Delahaye-Prat collected the above into a single
walkthrough on his (French) blog [11], providing detailed
instructions
and downloadable files and patches. The language barrier for
non-French-speakers can be surmounted without too much difficulty
via
google's language tools. The Rube Goldberg-like complexity of the
process, however, took much longer to puzzle out and left me with a
tree full of tiny scripts, notes, and patched software trees.

[1] http://www.xilinx.com/ise/logic_design_prod/webpack.htm
[2] http://digilentinc.com/Products/Detail.cfm?Prod=ADEPT
[3] http://download.cypress.com.edgesuite.net/design_resources/datasheets/contents/cy7c68013a_8.pdf
[4] http://linux-hotplug.sourceforge.net
[5] http://sdcc.sourceforge.net
[6] http://www.ixo.de/info/usb_jtag/
[7] http://www.intra2net.com/en/developer/libftdi
[8] http://urjtag.org
[9] http://www.fpga4fun.com/forum/viewtopic.php?p=4779
[10] http://sourceforge.net/forum/forum.php?thread_id=2312452&forum_id=682993
[11] http://www.m-del.net/info.html

Uwe Bonnes

unread,
Apr 2, 2009, 12:06:11 PM4/2/09
to
Andy Ross <andy.r...@gmail.com> wrote:
> emeb wrote:
> > I'm pretty sure that the Digilent 8051 code is loaded from flash at
> > power-up and this process reloads new open-source code from USB
> > which is lost at the next power down or reset. You should be OK
> > using this with Adept as long as you cycle power.

> Yes, that's exactly right. The FX2 chip has a built-in loader that
> works irrespective of what the boot configuration was. Once the
> device reboots (you have to unplug it from the USB bus, it's not
> controlled by the FPGA power switch) it restreams its firmware from
> the I2C EEPROM and acts like a Digilent device again.

I have a modified version of the USRP FX2 firmware and a modified version of
xc3sprog(Linux) to directly programm Spartan3/XCF and XC95XL via a
Bit/Jedecfile. Probably the firmware needs some adapations, as the JTAG Pins
will differ. However I don't have a Digilent adapter available, to someone
interested must do this changes by himself.

Some nearly recent verison is uploaded to the patches section of
xc3sprog at sourceforge.

--
Uwe Bonnes b...@elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------

Andy Ross

unread,
Apr 2, 2009, 3:19:22 PM4/2/09
to
On Apr 2, 9:06 am, Uwe Bonnes <b...@elektron.ikp.physik.tu-

darmstadt.de> wrote:
> I have a modified version of the USRP FX2 firmware and a modified version of
> xc3sprog(Linux) to directly programm Spartan3/XCF and XC95XL via a
> Bit/Jedecfile. Probably the firmware needs some adapations, as the JTAG Pins
> will differ. However I don't have a Digilent adapter available, to someone
> interested must do this changes by himself.

Yeah. With all due respect, though, the "someone needs to make it
work" part is a huge hurdle. There are all sorts of half-solutions
like that floating around the internet in various stages of decay.
Your own xc3sprog patches, for example, are still patches because the
project itself is abandoned. And of course, xc3sprog itself is a fork
of someone else's abandoned work...

I did see your stuff, by the way, but ultimately decided on the UrJTAG-
based solution instead. UrJTAG is actively maintained, works well,
and is more generically useful for anyone working with their FPGA
board than a Spartan-specific C program will be.

Likewise, Kolja Waschk's FX2 firmware seemed cleaner to me. It
emulates an existing protocol (spoken by the FTDI-based Altera
USBBlaster cable) and thus works out-of-the-box with UrJTAG without
modification. And the patches required for it consist only of a few
modified pin assignments and a fix for an integer overflow bug, so
it's easier for me to maintain as part of the script.

Obviously the Right Thing here would be for someone to write a generic
firmware suite for the FX2 (abstracting the JTAG pin assignments
somehow), pair it with dynamic USB device detection and configuration
for all known FX2-based JTAG controllers, and mate it to UrJTAG such
that any bitstream file can be thrown at any JTAG chain with the
expected results.

But I didn't have time (or the device library, or the domain
knowledge) to do that. So instead I wanted to get to a solution that
works well for just one device and requires as little from the user as
possible. That's what this script does.

Uwe Bonnes

unread,
Apr 2, 2009, 6:05:44 PM4/2/09
to
Andy Ross <andy.r...@gmail.com> wrote:
...

> like that floating around the internet in various stages of decay.
> Your own xc3sprog patches, for example, are still patches because the
> project itself is abandoned. And of course, xc3sprog itself is a fork
> of someone else's abandoned work...

That's the history of most open source projects.

> I did see your stuff, by the way, but ultimately decided on the UrJTAG-
> based solution instead. UrJTAG is actively maintained, works well,
> and is more generically useful for anyone working with their FPGA
> board than a Spartan-specific C program will be.

The stuff is in SVN locally.

> Likewise, Kolja Waschk's FX2 firmware seemed cleaner to me. It
> emulates an existing protocol (spoken by the FTDI-based Altera
> USBBlaster cable) and thus works out-of-the-box with UrJTAG without
> modification. And the patches required for it consist only of a few
> modified pin assignments and a fix for an integer overflow bug, so
> it's easier for me to maintain as part of the script.

This will have a hugh inpact on transfer speed

> Obviously the Right Thing here would be for someone to write a generic
> firmware suite for the FX2 (abstracting the JTAG pin assignments
> somehow), pair it with dynamic USB device detection and configuration
> for all known FX2-based JTAG controllers, and mate it to UrJTAG such
> that any bitstream file can be thrown at any JTAG chain with the
> expected results.

Thats a "eierlegende Wollmichsau", doing everything right, but probably
never in time.

> ...

emeb

unread,
Apr 2, 2009, 7:10:06 PM4/2/09
to
On Apr 2, 9:06 am, Uwe Bonnes <b...@elektron.ikp.physik.tu-
darmstadt.de> wrote:

I've got one of the low-end Digilent USB/JTAG cables that uses the FX2
chip at the JTAG end. If you could point me at your app source I'd
like to give this a try.

Eric

John Eaton

unread,
Apr 10, 2009, 5:51:45 PM4/10/09
to
Andy Ross wrote:

>
> Hopefully this will help other newbies with the learning curve. Let
> me know if something doesn't work, or if there are questions.

< bitgen ${PROJ}_par.ncd $PROJ.bit $PROJ.pcf
---
> bitgen $PROJ_par.ncd $PROJ.bit $PROJ.pcf

Andy Ross

unread,
Apr 11, 2009, 11:34:14 AM4/11/09
to
On Apr 10, 2:51 pm, John Eaton <nos...@spam.com> wrote:
> < bitgen ${PROJ}_par.ncd $PROJ.bit $PROJ.pcf
> ---
>  > bitgen $PROJ_par.ncd $PROJ.bit $PROJ.pcf

Good catch. Fixed in the tarball (didn't bother with versioning).

FWIW: your diff order is swapped. And, dude: non-unified diff output?
Raised in a barn?

Andy

John Eaton

unread,
Apr 11, 2009, 3:49:07 PM4/11/09
to

Hate to show my ignorance but what is "unified diff output"? All I did
was to diff the fixed script against the original.

I don't have a nexys2 board but will try to get this working with a
basys and a nexys board.


John Eaton

Muzaffer Kal

unread,
Apr 13, 2009, 2:15:54 AM4/13/09
to
On Sat, 11 Apr 2009 12:49:07 -0700, John Eaton <nos...@spam.com>
wrote:

http://en.wikipedia.org/wiki/Diff#Unified_format

jmi...@gmail.com

unread,
May 15, 2009, 3:09:52 AM5/15/09
to
On Mar 30, 4:46 pm, Andy Ross <andy.ross...@gmail.com> wrote:
> I recently bought a Digilent Nexys 2 board, and after a few days of
> research got to the point where I can successfully program it over USB
> from a Linux host without the use of a separate (and expensive!) JTAG
> interface...

Hi, Andy --

Thanks for posting this Perl script, Andy -- it makes a nice self-
documenting summary of the hoops to jump through. I've been playing
with the same board as well over the past week or so, attempting to
build a C API that's just enough to support standalone PC-hosted FPGA
apps (data acquisition, SDR, and so forth). I'm working in Win32 but
there's nothing really OS-specific about it.

The API is actually running OK in a limited fashion (see below), and
is relatively short and to the point:

int N2LoadFX2Image(CCyUSBDevice *device, char *image, int
image_bytes)
void N2SetFX2ClockMHz(CCyUSBDevice *device, int MHz)
int N2LoadSpartan3EImage(CCyUSBDevice *device, char *image, int
image_bytes)

The whole thing lives in just two C files -- fx2_ctrl.c which sdcc
turns into an image file suitable for passing to the N2LoadFX2Image()
function, and nexys2.cpp which is the USB-over-JTAG host API.

An application built with this API doesn't need any external projects,
libraries, scripts, tools, shells, or whatever. I'm using the stock
CyUSB driver from the Cypress FX2 devkit, which can talk to the Nexys2
if you cut the JP6 trace and install a jumper to disable the EEPROM
that the FX2 normally boots from. (I had problems trying to override
the EEPROM code, hence the need for the jumper to switch between "API
mode" and "Adept mode," and it didn't seem vital to pursue the issue
too far given the jumper pads provided by Digilent.)

I also have it working under the older EzUSB driver from the same
devkit; presumably it wouldn't be hard to support libusb as well.

So: I'm fine with putting the API and its source out there for anyone
else who wants to play with it, but I'm hoping to deal with one
troubling issue first. Currently, JP9 has to be in the ROM (Master
Serial/Platform Flash) position, not the JTAG position, and you have
to use -StartupClk:CClk to build the .bit file. If you set JP9 to
JTAG and use -StartupClk:JtagClk, the .bit upload fails, and the DONE
light never comes on. I don't feel comfortable releasing the code
until I have a better understanding of what's up with that. My
questions come down to these:

1) Regardless of the M2:M0 bits resulting from a given JP9 setting,
I'm still considered to be using "JTAG configuration" as long as I'm
sending the .bit image via the JTAG TAP state machine, correct?

2) Assuming that's true, I understand that the M2:M0 bits are ignored
during a boundary-scan upload... but then, why does -StartupClk:CClk
work OK for JTAG configurations if, and only if, M2:M0 are set for
Master Serial mode (000)? Page 250 of Xilinx's UG332 v1.5 suggests
that it won't work at all -- it's JtagClk or nothing if you're
performing JTAG configuration.

3) Most, but not all, of the Xilinx documentation says that a a
successful upload with the JTAG jumper setting and -StartupClk:JtagClk
requires a JSTART instruction followed by >= 12 TCK ticks after
the .bit image is transferred. I've spent quite a bit of time trying
to get JSTART to do something, following the guidelines in various
Xilinx manuals, with no luck. No state-machine sequences I've tried
have yielded a successful configuration with JP9=JTAG/-
StartupClk:JtagClk.

The JSTART thing bugs me because of how flaky its documentation is.
In fact, newer versions of XAPP058 no longer mention JSTART at all,
while various open-source USB-JTAG implementations still use it with
various chips. I'm fine with including a readme note that says "You
must set JP9 to the 'ROM' position and use -StartupClk:CClk," but
clearly there's *some* way to use the JTAG/StartupClk:JtagClk
technique, since Adept can use it. Any opinions on whether it's safe/
smart to ignore this issue?

Finally, apologies for hijacking your Linux-specific thread with some
lower-level minutiae, but this seems to be a good place to catch the
attention of people who're more familiar with Spartan3E config
topics. Would be nice to hear from anyone with a clue stick.

> Hopefully this will help other newbies with the learning curve.  Let
> me know if something doesn't work, or if there are questions.

More than you bargained for, I'm sure!

-- john, KE5FX

Brian Davis

unread,
May 16, 2009, 1:02:53 AM5/16/09
to
John,

Not a detailed answer ( I don't have a NEXSYS2 board ), but perhaps
some clues you haven't found yet, in these old posts summarizing
similar JTAG vs. mode pin vs. PROM conflicts:

JTAG/mode/PROM configuration problems:
http://groups.google.com/group/comp.arch.fpga/msg/5b79a99163d5282e
http://groups.google.com/group/comp.arch.fpga/msg/b06ca9faf716c347

Digilent Spartan3 ( original, non-E ) JTAG download issues:
http://groups.google.com/group/comp.arch.fpga/msg/8b2144041295cd24
http://groups.google.com/group/comp.arch.fpga/msg/63162b2622926fa9


Random Thoughts:

>
> If you set JP9 to JTAG and use -StartupClk:JtagClk, the .bit upload fails,
> and the DONE light never comes on.
>

Try doing an extra JTAG operation after config ( e.g. read the PROM
ID )

Does JTAG configuration work properly when using :
- Digilent's Adept suite through the USB config port ?
- an external Xilinx ( USB/parallel ) JTAG cable through IMPACT ?

>
> 1) Regardless of the M2:M0 bits resulting from a given JP9 setting,
> I'm still considered to be using "JTAG configuration" as long as I'm
> sending the .bit image via the JTAG TAP state machine, correct?
>

As mentioned in the above links, there are longstanding (and
regularly
recurring ) issues involving dueling configuration modes interrupting
one another and fouling up the configuration and/or FPGA startup
process.

Is there a spare I/O bit on the micro to force the FPGA mode pins
to JTAG during a JTAG download ?

>
> why does -StartupClk:CClk work OK for JTAG configurations if,
> and only if, M2:M0 are set for Master Serial mode (000)?
>

Master mode is the only one that normally generates CCLK from the
FPGA;
CCLK might be turning back on after the JTAG config completes, giving
the
FPGA the extra clocks it needs to finish startup.

>
> The JSTART thing bugs me because of how flaky its documentation is.
>

Have you searched the Answer Records for JSTART and JPROGRAM ?

Xilinx search engine tips:
>
> - Go to the Xilinx webpage
> - click the "advanced search" link (below the search button)
> - enter your search terms
> - check what to search ( answer records, archive, etc. )
>
> Note that although the search terms are filled in again
> on the results page, that is just the plain-old-search,
> not the advanced one; you have to back up to the advanced
> search page again to properly modify your search terms.
>

have fun,
Brian


0 new messages