Xilinx XST and initializing block RAMs

Hi all, I'm using XST 14.2 and trying to use block RAMs to store constant data (i.e. as ROMs) for program code that will be run by a CPU. I want to infer the block RAMs during synthesis and then actually put data into them from an ELF during bitgen (in concert with a BMM file), so the data will be part of the bitstream and the FPGA will configure with the RAMs preloaded.

Here?s the problem: XST keeps noticing that the great big arrays have nothing in them, and declares that ?Signal is used but never assigned. This sourceless signal will be automatically connected to value GND.?. Then it turns it into a LUT RAM for some reason, but only a tiny one.

I?ve gone through the Spartan 6 XST user guide and the Xilinx constraint guide. I?ve tried attaching the KEEP attribute (set to ?yes?), the S attribute (set to ?yes?), and the EQUIVALENT_REGISTER_REMOVAL attribute (set to ?no?) to the PMem signal. I?ve tried attaching all three of them at the same time. I?ve even tried simultaneously attaching all those attributes to both the memory block, the address lines going into it, the clock line, and the data lines coming out of it. Nothing helps! XST insists that the RAM is useless and destroys it.

Surely this is a pretty common use case? What am I missing here?

Thanks! Chris

Reply to
Christopher Head
Loading thread data ...

If you can't find a better answer, preload them with a function returning something other than 0.

- Brian

Reply to
Brian Drummond

That sounds like a pretty awful answer, but it works. There seems to be a second basic rule as well, though: don't try to make your RAM one bit wide. I tried to make one-bit-wide RAMs and they just refused to infer BRAMs no matter what I did. Changing the RAM to be at least two bits wide made everything work just fine, despite the Xilinx docs claiming that BRAMs can, in fact, be 18,432 by 1 bit aspect ratio.

I also recommend a function that returns lots of arbitrary values (personally I used a linear congruential random number generator). Sometimes XST notices that two RAMs have the same data in them and will combine them, so a function that just returns a simple pattern might not be sufficient.

Got my situation sorted out, though, so thanks!

Chris

Reply to
Christopher Head

a

s have

never

ut only

to

and the

the PMem signal.

?ve even

There should be a SET_DONT_TOUCH pragma or keyword. I have used this to force some delays to not be optimized out, but I am still using ISE 11.x

or so. ISE supports it and it is a standard in the ASIC synthesis world.

It has been a couple of years since I used it, so if you want more detail, I will have to go look in the code.

BobH

Reply to
BobH

You can put a $readmemh to initialise the memory.

reg [data_width-1:0] memory[0:depth-1];

initial begin $readmemh("filename.hex", memory); end

Should work with both XST & Synplify.

Reply to
Jon

Interesting. THAT might be tool version dependent, I haven't heard that one before.

Agreed. That's the benefit of a function : easy to change the operation without touching the main design.

An alternative function body would take a filename, and return the array filled with a default program (perhaps a bootloader?)

... didn't mention it yesterday because the thought of writing an ELF parser in VHDL was daunting ... but an Intel Hex reader in VHDL would be dead easy, and "objcopy -O" or other tools will get you from .elf to .hex.

This would give you a ready-to-run bitstream, but still allow bitgen to update the software if desired.

- Brian

Reply to
Brian Drummond

Early (> 15 years ago) versions of Synplify would not infer memory from an SLV (which is an array of SL), but it would infer memory from an array of std_logic_vector(0 to 0), which is an array of single bit vectors. Maybe XST will work with that too.

Synplify has long since fixed that bug.

Andy

Reply to
jonesandy

I'm afraid I tried that one. No luck.

Chris

Reply to
Christopher Head

I'm using VHDL, not Verilog. Anyway, yes, initializing the memory to something with useful data in it does seem to solve it. This approach here has the risk that if the hex file starts out small, the synthesizer will optimize out some of the RAMs that aren't used, and then you can't get them back later when the hex file grows except by resynthesizing.

Chris

Reply to
Christopher Head

Sorry to hear.

I'm not sure it does that, but you can always pad out the hex file. Are you using objcopy to convert an ELF to binary and then to hex? If so, use the

--pad-to option.

The advantage of including the initialisation in your RTL is that it means your model can be simulated as well.

Cheers, Jon

Reply to
Jon

Hi Jon,

I am trying to initialize BRAM witj readmemh function as you have written , however in simulation all locations are filled up with XXXXX.. ()don't care) values. I am using the code at :-

formatting link

Reply to
lovelyece

I've never run into the described problem, and I think that's because I've never tried to use an empty ROM.

As soon as there is write capability, the tool can't optimize it away anymore.

Maybe the problem could be fixed by implementing write access that is never used, but not so obviously that the tool would realize it.

BTW, good luck with DATA2MEM...

--------------------------------------- Posted through

formatting link

Reply to
mnentwig

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.