I have a Max1000 development board and would like to perform a remote system upgrade with it. I have programmed an SPI interface to send the required data. (Here not necessarily SPI must be used, but I think another interface does not change my problem). Now I want to program the RSU without the Nios. I have gotten to the point where I need the dual boot ip core to configure the "dual compressed image". An onchip-Ram to store the necessary data and an onchip-Flash to write to the CFM. But here my flash has only an address size of 17 bits, but to rewrite the CFM the address must be at least 18 bits.
Am I missing something here? Is it possible to rewrite the CFM with SPI like this?
Thanks for the example project. I found an answer to my question, however I don't quite understand why? You write in line 854 that the maximum address is 13ffh (79871). In the Platform Designer it says under Flash Memory that the largest address is 0x4dfff (319487 or 8*79871 - 1). Why do you divide the addresses by 8? Furthermore I don't understand your page_erase_addr in line 740. Of course you take 19 bits, because there is so much space in the register. But why do you start counting up in the middle?
2. Page erase operation at below the line ~740 is just UFM erase. Actually you can add here CFM sectors as well but I done CFM sectors erasing in sector erase mode. As you can see in UFM user guide (https://www.intel.com/content/www/us/en/docs/programmable/683180/18-0/ufm-and-cfm-array-size.html) 10M08 devices has 8+8= 16 pages in UFM sections. If you look at the flash ip, you can see that UFM sectors are between 0 and 0x07fff. It is normal sector addressing. It means approximately 0 - 0x2000 in avalon addressing and that is equal to 0-8192 bits. So we have 16 pages total, then one page's address is 8192/16=512 in avalon addressing. For this reason I increase the UFM page erase addresses by 512 for each page of UFM. I hope it doesn't confusing. In fact it is hard to understand that addressing and documentations about it is very poor.
@jozephka99 Why is it ok to start programming the flash data from either address 0xAC00 or 0x2000, based on the addresses shown in the Flash IP configuration, while the addresses shown in the .map file are a bit higher? In the map it shows 0x8800 as start of CFM1, so 0x2200, and 2B800 as start of CFM0, so 0xAE00.
This is based on your lines 373 - 378 from the file manual_rsu.vhd. I'm guessing your code works, so it is correct to use the addresses of the Flash IP block and not to use the .map information.
It is because the actual data -that differs from 1's- in that .rpd file begins from 0x8800 (0x2200) (CFM1) and 0x2B800 (0xAE00) (CFM0). Data before this addresses is full of "FF"s that is default value of OC RAM. (You can see that if you open the .rpd file with a HEX editor.) .map tells us that you don't have to change these addresses because you already erase the OC RAM before writing it and they are already in the default values. So you can either begin from addresses that shown in IP core like me, or you can use .map addressings. But I think .map addressings can change and it is not that easy to do it in dynamic way.
That's weird. Are you using Platform Designer? I'm guessing yes. Are you just exporting the Avalon interface out of the system and then connecting your control mechanism to it externally? What are you using for control if not Nios?
Yes, I am using the Platform Designer. I put the onchip-flash, onchip-memory and dual_boot in a Qsys file and added it to the project. I link the signals externally. I'll add a scrrenshot of it.
I would like to implement the RSU not with the Nios, but with an own logic circuit. So that I write the VHDL code myself to read and write the register and read from the flash or write on the flash. I could already read the register and got the expected data. It should not really change my problem if the Nios or something else is connected, because it does not increase the size of the addresbus from the onchip flash.
This is how a part of my interface to the onchip flash should look like then. I read the register, then I write in the register the command to clear a page and wait until the bit in the register is set that the clear was successful. But no matter how that looks, it shouldn't change my problem.
-- -------------------------------------------------------------------------------------
-- erase Page or sector
-- -------------------------------------------------------------------------------------
procedure register_erase (
i_data_register : in std_logic_vector(31 downto 0)) is
begin
CASE operation_register IS
-- 1. read in which mode flash is
-- 2. write erase command in register 0x01
-- 3. Check register 0x00 wheather erase was sucessful
-- 4. reset register 0x01
WHEN mode_start =>
onchip_flash_register_addr <= '0';
onchip_flash_register_read <= '1';
IF count_flash <= 5 THEN
count_flash <= count_flash + 1;
ELSE
IF onchip_flash_register_readdata (1 DOWNTO 0) = "00" THEN
-- Flash is in IDLE mode
operation_register <= mode_write;
count_flash <= 0;
ELSE
-- Flash is busy
count_flash <= 0;
count_error_flash <= count_error_flash + 1;
END IF;
END IF;
WHEN mode_write =>
onchip_flash_register_read <= '0';
onchip_flash_register_addr <= '1';
onchip_flash_register_write <= '1';
onchip_flash_register_writedata <= i_data_register;
-- wait a few ns to write in register
IF count_flash <= 10 THEN
count_flash <= count_flash + 1;
ELSE
count_flash <= 0;
operation_register <= mode_check;
END IF;
WHEN mode_check =>
onchip_flash_register_read <= '1';
onchip_flash_register_addr <= '0';
onchip_flash_register_write <= '0';
-- wait a few ns to read from register
IF count_flash <= 10 THEN
count_flash <= count_flash + 1;
ELSE
IF onchip_flash_register_readdata (4 DOWNTO 4) = "1" THEN
-- erase was sucessful
count_flash <= 0;
count_error_flash <= 0;
operation_register <= mode_reset;
ELSE
-- erase wasnt sucessful
count_flash <= 0;
count_error_flash <= count_error_flash + 1;
operation_register <= mode_write;
END IF;
END IF;
WHEN mode_reset =>
onchip_flash_register_read <= '0';
onchip_flash_register_addr <= '1';
onchip_flash_register_write <= '1';
onchip_flash_register_writedata <= x"FF800000";
-- wait a few ns to write in register
IF count_flash <= 5 THEN
count_flash <= count_flash + 1;
ELSE
count_flash <= 0;
operation_register <= mode_start;
operation_flash <= mode_wait;
onchip_flash_register_addr <= '0';
onchip_flash_register_write <= '0';
END IF;
WHEN OTHERS =>
operation_register <= mode_start;
END CASE;
end register_erase;
You're exporting everything out of the system, so you're not really building a system. If you make connections in the system without exporting and set proper addressing, the tool checks and makes sure everything in the interconnect is set up correctly and this might fix your issue.
I want to lead the signals out of the system to be able to set them manually. Just like jozephka99 did in his example. You can use only one nios in the system itself to set them? Or is there another alternative?
How interesting. The topic is Remote System Upgrade via SPI
However everybody switched to UART... May I make offtopic question and ask about discrete RSU via SPI (or I2C)?
From the very starting point - which IP block should I use for it?
The part I'm using is 10M08 with Verilog. I can translate from VHDL to Verilog, but original Verilog code is preferable.
There is a page with example for RSU via I2C but it does not help. Opening .par file shows only top file for 10M50 used as a I2C host. Structure of the project and used IP blocks are invisible
Besides the description of the project and how to run written for Quartus 16 and for a template it suggests to use an evaluation board that does not exist anymore.