Flash interface for XEM6001 vs. XEM7001


Due to the end-of-life announcement for XEM6001 we are in the process of migrating to XEM7001. We want to keep the exact same functionality and have basically just replaced the constraint file.

In the first test there seems to be a problem with the flash memory interface. According to the specification, the flash circuit should be the same on XEM7001 as on XEM6001, a Numonyx M25P32-VME6G.
We use the flash to store system settings, but only sector 32. I don’t think the bit-files for XC7A15T are so much larger that there should be any conflict with this sector, right? Furthermore, we don’t even use the flash to boot the FPGA, the JP5 switch is in the USB position.

In the constraint file the four flash pins are set to LVCMOS33 and mapped accordingly:
set_property PACKAGE_PIN L12 [get_ports {spi_cs}]
set_property PACKAGE_PIN M6 [get_ports {spi_clk}]
set_property PACKAGE_PIN N9 [get_ports {spi_din}]
set_property PACKAGE_PIN P9 [get_ports {spi_dout}]

We use flashloader.bit to write the flash, but with our own SW instead of flashloader.exe, starting at address 8192 (32 sectors x 256 pages = 8192). To read the flash we use our own HDL.
This has always worked perfect on XEM6001 but for some reason not on XEM7001. Has anything changed regarding the flash, either in the API or in the SPI?

Best Regards,

Hi Kenny,

The only thing that might have changed (depending on when you purchased either XEM) is the flash could be an ISSI IS25LQ032B-JLLE instead of the Numonyx flash. However, they are equivalent. Could you provide any more details on your implementation and the behavior you are observing to help narrow down the issue? One thing I noticed is that the XEM7001 has a FrontPanel HDL signal called hi_aa that the XEM6001 doesn’t require.

I loaded a text file with some data at various sectors, and was able to read it back on a XEM7001 with Numonyx and ISSI flashes.

Just to confirm, you are using the appropriate flashloader.bit for the XEM7001 located in FrontPanelUSB\bitfiles, correct?

Hayden, thanks for your reply!
Great to know that there are no major differences and that you have got the flash to work without any special adjustments :slight_smile:

I forgot to mention that I had added the new hi_aa signal and included it in the okHost instance:
set_property PACKAGE_PIN M15 [get_ports {hi_aa}]
set_property IOSTANDARD LVCMOS33 [get_ports {hi_aa}]
okHI : okHost port map (hi_in => hi_in, hi_out => hi_out, hi_inout => hi_inout, hi_aa => hi_aa, ti_clk => ti_clk, ok1 => ok1, ok2 => ok2);
That should be enough, right?

Yes, we have changed to the XEM7001 flashloader.bit file.

I’m only responsible for the HDL development while a colleague is implementing the SW and perform testing. We are working in different cities so I don’t have access to the HW and he’s currently occupied with other tasks, so it will probably take at least one week before I can come back with more information about the experienced behavior.
If we manage to solve it I will report what the reason was :slight_smile:

Me and my SW colleague have struggled quite a lot with the flash memory and finally we found the problem!

First, since Hayden pointed out that there could be different flash models we checked this and found that our XEM6001 have Numonyx while the XEM7001 has an ISSI. Even though they are supposed to be equivalent we checked the datasheets and found out that the read data is stable on rising clock edge for Numonyx but on the falling edge for ISSI.
However, in our case the read clock is quite slow and due to the time margin this turned out to have no effect in our implementation, but might help someone else :slight_smile:

The problem we experienced was the worst kind; it worked “sometimes”. After hours of testing different operation sequences, data, and addresses; this was our basic conclusions:

  1. It works if starting to write at address 0, then the full memory may be written with valid data in a long sequence.
  2. If the start write address is in another location, the data is sometimes valid but often fully or partly corrupted.

Any guess what caused this? If you want to figure it out, then stop here to think before reading the spoiler a bit further down :wink:

Naturally, our first thought was that the problem must be our own reading functionality. So we tried to push this part to the limits by jumping back and forth between memory addresses, and these results were always consistent.
Furthermore, we have two different read operations; one where we read one page and send the result as a message through an okPipeOut component and one where we only read 4 bytes and set in registers (okWireOut), which both give the same data.

So then we were quite sure that the root cause unexpectedly must be within the write operation. After even more tests we finally found out that the errors more specifically came from the erase operation!

In XEM6001 we only used sector 32, starting at address 0x200000. It then worked to activate the erase in any single sector:
m_pXEM->SetWireInValue(0x00, address); // Send starting address
m_pXEM->SetWireInValue(0x01, nbrsectors); // Send the number of sectors to erase
m_pXEM->UpdateTriggerOuts(); // Makes sure that there are no pending triggers back
m_pXEM->ActivateTriggerIn(0x40, 3); // Trigger the beginning of the sector erase routine

For some reason this does not work with XEM7001. Do we need to change something in these function calls?
As I mentioned in my first post, we use flashloader.bit to write the flash. So my guess would be that’s where the actual error is… Can anyone confirm?

Since it works to erase the whole flash (address = 0 and nbrsectors = 64), or as far as you want as long as you start from address 0, this is a simple workaround. But there could of course be situations when it’s not suitable to erase everything before the actual write position, so it would be nice with a solution to this issue :slight_smile:

Best Regards,

Please contact support@opalkelly.com.