Go Back

Source code

Details

Name: wishbone_spi_flash_interface
Created: Sep 2, 2013
Updated: Sep 7, 2013
SVN Updated: Sep 7, 2013

Other project properties

Category: Memory core
Language: VHDL
Development status: Beta
Additional info:
WishBone Compliant: No
License: LGPL

Description

This module uses an interface to SPI serial FLASH memory devices to allow reading/writing/erasing of the FLASH. It includes a state machine that coordinates many of the required commands automatically, to make the process of reading and writing SPI FLASH appear as though a simple RAM is being used. Moreover, the state machine has an initialization mode which can read bytes out of the selected SPI FLASH device and present them on an 8-bit parallel output port. This initialization mode can be set up so that the module takes action immediately after reset, reading the SPI FLASH and initializing various registers in the FPGA. This is quite useful for a device that needs to be reconfigurable to behave in different ways upon power up, without actually resynthesizing the basic design.
This project was tested using the ST Micro M25P64 device. Also, the AT25DF641 data sheet was consulted. It should work with many different devices, but so far it has only been tested with the M25P64 device which is used on a Lattice Semiconductor ECP3 "Versa" FPGA development board. It turns out that the M25P64 device has 128 sectors of 64kbytes each, and only about the first 13 or so were being used for configuring the FPGA... So the most of the space in the device is actually available for use!
There are two SPI interfaces the VHDL file "spi_pack.vhd" The first one is a basic interface that can be used with any SPI device really, including things which are not FLASH. The second interface, "spi_flash_sys_init" is the fancy one that provides the memory mapping and system initialization sequencing.
There is a testbench which can be used to exercise the example FPGA design, showing how the initialization commands are sent as characters to the ASCII based "async_syscon" unit to program values from the SPI FLASH into the FPGA registers.
I even wrote a simple SPI FLASH simulator to use in the testbench!
This project attempts to provide a super easy to use interface to a SPI FLASH device by mapping the contents as RAM. However, there are some caveats to remember:
1. The SPI FLASH device can only work with bytes that are provided in ascending order. Therefore, the "RAM mapped" device should be read or written using addresses that increment by one each time.
2. The SPI FLASH write enable (WREN) and page programming take a certain number of clock cycles to send. This makes the very first access longer than the subsequent ones. Reading bytes takes 18 system clock cycles per byte due to the way the SPI clock is generated. Therefore, each "RAM mapped" SPI FLASH access cycle has an acknowledge signal which indicates when the access is completed, and the cycles can be longer or shorter, depending on what is happening with the SPI FLASH. For example, the very first write cycle includes the WREN command, then the Page Program command, then the address is sent, and then the first data byte. This means that the first write cycle takes many clocks to finish. But subsequent bytes written only take 18 system clocks.
3. There is a timer in the state machine, which is used to decide when to terminate the command session to the SPI device. So, for example, if read cycles keep coming, the timer is continuously reset. However, when reads are no longer issued for a given number of milliseconds, then the state machine terminates the read command. The next read cycle will then take longer because a new read command must be initiated, and the address must be sent again. The number of milliseconds used for the timeout is adjustable by setting a VHDL generic value.
4. Page writes are only good within the boundaries of a single page, which is 256 bytes. You can start writing at any address within the SPI Flash address space, but as the address crosses the page boundary, it will "wrap around" to the beginning of the page. So when programming the device, do it in blocks of 256 bytes or less, with time in between each to allow for the programming to complete.
5. Sector erase operations must be done through the registers, and they can take a long time, like maybe up to a second!
Sounds complicated, right? Well, this project *does* make it somewhat easier, since the state machine sequences through the needed commands for you automatically, so your project doesn't have to. Hopefully it will prove useful to others, as I have certainly enjoyed making it.
The design was tested at a system clock frequency of 50 MHz. It might work faster, but some SPI FLASH devices are limited in their interface speed anyway. So, try it out. Let me know if it works for you.
There is a good "comments" section in the code to describe the registers and what they do. Unfortunately, there is currently no other documentation provided.