Forum Discussion
Altera_Forum
Honored Contributor
11 years agoFPGA memory initialization and management
Hi,
my design is using a cyclone IV on-chip memory. I have two questions (for the moment): - when configuring the memory with qsys, I don't really understand the data-width choice. If it's 32-bit-wide, does it mean a +1 increment in the address will be a 32-bit increment for the data? If I read something at address a, will *a be a 32-bit word? - the initialization could be made by a file. What should I use to edit this file? For example I have an 8-bit words memory, I've tried a hexadecimal editor but when reading it (by a software executed on a Nios2 cpu) it's not what I expect. Thank you for the explanations you can give me.16 Replies
- Altera_Forum
Honored Contributor
The address changes depending on where you are in the design.
1. On an altsyncram component, with 32-bit data width, incrementing the address +1 increments the data by a 32-bit word. 2. Qsys slave addressing is word-based. So, on a Qsys Avalon-MM slave interface, with 32-bit data width, incrementing the address +1 increments the data by a 32-bit word. 3. Qsys master addressing is byte-based. So, for a master accessing an Avalon-MM slave interface, with 32-bit data width, incrementing the master address +4 increments the data by a 32-bit word. The Altera hex editor works fine. I typically create a couple of words in an example file using the hex editor, save it as Intel hex format, and the look at that file relative to the Intel hex standard. For 32-bit words, I'm pretty sure the Intel hex format will be one 32-bit value per line in the file. I then write code (C, MATLAB, or Tcl) to create the hex file. Cheers, Dave - Altera_Forum
Honored Contributor
OK.
I don't use an Avalon-MM but a dual-port RAM in Qsys. One is connected to the cpu, the other is exported so the FPGA design can write on it. I don't know why, but the results don't seem good. For the editor, I don't find it in any Quartus II menu. Where is it? - Altera_Forum
Honored Contributor
--- Quote Start --- I don't use an Avalon-MM but a dual-port RAM in Qsys. One is connected to the cpu, the other is exported so the FPGA design can write on it. I don't know why, but the results don't seem good. --- Quote End --- Read the code and see what it does with the altsyncram address port. --- Quote Start --- For the editor, I don't find it in any Quartus II menu. Where is it? --- Quote End --- File->New, Memory Files, Hexadecimal (Intel-Format) File. Cheers, Dave - Altera_Forum
Honored Contributor
--- Quote Start --- Read the code and see what it does with the altsyncram address port. --- Quote End --- Qsys tells it's an altera_avalon_onchip_memory2, I don't know if it's the same as altsyncram... The address is controlled by a VHDL line:
Tell me if I shouldn't do that. --- Quote Start --- File->New, Memory Files, Hexadecimal (Intel-Format) File. --- Quote End --- Thanks for that. Is the Memory Initialization File better?addr <= std_logic_vector(to_unsigned(tstep, addr'length)); - Altera_Forum
Honored Contributor
I really don't understand what's happening in my design. I give you details:
The hardware part (a Quartus II project downloaded on the Cyclone IV of a de0-nano board) is instantiating a qsys project with a Nios II cpu and a dual-port memory. The cpu can read the memory that can be written by the hardware part. For the moment I don't write anything, the memory (8-bit words) is initialized by a .hex file created as a memory initialization file by Quartus II as showed by this picture: https://www.alteraforum.com/forum/attachment.php?attachmentid=9298 A software is running on the cpu. I give the code:
and the result is: --- Quote Start --- Start! 67305985 67305985 67305985 67305985 134678021 134678021 134678021 134678021 2826 2826 2826 2826 0 0 0 --- Quote End --- I don't understand this. If you can explain what is done, please tell me. Thanks.#include <stdio.h> # include "system.h" int main() { int *pmem; int i=0; printf("Start!\n"); for (i=0; i<15; i++) { pmem=(int *)(0x80000000|(ONCHIP_MEMORY2_0_BASE+i)); printf("%u\n", *pmem); } return 0; } - Altera_Forum
Honored Contributor
--- Quote Start --- Qsys tells it's an altera_avalon_onchip_memory2, I don't know if it's the same as altsyncram... --- Quote End --- Looking at the Qsys GUI is not the same as reading the code. Generate your Qsys system, and then look at the synthesis code. There will be either a component instance called altera_avalon_onchip_memory2 or there will be a file with that name. It will use an altsyncram :) --- Quote Start --- The address is controlled by a VHDL line:
Tell me if I shouldn't do that. --- Quote End --- If the RAM is in Qsys, then you don't get to control it, unless of course you have added a dual-ported RAM to your Qsys system and exported one side of the RAM to the top-level. Either way, this is not enough code to tell what you are doing. Basically it looks like you're converting an integer tstep to a std_logic_vector, but you have not shown how you update tstep. --- Quote Start --- Thanks for that. Is the Memory Initialization File better? --- Quote End --- Better than what? You asked how you can initialize it from file. You can use RAM/ROM initialization files when you want the RAM to contain "something" at power-on, eg., a processor bootloader program. Whether you need an initialization file or not depends on what you are trying to do. Cheers, Daveaddr <= std_logic_vector(to_unsigned(tstep, addr'length)); - Altera_Forum
Honored Contributor
Assuming you have your base address correct, try the following code;
The statement *pmem++ operates as follows; *pmem points to the 32-bit int, so your print statement prints out the value of the integer, and then the ++ increments the pointer by the size of the pointer, i.e., 32-bits. Your original code added i to a# define, so that would have only moved the pointer by a single byte. Cheers, Dave# include <stdio.h> # include "system.h" int main() { int *pmem; int i=0; printf("Start!\n"); pmem=(int *)(0x80000000|(ONCHIP_MEMORY2_0_BASE)); for (i=0; i<15; i++) { printf("%u\n", *pmem++); } return 0; } - Altera_Forum
Honored Contributor
OK it IS an altsyncram.
The tstep signal is generated like that:
--- Quote Start --- Better than what? You asked how you can initialize it from file. --- Quote End --- Better than a .hex file?process(clk, tckup) begin if rising_edge(clk) then if (tckup='1') then wen <= '1'; if tstep<25000 then tstep <= tstep+1; end if; else wen <= '0'; end if; end if; end process; - Altera_Forum
Honored Contributor
--- Quote Start --- The tstep signal is generated like that:
--- Quote End --- This code has some minor coding issues; (1) you do not need tckup in the sensivity list, (2) generally you should not code using integers. Its better to be explicit to synthesis tools so there is no room for ambiguity. In your case you could define tstep as an integer over a limited range. or use an unsigned of an appropriate bit-length. --- Quote Start --- Better than a .hex file? --- Quote End --- .hex files are an industry standard, .mif files are Altera-specific. I personally prefer to stick with standard formats where possible. However, both .hex and .mif initialize RAM, so either is fine. Cheers, Daveprocess(clk, tckup) begin if rising_edge(clk) then if (tckup='1') then wen <= '1'; if tstep<25000 then tstep <= tstep+1; end if; else wen <= '0'; end if; end if; end process; - Altera_Forum
Honored Contributor
I think I've corrected everything (pmem++, sensivity list and integer range) and now the result is:
--- Quote Start --- Start! 67305985 134678021 2826 0 0 0 0 0 0 0 0 0 0 0 0 --- Quote End --- I still don't understand...