Forum Discussion
Altera_Forum
Honored Contributor
15 years agoNIOSII addressing for 32 bit wide SDRAM
Hello, first time poster here.
As the title suggests, I have an FPGA accessing a 32 bit wide DDR2 device (actually 2x 16 bit devices with appropriately shared signals). Using SOPC builder to generate a simple system with mainly NIOSII/f and one HPCII DDR2 controller. The controller is running full rate which means the "local width" is 64 bits. The DDR2 size is 256MB so the span is 0x10000000 (bytes) and the base address is 0x20000000 in SOPC. I am trying to confirm how to access all of the memory. Should I use IOWR/IORD or IOWR_32DIRECT/IORD_32DIRECT? If I use IOWR_32DIRECT/IORD_32DIRECT then should I read/write as: IOWR_32DIRECT(BASE, 0, val); IOWR_32DIRECT(BASE, 4, val); IOWR_32DIRECT(BASE, 8, val); ... IOWR_32DIRECT(BASE, 0xFFFFFFC, val); else should the address increments be multiples of 8. Else what? Thank-you.27 Replies
- Altera_Forum
Honored Contributor
A possible epiphany here...
w.r.t. my last few posts: I believe that accesses that involve 0x0F and 0xF0 BE(local_be) values would logically necessitate toggling the LSB of the mem column address but since the controller datasheet says the LSB of the mem column address is ignored for full rate that this is precisely why 0x0F and 0xF0 local_be are ignored thus the only way to see all the memory is to ONLY make 0xFF local_be accesses. Thoughts? - Altera_Forum
Honored Contributor
Hmmm, not sure that makes complete sense either w.r.t. ignoring LSB col addr bit
as even if i do a 0xFF 64 bit access that even then I would expect two accesses with the col addr LSB toggling. - Altera_Forum
Honored Contributor
So, generating BE = 0xFF transactions from NIOS by using a DMA controller
by first transferring test data from NIOS to 64 bit onchipmem and then 64-bit DMA'ing this to the 64-bit local bus of the DDR2 controller and then reversing the process to get the data back to NIOS works fine. This creates an acceptable workaround for me. The whole BE = 0x0F/0xF0 thing not working properly is probably going to come down to the whole partial write support of the controller. Whatever. I have my solution and don't want to spend any more time thinking about this. - Altera_Forum
Honored Contributor
Sigh. :(
The next step for me was to go to a half rate implementation which means for my 32 bit DDR2 that the local data width is 128-bit operating at 75MHz with DDR still at 150MHz. Timing is all met. Ok, so I implement a variation of the solution in my last post now using a 128 bit onchipmem and also 128 bit DMA controller so now BE = 0xFFFF for all writes/reads. Data is getting in and out of onchipmem fine. DMA writes look good on the local interface. For the DMA reads it looks like the command is correct going to the controller on the local interface but the readdatavalid looks out of whack asserting and deasserting in a periodic fashion. seemingly unrelated to the read command just sent to it and this naturally has dire consequences to the latched data. Searched through the forum, looked at http://www.altera.com/literature/rn/rn_ip.pdf, looked at unsupported features. Thoughts? - Altera_Forum
Honored Contributor
>>>>Timing is all met.
Or is it? <rhetorical> Trimmed the system down to bare minimum and it worked. Also, characterization showed unreasonable variability in the outcome. I believe I have over-constrained the design and will work to properly constrain. - Altera_Forum
Honored Contributor
Dummy text
- Altera_Forum
Honored Contributor
--- Quote Start --- So, I did a bunch of testing and experimenting and I need help to clarify things that may put this thing to rest. Firstly, I have only NIOS, DDR, On-chip mem, and JTAG in the system and I have reduced the clocks for all possible to the 50MHz sysclk. With this, all critical warnings have been removed as previously stated. The result with 4x address incrementing is like this: 1: wrote 00000001, test_addr 00000000, read_val 00000004, device 0 2: wrote 00000002, test_addr 00000004, read_val 00000004, device 0 3: wrote 00000004, test_addr 00000008, read_val 00000008, device 0 4: wrote 00000008, test_addr 0000000c, read_val 00000008, device 0 5: wrote 00000010, test_addr 00000010, read_val 00000040, device 0 6: wrote 00000020, test_addr 00000014, read_val 00000040, device 0 7: wrote 00000040, test_addr 00000018, read_val 00000080, device 0 8: wrote 00000080, test_addr 0000001c, read_val 00000080, device 0 ... etc, etc and with 8x address incrementing is like this: 1: wrote 00000001, test_addr 00000000, read_val 00000001, device 0 2: wrote 00000002, test_addr 00000008, read_val 00000002, device 0 3: wrote 00000004, test_addr 00000010, read_val 00000004, device 0 4: wrote 00000008, test_addr 00000018, read_val 00000008, device 0 5: wrote 00000010, test_addr 00000020, read_val 00000010, device 0 6: wrote 00000020, test_addr 00000028, read_val 00000020, device 0 7: wrote 00000040, test_addr 00000030, read_val 00000040, device 0 8: wrote 00000080, test_addr 00000038, read_val 00000080, device 0 etc, etc, ... 8x incrementing looks to provide correct results but that means that since we only get 4 bytes per read from NIOS that we are missing the other 4 bytes assuming the addresses provided to the _32DIRECT RD/WR macros are byte addresses. I confirmed that with 8x addr incrementing that I cannot write past the span of 0x10000000(256MB which is size of device). I used SignalTap to look at the *local* signals and addresses and this seems the root of the problem. When using 4x incrementing then the local_address increases as 0,0,1,1,2,2,3,3, etc. for every local_read_req pulse. When using 8x incrementing then the local_address increases as 0,1,2,3, etc. So, here, 8x looks correct but then since I can only access up to the span 0x10000000 (256MB if byte addr) before NIOS returns 0xFFFFFFFF as data and the devices are 256MB then half the addresses are not available apparently. Note for the reads the data for one of the 8x reads on this local_rdata bus (64 bits wide) is: 0x00000002_00000002 Note for the reads the data for one of the 4x reads on this local_rdata bus (64 bits wide) is: 0x00000004_00000004 How do I access ____ALL____ 256MB of this device. The emi_ddr_ug.pdf by Altera shows local_address on page 121 which talks about "LSB of column address on memory side is ignored" which may be of some relevance. Does this mean we ____WILL____ only see half of our memory??? Thank-you. --- Quote End --- Hi, How can you test the read/write values ? Did you write a C program to do this ? Which kind of tools can we use to write and read data between Nios II et DDR/DDR-2 ? I have also NIOS, DDR, On-chip mem, and JTAG Thank you in advance.