FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6056 Discussions

MAX 10 - Erase CFM sector - IP states "successful" yet sector not erased


I'm in the process of building remote system upgrade functionality for my MAX10. In contrary to the examples I can find, I do not want to use the NIOS II processor and my design must be VHDL only.


In my current phase, I'm trying to erase a sector of the CFM, as the on-chip flash memory guide states it's better to first erase a sector and then to re-program it. 


After creating my own Avalon MM master to connect to the csr slave of the on-chip flash IP block, I was able to figure out some issues through simulation. In the simulation waveforms, I can now see the IP block setting its busy bits and setting its "erase successful" bit once done.

However, when I program my design in my MAX10 development board and execute it, the sector is not erased.

Test procedure:

1) upload my design.

2) hit a button to start the erase

3) once I see, through LED, the erase has happened and the IP block reports "successful", I powercycle my board (= disconnecting USB cable and then reconnecting it).


I would then expect the flash sector to be empty and hence my MAX10 doing nothing, as it can't find a design. However, after the reconnect, my MAX10 boots the design again. This thus shows the sector was not erased, despite the "successful" bit of the IP block.


Any pointers to start figuring out what is wrong or what I'm missing? 

Attached are the settings of the FLASH IP block, my platform and the VHDL code of my Avalon MM master. 


PS: I found 2 other post seemingly having the same problem, but theirs was solved by signal connections. I believe my connections to be correct as the simulation (and actual hardware) provide the expected signals/waveforms.

0 Kudos
18 Replies
Honored Contributor III

Sanity check question: is your control register address at 100 because of byte addressing?

I see nothing in your code for checking waitrequest.  You have the input signal, but you haven't coded for it.  You mention a "busy signal".  Is that supposed to be waitrequest?  Edit: no, you're talking about the busy states of the IP.  Nevermind.

Waitrequest could certainly be your problem.  Have you set up Signal Tap yet to test while running in hardware?


my address is at 100 because that's the only way I got a response. Although the manual states that status and control register are on address 0 and 1, the platform designer put the address range for the csr interface on 0x0 to 0x7. But when I actually used '000' and '001' as addresses, nothing happened. In the spirit of "why not try this" I changed the bit to set the address and "100" worked. No idea why that works.


The waitrequest signal is only there because an avalon MM master needs it, but the CSR interface doesn't have a waitrequest signal. So I don't think I have to look at it, for the CSR interface. I indeed meant the busy state of the IP. 


I have not set up Signal Tap yet. I'll look into it and try to find a manual. If you have a correct manual to set this up, please share  

I did investigate some signals through available LEDs and those seemed alright. But hey, something is clearly wrong, so I'll investigate the signal tap.


In any case, the weird thing is the "erase successful" bit is clearly set in simulation and in hardware (again, seen through LED), yet nothing seems to be erased...

Honored Contributor III

The address needs to be 100 because hosts (previously referred to as masters) use byte addressing.  As such, you have to increase the address by 4 to get to subsequent 32-bit registers in the agent (previously referred to as slaves).

Just because you don't see waitrequest on the agent side, in a Platform Designer system, waitrequest is required on the host side.  The interconnect controls it if it is not present from the agent.  address and waitrequest are the only required Avalon signals for a host.  All the others are optional depending on the types of transfers you want to support.  Without waitrequest checking, you have no guarantee that that "erase successful" bit read is valid or not.

The Signal Tap online trainings were just updated.  They'll link you to the debug tools user guide.  Start here:



New Contributor II

