• 0
qwertier

How to prepare the data for a program on board using Nexys4 DDR?

Question

I'm writing a cpu on Nexys 4 DDR, but I have a problem: The DDR2 memory on Nexys4 will be reset whenever a new .bit file is written to the FPGA.

I have already generated two .bit files. One is to write instructions and data to the DDR2 memory, and the other is the cpu program.

What should I do to make the DDR2 memory remain the same even after it's programmed? Thank you!

Share this post


Link to post
Share on other sites

5 answers to this question

Recommended Posts

  • 1

@qwertier,

That sounds like a fun project!  Care to share any info about it?

I myself have put a lot of time and effort into the ZipCPU.  You can find an overview here, even though it's a touch outdated.  (The CPU started out supporting 32-bit bytes only, and was only upgraded to 8-bit bytes this year.  The specification is up to date, but requires more reading.)  For the following discussion, it's important to know that the ZipCPU handles all peripherals via a memory mapped I/O interface.

I managed to get around your problem via a different approach:

  • I first created a means of accessing the internals of the FPGA using a debugging bus.  This allowed me to read/write memory locations, prove peripherals worked, etc.  The bus allows you to access memory locations, reading and writing them as necessary, over a UART port.  (Remember how I said that every peripheral was memory mapped, right?)  An example design doing nothing more than just running a similar bus may be found here.
  • As a next step, I added the CPU to my design.  Unlike your approach above, I didn't replace the debugging bus with the CPU, but rather placed a bus arbiter between the two so that they could both access memory and peripherals, but the arbitration circuit would only let one do so at any given time.
  • The CPU itself was given two addresses on the bus--but prevented from accessing itself.  From those two addresses, I can start and stop the CPU, read and write registers, reboot the CPU, step the CPU by one instruction, etc.  (Check out chapter 5 of the CPU spec, and the section on "Debug Port Registers"--should be section 5.2)  If you haven't already thought about it, you might want to spend a moment to think through what requirements your CPU will have to meet in order to be able to be debugged.  These two registers formed the basis for how I created my hardware debugging capability.  I had another capability already written for debugging in simulation--something I would highly encourage for you as well.
  • On my first several implementations (Basys3, XuLA2, Arty), the CPU would start in a stopped state, and only start running when told to run by a command line program (like this one).  This allowed me to set the memory for the CPU, to adjust the program counter, clear registers, etc., so that the CPU would start in a known state.  Indeed, this allowed me to start the CPU in a state other than the reset/reboot if I wanted to.
  • Some implementations (CMod S6), though, forced the CPU to run without the debugging bus in place.  For these implementations, I first loaded the code into flash.  (Be careful not to overwrite the FPGA configuration!  In my experience, this usually takes up roughly the first 1/4 of the flash, but that can be design dependent)  This is another solution to the problem you outline above, although I think I would recommend the longer solution via the debugging bus approach first.  Writing to and reading from the flash takes some ... extra logic.  Further, I lost access to the debugger when running on the S6, requiring even more creative solutions.
  • Incidentally, I would *highly* recommend that you run your first several programs in simulation, before  you try to run them on your hardware.  (You can read about my debugging philosophy here.)

I'm hoping to blog later this week about how to build a CPU debugger that allows you to debug your CPU while in simulation.  (Hint: my solution uses Verilator and ncurses)

Hope this helps.  Feel free to write back if you have further questions.  There are also some chat-rooms on IRC dedicated to particular soft-core FPGA's, where you might find their designers helpful in your work.

Dan

Share this post


Link to post
Share on other sites
  • 0

@D@n

Thanks a lot for your approach, really. I generated 3 .bit files. The 3 .bit files are write_instructions.bit, test_write_instructions.bit and cpu.bit.

After writing and executing write_instructions.bit on nexys 4, I wrote and executed test_wtite_instructions.bit. It turned out that I wrote the instructions into the ddr2 memory successfully. Even after I reprogrammed nexys 4 using test_writing_instructions.bit, the data in ddr2 memory is still there.

But after I reprogrammed nexys 4 using cpu.bit, the data in ddr2 memory is gone. How did this happen? Could you please explain it?

PS: During the whole process, the power was on all the time.

Edited by qwertier

Share this post


Link to post
Share on other sites
  • 0

@qwertier,

Can I explain it?  Perhaps not well.  I'll try though.

Modern day SDRAM's, such as the DDR2 SDRAM on your FPGA board, are built out of capacitors.  Setting a bit to "1" amounts to placing charge on the capacitor.  As with any capacitor, this charge will leak over time.  To keep this from happening, the SDRAM controller on your design needs to routinely shutdown any SDRAM interactions and have it refresh the capacitors.  It typically does this on a row by row basis, refreshing one row at a time.  Some SDRAM's and SDRAM controllers allow you to refresh more than a row at a time, or to push off the updates for a bit of time much like you or I might be able to swim underwater.  When the time runs out, updates are required and your SDRAM controller will take the SDRAM offline for longer to get all of the row updates accomplished.

The problem with what you are dealing with is that you are changing the design that is in place.  When you change .bit files, you (of necessity) shut down this capacitor refresh process.  While you *might* manage to finish updating your .bit file before the capacitors need to be refreshed again, the SDRAM controller (a part of your .bit file) doesn't know its supposed to send many, many refresh requests to the SDRAM--since it just started.

As for the fact that it "appears" to work, I would probably list this among the "non-supported" features of the hardware you are using.  I'd be surprised if it actually works "reliably" without ever losing a bit in the process.

Dan

Share this post


Link to post
Share on other sites
  • 0

@D@n

Many thanks to you. I found out that the ram on the Nexys 4 can actually save the data during the process I wrote the .bit file into the board. I will try your method, and I think it can be really helpful if I learned how to use it. Now the cpu is working well and I'm really grateful for your help.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now