Block RAM Guide

The Problem

You will have no doubt noticed that in the APMIPS.zip there are two modules called InstructionMemory and DataMemory. These two modules are mostly identical, and ideally generate block RAMs in a fairly general way. The only difference between the two is that there is an extra read port on the InstructionMemory. Basically, our synthesizer, XST, looks at a set of Language Templates and tries to infer what is being described. To view the Language Templates in ISE click Edit->Language Templates in the top menus. If you look at the modules themselves you will see that the addresses are being latched in on the positive edge of the clock, and then a lookup is being done in an array of regs. This is a very standard way of describing memories in Verilog. Unfortunately, these modules were only tested on XST versions 11.1 and 12.1. It seems like they should then work in XST 11.5, but that is not the case. It appears that memory inference in 11.5 is seriously broken, and we are going to have to use Coregen to generate block RAM. The reason we did not want to do this in the first place is that Coregen memories are a lot more static. You need to rerun Coregen any time you want to resize them or specify a new set of initial data. The huge down side to this is that it nearly doubles the downtime during simulation runs, because Coregen is *slow*.

The Solution

The most flexible solution I have is to continue to use the DataMemory and InstructionMemory modules in simulation, since this provides any easy way to change the initial values of the two memories through the hex files generated by the toolchain. But during synthesis use Coregen to generate a block RAM module that replaces InstructionMemory. I have included a new module named InstructionMemoryCoregen, this shows an example of instantiating the block RAMs to replace the InstructionMemory. The block RAM generator interface in Coregen is pretty straightforward. I will go through the steps of describing a 2 read, 1 write ported 2^16 byte memory.

Coregen Steps

  1. Open Coregen
  2. Create a new project
  3. Find the Block Memory Generator, Basic Elements->Memory Elements
  4. Page 1, we want Simple Dual Port RAM, and defaults for the rest
  5. Page 2, Write Width=32, Write Depth=2^16 bytes=2^14 words=16384, you want ENA and ENB pins, defaults for the rest
  6. Page 3, you want defaults for everything but Load Init File, this you want to set to the coe file generated by the toolchain, use Show to verify
  7. Page 4, defaults
  8. Page 5, defaults