As mentioned here (https://www.intel.com/content/www/us/en/docs/programmable/683180/18-0/ufm-sector-erase-operation.htm... the maximum sector erase time is 350ms, so you can try adding a delay as a workaround. May be for another reason that if one of the CFM images cannot be erased, FPGA switch to that image and program itself from it. So you must be sure that all 2 images erased successfully.


@jozephka99 wrote:

As mentioned here (https://www.intel.com/content/www/us/en/docs/programmable/683180/18-0/ufm-sector-erase-operation.htm... the maximum sector erase time is 350ms, so you can try adding a delay as a workaround. May be for another reason that if one of the CFM images cannot be erased, FPGA switch to that image and program itself from it. So you must be sure that all 2 images erased successfully.

Since I use the dual-configuration IP block, I know that the FPGA could boot from the other CFM if one is not available. This is, however, not happening as I make sure there is another image in the other CFM, so I can clearly see if it boots from the other (and thus the erase was successful).


I had some simulation progress today. Where previously the wait_request signal never went to '0', I can now see it has a pattern of 2 clock-cycles '1' and one clock-cycle '0'. I forgot to explicitly put the reset_n signal to '0' a few cycles before putting it to '1' for the remainder of the simulation. So I changed my code in a few places to wait for the wait_request to go to '0' once the erase command has started (busy state changed to "01").

This change in code, however, had no consequences in the actual hardware implementation. The "successful" bit is still set, but after a powercycle of the board, the image is still present in the flash. 


So, I guess my final option is indeed figuring out how to setup the Signal Tap and do live debugging, in the hopes this shows what goes wrong. (which is a pity, since the simulation now reports no errors and everything behaves as stated in the manual https://www.intel.com/content/www/us/en/docs/programmable/683180/18-0/ufm-sector-erase-operation.htm... )

Honored Contributor III

Is the successful erase status appearing on a read you perform when waitrequest is low?  That's the only way to know it's valid.

And what you describe is not the proper implementation of waitrequest in a host.  It doesn't have a set pattern.  You can issue a read/write command (address & data signals) at any time, but if waitrequest is asserted, you need to continue asserting the command signals until one cycle after waitrequest is deasserted.  The command is transferred on that cycle and you deassert the control signals after that point.


Don't really have the time right now to figure out that Signal Tap.


Purely as a test, would the following work?

  • just writing 1 clock cycle "disable write protection" of my desired sector ID to the csr_control register;
  • the next clock cycle "disable write protection + set sector erase address" of my desired sector ID to the csr_control register; and
  • then setting csr_write and csr_read to 0, address to 0 and write data to Z or '1'.
  • If I then wait a few seconds and then power-cycle my board, should I then see the sector erased and hence no configuration being present?

Because, as I understand the guide, that's all that really needs to happen to erase a Flash sector. (guide only mentions UFM sectors, but I'm guessing this should work for CFM sectors too). (Agreed, checking busy bit and successful bit and re-enabling write protection are crucial steps going forward. The above is purely as a quick check to just erase the CFM sector)


Extra question: my understanding the guide is correct that to just erase CFM sectors, interaction with the csr interface is enough and indeed no interaction with the data interface is necessary? 

New Contributor II

Let do a CFM erase operation from beginning:


1. In one cycle, set:

csr_write <= '1'

csr_address <= '1'

csr_writedata(31 downto 23) <= "111100000" --Write protection off for all sectors (max: 2 ufm, 3 ufm. Your device may not have all of this but it don't broke the program.)

onchip_flash_csr_writedata(22 downto 20) <= sector_erase_addr; -- "100" for image 0,  "010" and "011" for image 1 (you have to clear one by one for each sector in image 1)

onchip_flash_csr_writedata(19 downto 0) <= "11111111111111111111"; -- rest default


2. In the next cycle, set:

csr_write <= '0'

And wait 350 ms. (Max sector erase time)


3. If you want to erase image 1, go back to first step and set other sector id.


4. Here, your sector must be cleared. You can check it from erase succesfull flag. If you don't have any configuration in the other image you cannot run the fpga if you power-cycle as you said. You don't have to deal with data interface just for clearing. And if you want to check it is really cleared the sector you should read the sector and if it is all FF's then erasing is succesfull.


@jozephka99 That's also my understanding, except that the manual says onchip_flash_csr_writedata(22 downto 20) "101" for image 0 (sector 5) and "100" and "011" for image 1 (sector 4 and sector 3). 

Anyway, I also tried this, no luck. Both for the writedata(22 downto 20) addresses mentioned by Jozephka99 and those mentioned in the manual.


I've added my latest project as a zip file. In this latest test, I even just exported the csr interface and manually connected my signals to it.



I hope to find time this week to setup the signal tap so I can see what goes on in the actual FPGA and why this is failing. (or at least gives the impression of failing)


Already many thanks for the different people replying to this topic and helping me figuring this out!

New Contributor II

"timeout" component file missing. So I cannot compile that project. Can you provide it?


@jozephka99 Sorry, didn't see that. It's attached here. 

New Contributor II

I tried your code and either I cannot properly erase CFM sectors. Idk why it needs further investigation but I haven't face any situation like this. I tried several things like erasing all 5 sectors one by one, increasing erase delay, changing address bits and power cycle via dual boot core but when the fpga restarts I can see that the image has not erased. May be the erase operation cannot work because the core is busy. UFM user guide says: "Note: The IP core only accepts the sector erase address when it is in IDLE state; busy field at status register is 2'b00. If the IP core is busy, it will ignore the sector erase address.". You should check this I think.


Another issue that I noticed that, when I use programmer, I erase all sectors first then only write one of the 2 CFM sections, FPGA works and when I switch the other CFM image with dual boot core, FPGA works from other CFM image that I haven't load to FPGA. I use this techinque before with 10M08 and 10M04 devices and normally it shouldn't switch the other CFM because I erased it. Comes to my mind that even programmer cannot erase the CFMs but I don't sure. An addition to that, for example I switch the other CFM with dual boot core and then erase all sectors with programmer then load only one CFM that the opposite of switched one, The FPGA works from switched CFM image that is also wrong. 


@jozephka99  Thanks for trying out my code. I also already tried all options you mentioned there, without any success. You're right, I do not check for the IDLE state of the IP core. However, when I disable the write protect and then put the sector erase, I do see the BUSY state and after a (very) short while, I see the ERASE SUCCESS bit. This would assume the core has accepted the command and thinks it executed successfully?


I can erase sectors with the programmer, so the issue you're describing regarding the programmer, I do not have.


I think I figured out the signal tap, and it showed me the same signals as both the simulation as the ones I route to my LEDs. So it does set "BUSY" and after a (very) short while it sets the "ERASE SUCCESS" bit. Nothing is cleared, however. 
To be sure, I'll re-do the signal tap in several configurations later this week to make sure the signals I read out are correct.


Reading the manual over and over, and reading the comments here in the thread, I'm more and more convinced my VHDL code is correct. (Or at least is implementing the necessary steps). So that makes me wonder if it is the development board that is not letting me erase the CFM. So I'll see if somewhere another board is in stock and I can try that one. Or are there some settings that are not mentioned anywhere that must also be set/altered? 


In the mean time, any other tips or steps I can try in order to get the CFM erased? Is manually writing 0's to each possible address in the CFM address range in option, to "fake" an erase? (although that will probably take a long time). 

New Contributor II

I use DE10-Lite board which has same FPGA model as your project for testing your code. But before I use MAX1000 (has 10M08) and 10M04 FPGAs and success the RSU operation (erase, rewrite and switch images). May be you can try different FPGA model as you said.


As comes to "fake" an erase, unfortunately it is impossible. Because when erasing, writing "1" to all bits and you can not change "0" to "1" manually. You can just change "1" to "0". But you can try page erase operation. May be it works.


Thanks. I just ordered 2 MAX1000 at VHDPlus, so once they arrive, I'll try those. 


@jozephka99 I found some code (by you?) at community.intel.com/t5/FPGA-SoC-And-CPLD-Boards-And/Max1000-Remote-System-Upgrade-via-SPI/m-p/1368963#M22012 . Can I use this code as an example for RSU on a MAX1000 device?

New Contributor II

Yes, of course. It's a bit complex but you can get it I think.


My Max1000 came in the mail yesterday, just tried the simple code in this thread here to erase CFM0. Instant success! 

Thanks for pointing me to this dev. board.


I'm guessing there is either a flaw in the 10M50 that did not enable/allow flash erase or either in the T-Core Terassic dev. board I was using. 



Now I can gradually enhance the functionality and get to a working RSU.

Thanks all involved!