litedram: Fix DRAM init mem using too many address bits
[microwatt.git] / litedram / generated / sim / litedram-initmem.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 use std.textio.all;
5
6 library work;
7 use work.wishbone_types.all;
8 use work.utils.all;
9
10 entity dram_init_mem is
11 generic (
12 EXTRA_PAYLOAD_FILE : string := "";
13 EXTRA_PAYLOAD_SIZE : integer := 0
14 );
15 port (
16 clk : in std_ulogic;
17 wb_in : in wb_io_master_out;
18 wb_out : out wb_io_slave_out
19 );
20 end entity dram_init_mem;
21
22 architecture rtl of dram_init_mem is
23
24 constant INIT_RAM_SIZE : integer := 16384;
25 constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
26 constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
27 constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);
28 constant INIT_RAM_FILE : string := "litedram/generated/sim/litedram_core.init";
29
30 type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
31
32 -- XXX FIXME: Have a single init function called twice with
33 -- an offset as argument
34 procedure init_load_payload(ram: inout ram_t; filename: string) is
35 file payload_file : text open read_mode is filename;
36 variable ram_line : line;
37 variable temp_word : std_logic_vector(63 downto 0);
38 begin
39 for i in 0 to RND_PAYLOAD_SIZE-1 loop
40 exit when endfile(payload_file);
41 readline(payload_file, ram_line);
42 hread(ram_line, temp_word);
43 ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
44 ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
45 end loop;
46 assert endfile(payload_file) report "Payload too big !" severity failure;
47 end procedure;
48
49 impure function init_load_ram(name : string) return ram_t is
50 file ram_file : text open read_mode is name;
51 variable temp_word : std_logic_vector(63 downto 0);
52 variable temp_ram : ram_t := (others => (others => '0'));
53 variable ram_line : line;
54 begin
55 report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
56 " rounded to:" & integer'image(RND_PAYLOAD_SIZE);
57 report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
58 " bytes using " & integer'image(INIT_RAM_ABITS) &
59 " address bits";
60 for i in 0 to (INIT_RAM_SIZE/8)-1 loop
61 exit when endfile(ram_file);
62 readline(ram_file, ram_line);
63 hread(ram_line, temp_word);
64 temp_ram(i*2) := temp_word(31 downto 0);
65 temp_ram(i*2+1) := temp_word(63 downto 32);
66 end loop;
67 if RND_PAYLOAD_SIZE /= 0 then
68 init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
69 end if;
70 return temp_ram;
71 end function;
72
73 impure function init_zero return ram_t is
74 variable temp_ram : ram_t := (others => (others => '0'));
75 begin
76 return temp_ram;
77 end function;
78
79 impure function initialize_ram(filename: string) return ram_t is
80 begin
81 report "Opening file " & filename;
82 if filename'length = 0 then
83 return init_zero;
84 else
85 return init_load_ram(filename);
86 end if;
87 end function;
88 signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);
89
90 attribute ram_style : string;
91 attribute ram_style of init_ram: signal is "block";
92
93 signal obuf : std_ulogic_vector(31 downto 0);
94 signal oack : std_ulogic;
95 begin
96
97 init_ram_0: process(clk)
98 variable adr : integer;
99 begin
100 if rising_edge(clk) then
101 oack <= '0';
102 if (wb_in.cyc and wb_in.stb) = '1' then
103 adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
104 if wb_in.we = '0' then
105 obuf <= init_ram(adr);
106 else
107 for i in 0 to 3 loop
108 if wb_in.sel(i) = '1' then
109 init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
110 wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
111 end if;
112 end loop;
113 end if;
114 oack <= '1';
115 end if;
116 wb_out.ack <= oack;
117 wb_out.dat <= obuf;
118 end if;
119 end process;
120
121 wb_out.stall <= '0';
122
123 end architecture rtl;