Xilinx BRAM initialization

B

Brad Smallridge

Guest
I would like to initialize a Xilinx BRAM in a format that is more byte wide
organized and with the bytes going in a left to right, or down the page,
manner.

Presently, the Xilinx BRAMs are initialized in the generic map with
statements like this:

INIT_00 =>
"0000000000000000000000000000000000000000000000000000000004030201",

which, I believe are, 256 bit bit_vectors filled with hex literals. The init
as shown goes from right to left and would count 1,2,3,4 in a 9 bit wide
read. Very clumsy.

Even more difficult to format is the extra parity bit.

I will make shorter constant bit_vectors and reverse the order
with long concatenate statements if no one can suggest to me an
easier way. What I would like to see is an unconstained array of
8 or 9 bit bit_vectors, and some sort of procedure or function
that stuffs the BRAM init strings with the needed reversed order,
perhaps fills the rest of BRAM with a default value, and passes
this info to a wrapper BRAM module, whereby most of the BRAMs
workings, and initiaization, can be hidden away.

Brad Smallridge
ai vision
 
Brad Smallridge wrote:

Presently, the Xilinx BRAMs are initialized in the generic map with
statements like this:

INIT_00 =
"0000000000000000000000000000000000000000000000000000000004030201",

which, I believe are, 256 bit bit_vectors filled with hex literals. The init
as shown goes from right to left and would count 1,2,3,4 in a 9 bit wide
read. Very clumsy.
Indeed.

I would describe the ROM as a constant array
and let synthesis handle the gory details.

-- Mike Treseler
 
I was working on this last night,
and reading Ashenden's book as well.

How do you pronounce this guy's name
a-SHEN-den ? perhaps? or is it ASH-en-den?

I have the BRAM generic map call a function passing the data array and the
init bit_vector index. The while test in the function will test both indexes
for overflow. I think it should be fairly robust(although I have not
figured out how to test it completely) and easy to modify for other data
types.


Here's some of the code

.. . .

type init_array_type is array(natural range <>) of bit_vector(7 downto 0);

constant bram8_data : init_array_type :=(
X"00",X"01",X"02",X"03",X"04",X"05",X"06",X"07",
X"08",X"09",X"0A",X"0B",X"0C",X"0D",X"0E",X"0F",
X"00", X"FF"
);

function stuff_it
(
init_array : init_array_type;
init_xx : integer
) return bit_vector is
variable result : bit_vector(255 downto 0);
variable i : integer ;
variable j : integer ;
begin
result :=
X"0000000000000000000000000000000000000000000000000000000000000000";
i := 0 ;
j := 32*init_xx ;
while( (j < init_array'length) and (i<256) )
loop
result( (i+7) downto (i) ) := init_array(j) ;
i := i + 8 ;
j := j + 1 ;
end loop;
return result;
end function stuff_it;
.. . .
begin
.. . .
RAMB16_1 : RAMB16
generic map (
.. . .
INIT_00 => stuff_it(bram8_data,16#00#),
INIT_01 => stuff_it(bram8_data,16#01#),
INIT_02 => stuff_it(bram8_data,16#02#),
INIT_03 => stuff_it(bram8_data,16#03#),
INIT_04 => stuff_it(bram8_data,16#04#),
.. . .
 
I would describe the ROM as a constant array
and let synthesis handle the gory details.
Wow. For some reason I thought I had to do this
on my own, but the Xilinx tool seems to handle
it fine. Nice, hopefully portable, code.

Thanks Mike. Here's what I did:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity bram8 is
port (
clk : in std_logic;
rst : in std_logic;
q : out std_logic_vector(7 downto 0));
end bram8;

architecture behavioral of bram8 is

signal addr : std_logic_vector(11 downto 0);

type init_array_type is array(natural range <>) of std_logic_vector(7
downto 0);

constant bram8_data : init_array_type :=(
X"00",X"01",X"02",X"03",X"04",X"05",X"06",X"07",
X"08",X"09",X"0A",X"0B",X"0C",X"0D",X"0E",X"0F",
X"00",X"01",X"02",X"03",X"04",X"05",X"06",X"07",
X"08",X"09",X"0A",X"0B",X"0C",X"0D",X"0E",X"0F",
X"08",X"09",X"0A",X"0B",X"0C",X"0D",X"0E",X"0F",
X"00",X"01",X"02",X"03",X"04",X"05",X"06",X"07",
X"08",X"09",X"0A",X"0B",X"0C",X"0D",X"0E",X"0F",
X"00", X"FF"
);

begin

LUT_proc : process(clk)
begin
if( clk'event and clk='1') then
if(rst='1') then
q <= (others=>'0');
addr <= (others=>'0');
else
q <= bram8_data(CONV_INTEGER(addr));
addr <= addr + 1;
end if;
end if;
end process;

end behavioral;
 
Brad Smallridge wrote:

Thanks Mike. Here's what I did:

LUT_proc : process(clk)
begin
if( clk'event and clk='1') then
if(rst='1') then
q <= (others=>'0');
addr <= (others=>'0');
else
q <= bram8_data(CONV_INTEGER(addr));
addr <= addr + 1;
end if;
end if;
end process;

end behavioral;

If all you need is a rom, you don't have to
include hardware for a loader. See below.

-- Mike Treseler

http://home.comcast.net/~mike_treseler/sync_rom.vhd
http://home.comcast.net/~mike_treseler/sync_rom_tech.pdf
http://home.comcast.net/~mike_treseler/sync_rom_rtl.pdf
 

Welcome to EDABoard.com

Sponsor

Back
Top