Skip to main content

How to program SPI flash memory on Digilent Nexys4 and other 7th generation devices using Vivado 2014.x

Update: The methods described below work also on Vivado 2015! Please let me know if you had any issues with other Vivado versions.

The information in the official user guides and tutorials seems to be fragmentary and sometimes out-of-date, that's why I decided to fill in this gap, not waiting for the official Xilinx updates. Our goal is to show how to program the SPI flash memory of the 7th generation Xilinx devices with Vivado 2014 on example of Nexys4 board.

Note: before we start, we assume you already have a working project, that means the generated bitstream file works on your device. If not, you may want to go directly to the Program the SPI flash section to test your Nexys4 board with prepared .mcs file.


  1. Configure the hardware to work with SPI flash memory
  2. Regenerate the bitstream file
  3. Convert the bitstream file into the "Prom" format
  4. Program the SPI flash
  5. Boot the device

Configure the hardware to work with SPI flash memory

Open the synthesized or implemented design and then open the Edit Device Properties dialog from the Tools menu. Select the Configuration on the left and on the right under the SPI Configuration group set the Bus width equal 4. Now, switch to the Configuration Modes (on the left) and set the checkbox corresponding to Master SPI x4. Note, if you set Bus width equal 2 (or 1), then you would check the Master SPI x2 (or x1), corresponding to the bus width you have previously selected.
UPDATE Alternatively you may edit your constraints (.xdc) file:
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]

Regenerate the bitstream file

This step is not quite obvious and it not mentioned in the documentation, but all you need is just to run the Generate bitstream command again.

Convert the bitstream file into the "Prom" format

The file to program SPI flash memory has different format than .bit. In fact, the first one (called "Prom" in the ISE suit) is an ASCII text, while the last one is a binary file. In Vivado 2014 it is a file with .mcs extension, and it is generated by the Tcl write_cfgmem utility [5]. This step may cause the biggest difficulty if you are a reader of the generic user guides since you need to figure out yourself all the configuration for your device. The key arguments of the write_cfgmem utility that often differ from device to device are the interface and size. For the Nexys4 device a spix4 interface usually will work. Size is in megabytes and depends on your SPI chip capacity, which is usually written on chip in megabits. Therefore, size is the capacity in megabits written divided by eight. For instance, if you have a FL128... chip, then the size will be 16 (MB).

Now, open the Tcl console (in the left bottom tab of your workspace) and type

write_cfgmem -format mcs -interface spix4 -size 16 -loadbit "up 0x0 ./your_path/project_1.runs/impl_1/some_name_top.bit" -file main.mcs

Hint, if the utility outputs an error that the .bit file does not exist, you may check your working directory. Alternatively, you may write a global path, i.e. /home/user/Nexys4_proj/project_1.runs/impl_1/some_name_top.bit
(or on Windows machine it would be something like C:\Nexys4_proj\project_1.runs\impl_1\some_name_top.bit).

If everything went successfully, you will find the .mcs file in your working directory. Vivado uses the directory you run it. For pure GUI users, it is usually the default directory when you click the Open Project icon.

Program the SPI flash. Boot the device

Here is a small bonus for the Nexys4 owners, a prepared main.mcs file with the parameters from the previous section you may want to test your Nexys4 board with. Here is also the disclaimer. The file is based on the example 34 from the Digital Design Using Digilent FPGA Boards. Basically, it is a 4 bit multiplier. Use the right-most 8 switches to enter the two 4 bit numbers. The result of multiplication is a hex number displayed on the two right-most 7-segment LEDs.

Actually the last two steps are well documented in the Vivado Programming User Guide [1]. To recap, open target in the Hardware Manager. Then, if it succeeded, right click on the target (i.e. on xc7a100t_0) and select the Add Configuration Memory Device. There you have to choose your part (in the case of Nexys4 it can be s25fl128sxxxxxx0). After you click OK, you can confirm that you want to program the configuration memory device (or any time right click on the configuration memory part and select Program Configuration Memory Device). There, you have to select your configuration file (the main.mcs). I also prefer to choose the Entire Configuration Memory Device as an Address Range. Other options Erase, Program and Verify are also useful, so you are advised to select them. State of non-config mem IO pins is usually Pull-none. Then, OK... It will take quite a lot of time, so be patient.

And finally, to boot the device, right click on the target and Boot Device. But before, do not forget to set the JP1 on the QSPI position on your board. Enjoy!


You may also like...

Want to learn more about neural networks? Check out this post.


Post a Comment

Please be relevant, helpful and nice.

Popular posts from this blog

How to fix 'ImportError: cannot import name QtCore' on Debian Linux

What to do if such import error occurs? >>> import PySide >>> from PySide import QtCore Traceback (most recent call last):   File "<stdin>", line 1, in <module> ImportError: cannot import name QtCore 1. Try to locate where your pyside is installed: $ locate PySide ... /usr/lib/python2.7/dist-packages/PySide /usr/lib/python2.7/dist-packages/PySide/ /usr/lib/python2.7/dist-packages/PySide/__init__.pyc /usr/lib/python2.7/dist-packages/PySide/ /usr/lib/python2.7/dist-packages/PySide/ /usr/lib/python2.7/dist-packages/PySide/ /usr/lib/python2.7/dist-packages/PySide/ /usr/lib/python2.7/dist-packages/PySide/ ... Hint: use this to update your file index: $ sudo updatedb 2. The solution is easy: add this to your ~/.bashrc (or ~/.<shell>rc you actually have). export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/python2.7/dist-packages/PySide

Inkscape extension example

Recently, when preparing figures for publications using Inkscape, I decided to simplify my life. Some of the figures can be described as 2x2, 2x3, or even 2x6 grids. Sometimes it is very awkward to rearrange them if you decide to switch from 2x6 to 3x4 or vice versa. It would be nice to have an Inkscape extension, which will minimize the efforts. For the sake of simplicity we assume that all the elements are equal in width and should be rearranged symmetrically with respect to the vertical axis. Also, the element should be ordered according to its relative to the other elements location. The top left element is the first and the bottom right is the last one. So for example, you can visually prepare the elements and then tidy them up with a single click of our magic button. Hint : before developing a similar extension, you may want to check the standard Align and Distribute tool (Ctrl+Shift+A). Before writing any actual code let's take a look at some official Inkscape extensio