Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BRAM_INIT in VHDL

I am simulating a processor based design where the program memory contents are held in a BRAM. I am realizing the program memory using VHDL (inferring BRAMs). I am trying to avoid CoreGen because I want to keep the design portable. Eventually this design will go to an FPGA.

I am looking to see if there is a way to initialize memory contents of the BRAMs using VHDL generics ? I understand that Coregen uses COE file to initialize the BRAM but do we have a VHDL code based way to do this ?

Let me know your alternate suggestions as well.

like image 731
boffin Avatar asked Dec 21 '22 22:12

boffin


2 Answers

Yes it is certainly possible. Take a look at the Xilinx Synthesis Tool (XST) User guide, specifically page 187.

The code they recommend to do this is reproduced below. They have notes in the user guide regarding the formatting of the file that will be read. Note that this code doesn't directly use generics, but I could imagine that you could possibly set a constant or generic to hold the name of the filename...

--
-- Initializing Block RAM from external data file
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use std.textio.all;

entity rams_20c is
port(clk : in std_logic;
   we : in std_logic;
   addr : in std_logic_vector(5 downto 0);
   din : in std_logic_vector(31 downto 0);
   dout : out std_logic_vector(31 downto 0));
end rams_20c;
architecture syn of rams_20c is
   type RamType is array(0 to 63) of bit_vector(31 downto 0);
   impure function InitRamFromFile (RamFileName : in string) return RamType is
      FILE RamFile : text is in RamFileName;
      variable RamFileLine : line;
      variable RAM : RamType;
   begin
      for I in RamTyperange loop
         readline (RamFile, RamFileLine);
         read (RamFileLine, RAM(I));
      end loop;
      return RAM;
   end function;
signal RAM : RamType := InitRamFromFile("rams_20c.data");
begin
   process (clk)
   begin
      if clkevent and clk = 1 then
         if we = 1 then
            RAM(conv_integer(addr)) <= to_bitvector(din);
         end if;
         dout <= to_stdlogicvector(RAM(conv_integer(addr)));
      end if;
   end process;
end syn;
like image 72
Josh Avatar answered Dec 23 '22 12:12

Josh


Alternatively, don't bother using generics or reading files; just declare a constant array in a package. Put it in a package rather than the main architecture, and you can even write the package automatically using a script (say, reading the assembler output or a text file).

library ieee;
use ieee.std_logic_1164.all;

package ProgMem is

type Word is std_logic_vector(7 downto 0);

constant ROM : array (0 to 3) of Word := 
    (
         X"C3",
         X"00",
         X"00",
         "UUUUUUUU" );         

end package Progmem;

The real program may be longer, but this illustrates the pattern

like image 40
user_1818839 Avatar answered Dec 23 '22 13:12

user_1818839