Reputation: 3084
I made an entity in which quartus successfully recognizes RAM, and instantiates a RAM megafunction for it. It would be nice if I could initialize that RAM from a file. I found tutorials for making such file (.mif file). Now that I have created that file, i don't know how to make quartus initialize that module. Any help is appreciated.
Here is my RAM entity:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity RAM is
port (
clk: in std_logic;
we: in std_logic;
data_in: in std_logic_vector (7 downto 0);
read_addr: in integer range 0 to 65535;
write_addr: in integer range 0 to 65535;
data_out: out std_logic_vector (7 downto 0)
);
end entity RAM;
architecture RAM_arch of RAM is
type memory is array (65535 downto 0) of std_logic_vector (7 downto 0);
signal content: memory;
begin
process(clk)
begin
if (RISING_EDGE(clk)) then
if (we = '1') then
content(write_addr) <= data_in;
end if;
data_out <= content(read_addr);
end if;
end process;
end architecture;
Upvotes: 3
Views: 11114
Reputation: 21
simplest method of initializing is by writing .mif with any simple editor such as Notepad. The .mif list below is for a ROM decoder as multiplexer. 6-bit address 64-bit data. .mif can contain any data word size 8,16,32,64-bit etc..in both hex or binary. Works all the time. The file must be in same directory as project.
WIDTH=64;
DEPTH=128;
ADDRESS_RADIX=HEX;
DATA_RADIX=HEX;
CONTENT BEGIN
000 : 0000000000000001;-- 0
001 : 0000000000000002;-- 1
002 : 0000000000000004;-- 2
003 : 0000000000000008;-- 3
004 : 0000000000000010;-- 4
005 : 0000000000000020;-- 5
006 : 0000000000000040;-- 6
007 : 0000000000000080;-- 7
008 : 0000000000000100;-- 8
009 : 0000000000000200;-- 9
00A : 0000000000000400;-- 10
00B : 0000000000000800;-- 11
00C : 0000000000001000;-- 12
00D : 0000000000002000;-- 13
00E : 0000000000004000;-- 14
00F : 0000000000008000;-- 15
010 : 0000000000010000;-- 16
011 : 0000000000020000;-- 17
012 : 0000000000040000;-- 18
013 : 0000000000080000;-- 19
014 : 0000000000100000;-- 20
015 : 0000000000200000;-- 21
016 : 0000000000400000;-- 22
017 : 0000000000800000;-- 23
018 : 0000000001000000;-- 24
019 : 0000000002000000;-- 25
01A : 0000000004000000;-- 26
01B : 0000000008000000;-- 27
01C : 0000000010000000;-- 28
01D : 0000000020000000;-- 29
01E : 0000000040000000;-- 30
01F : 0000000080000000;-- 31
020 : 0000000100000000;-- 32
021 : 0000000200000000;-- 33
022 : 0000000400000000;-- 34
023 : 0000000800000000;-- 35
024 : 0000001000000000;-- 36
025 : 0000002000000000;-- 37
026 : 0000004000000000;-- 38
027 : 0000008000000000;-- 39
028 : 0000010000000000;-- 40
029 : 0000020000000000;-- 41
02A : 0000040000000000;-- 42
02B : 0000080000000000;-- 43
02C : 0000100000000000;-- 44
02D : 0000200000000000;-- 45
02E : 0000400000000000;-- 46
02F : 0000800000000000;-- 47
030 : 0001000000000000;-- 48
031 : 0002000000000000;-- 49
032 : 0004000000000000;-- 50
033 : 0008000000000000;-- 51
034 : 0010000000000000;-- 52
035 : 0020000000000000;-- 53
036 : 0040000000000000;-- 54
037 : 0080000000000000;-- 55
038 : 0100000000000000;-- 56
039 : 0200000000000000;-- 57
03A : 0400000000000000;-- 58
03B : 0800000000000000;-- 59
03C : 1000000000000000;-- 60
03D : 2000000000000000;-- 61
03E : 4000000000000000;-- 62
03F : 8000000000000000;-- 63
[40..7F] : 0000000000000000;
END;
Upvotes: 2
Reputation: 1515
If you generated one of the RAM modules using the wizard but forgot to add a memory initialization file to it you can add one later by doing the following:
Tools > MegaWizard Plug-In Manager > Edit an existing custom megafunction variation > {Select your file} > Next > Mem Init > Yes, use this file for the memory content data > Browse
Upvotes: 1
Reputation: 29
One simple way to initalize a ram area is as follows: (quartus 15.1 tested)
(* ram_init_file = "Bm437_IBM_VGA8.mif" *) reg [7:0] Bm437_IBM_VGA8[4096];
Best regards, Johi.
Upvotes: 2
Reputation: 3084
As specified in this document this is the proper way to init memory from file:
signal content: memory;
attribute ram_init_file : string;
attribute ram_init_file of content:
signal is "init.mif";
Upvotes: 1
Reputation:
Possibly the best way to initialise the memory is to ... put an initialisation clause on the memory variable. There may be Quartus-specific ways to load .MIF files, but this is probably simpler, definitely more portable (to Xilinx for example), and more flexible because you get to define the file format, you don't have to generate .mif files.
Given the following code:
type memory is array (65535 downto 0) of std_logic_vector (7 downto 0);
signal content: memory;
you could simply write
type memory is array (65535 downto 0) of std_logic_vector (7 downto 0);
signal content: memory := init_my_RAM(filename => "ram_contents.txt");
Now it is possible but unlikely that Quartus doesn't support initialisation this way, so we can test it by writing a simple init_my_ram function ignoring the actual file contents:
function init_my_ram (filename : string) return memory is
variable f : file;
variable m : memory;
begin
file_open(f, filename, read_mode);
for i in memory'range loop
m(i) := X"55";
end loop;
file_close(f);
return m;
end init_my_ram;
Because the function call is an initialiser, and called at elaboration time when the design is synthesised, this is all synthesisable.
If this compiles and Quartus generates a memory full of X"55", you are good to go, to parse whatever file format you want, in the init_my_ram function. (Binary files are harder, and the reader code may not be so portable between tools, but not impossible).
The .MIF approach has one potential advantage though : you can update just the memory contents without requiring another synthesis/place and route cycle.
Upvotes: 3