Xilinx XST and initializing block RAMs

  • Thread starter Christopher Head
  • Start date
C

Christopher Head

Guest
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 <PMem_0> 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
 
On Sun, 03 Mar 2013 03:20:24 -0800, Christopher Head wrote:

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 <PMem_0> is used but never
assigned.
If you can't find a better answer, preload them with a function returning
something other than 0.

- Brian
 
On Sun, 3 Mar 2013 12:51:29 +0000 (UTC)
Brian Drummond <brian@shapes.demon.co.uk> wrote:

On Sun, 03 Mar 2013 03:20:24 -0800, Christopher Head wrote:

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 <PMem_0> is used
but never assigned.

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

- Brian
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
 
On 3/3/2013 4:20 AM, Christopher Head wrote:
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 <PMem_0> 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
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
 
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.
 
On Sun, 03 Mar 2013 18:08:14 -0800, Christopher Head wrote:

On Sun, 3 Mar 2013 12:51:29 +0000 (UTC)
Brian Drummond <brian@shapes.demon.co.uk> wrote:

On Sun, 03 Mar 2013 03:20:24 -0800, Christopher Head wrote:

Here’s the problem: XST keeps noticing that the great big arrays have
nothing in them, and declares that “Signal <PMem_0> is used but never
assigned.

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

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.
Interesting. THAT might be tool version dependent, I haven't heard that
one before.

I also recommend a function that returns lots of arbitrary values
(personally I used a linear congruential random number generator).
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
 
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
 
I'm afraid I tried that one. No luck.

Chris

On Mon, 4 Mar 2013 12:11:43 -0800 (PST)
jonesandy@comcast.net wrote:

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
 
On Mon, 4 Mar 2013 02:03:34 -0800 (PST)
Jon <jon@beniston.com> wrote:

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.
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
 
On Wednesday, March 6, 2013 5:52:48 AM UTC, Christopher Head wrote:
On Mon, 4 Mar 2013 02:03:34 -0800 (PST)

Jon wrote:

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.

I'm using VHDL, not Verilog.
Sorry to hear.

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.
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
 
On Monday, March 4, 2013 at 3:33:34 PM UTC+5:30, Jon wrote:
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.

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 :-
http://www.testbench.in/TB_03_FILE_IO_TB.html
 
I've never run into the described problem, and I think that's because I'v
never tried to use an empty ROM.
As soon as there is write capability, the tool can't optimize it awa
anymore.

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

BTW, good luck with DATA2MEM...

---------------------------------------
Posted through http://www.FPGARelated.com
 

Welcome to EDABoard.com

Sponsor

Back
Top