litedram: Add support for booting without BRAM

This adds an option to disable the main BRAM and instead copy a
payload stashed along with the init code in the secondary BRAM
into DRAM and boot from there

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
jtag-port
Benjamin Herrenschmidt 5 years ago
parent 6fe077910b
commit bf1b98b958

@ -7,33 +7,52 @@ use work.common.all;
use work.wishbone_types.all;

entity core_dram_tb is
generic (
MEMORY_SIZE : natural := (384*1024);
MAIN_RAM_FILE : string := "main_ram.bin";
DRAM_INIT_FILE : string := "";
DRAM_INIT_SIZE : natural := 16#c000#
);
end core_dram_tb;

architecture behave of core_dram_tb is
signal clk, rst: std_logic;
signal system_clk, soc_rst : std_ulogic;

-- testbench signals
constant clk_period : time := 10 ns;

-- Sim DRAM
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_ctrl_in : wb_io_master_out;
signal wb_dram_ctrl_out : wb_io_slave_out;
signal wb_dram_is_csr : std_ulogic;
signal wb_dram_is_init : std_ulogic;
signal core_alt_reset : std_ulogic;
signal clk, rst: std_logic;
signal system_clk, soc_rst : std_ulogic;

-- testbench signals
constant clk_period : time := 10 ns;

-- Sim DRAM
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_ctrl_in : wb_io_master_out;
signal wb_dram_ctrl_out : wb_io_slave_out;
signal wb_dram_is_csr : std_ulogic;
signal wb_dram_is_init : std_ulogic;
signal core_alt_reset : std_ulogic;

-- ROM size
function get_rom_size return natural is
begin
if MEMORY_SIZE = 0 then
return DRAM_INIT_SIZE;
else
return 0;
end if;
end function;

constant ROM_SIZE : natural := get_rom_size;
begin

soc0: entity work.soc
generic map(
SIM => true,
MEMORY_SIZE => (384*1024),
RAM_INIT_FILE => "main_ram.bin",
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => MAIN_RAM_FILE,
RESET_LOW => false,
HAS_DRAM => true,
DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => ROM_SIZE,
CLK_FREQ => 100000000
)
port map(
@ -50,48 +69,50 @@ begin
alt_reset => core_alt_reset
);

dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 1
)
port map(
clk_in => clk,
rst => rst,
system_clk => system_clk,
system_reset => soc_rst,
core_alt_reset => core_alt_reset,
pll_locked => open,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_ctrl_in => wb_dram_ctrl_in,
wb_ctrl_out => wb_dram_ctrl_out,
wb_ctrl_is_csr => wb_dram_is_csr,
wb_ctrl_is_init => wb_dram_is_init,

serial_tx => open,
serial_rx => '1',

init_done => open,
init_error => open,

ddram_a => open,
ddram_ba => open,
ddram_ras_n => open,
ddram_cas_n => open,
ddram_we_n => open,
ddram_cs_n => open,
ddram_dm => open,
ddram_dq => open,
ddram_dqs_p => open,
ddram_dqs_n => open,
ddram_clk_p => open,
ddram_clk_n => open,
ddram_cke => open,
ddram_odt => open,
ddram_reset_n => open
);
dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 1,
PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => ROM_SIZE
)
port map(
clk_in => clk,
rst => rst,
system_clk => system_clk,
system_reset => soc_rst,
core_alt_reset => core_alt_reset,
pll_locked => open,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_ctrl_in => wb_dram_ctrl_in,
wb_ctrl_out => wb_dram_ctrl_out,
wb_ctrl_is_csr => wb_dram_is_csr,
wb_ctrl_is_init => wb_dram_is_init,

serial_tx => open,
serial_rx => '1',

init_done => open,
init_error => open,

ddram_a => open,
ddram_ba => open,
ddram_ras_n => open,
ddram_cas_n => open,
ddram_we_n => open,
ddram_cs_n => open,
ddram_dm => open,
ddram_dq => open,
ddram_dqs_p => open,
ddram_dqs_n => open,
ddram_clk_p => open,
ddram_clk_n => open,
ddram_cke => open,
ddram_odt => open,
ddram_reset_n => open
);

clk_process: process
begin

@ -10,11 +10,12 @@ use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : positive := 16384;
MEMORY_SIZE : integer := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_FREQUENCY : positive := 100000000;
USE_LITEDRAM : boolean := false;
NO_BRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false
);
port(
@ -85,6 +86,28 @@ architecture behaviour of toplevel is

-- Dumb PWM for the LEDs, those RGB LEDs are too bright otherwise
signal pwm_counter : std_ulogic_vector(8 downto 0);

-- Fixup various memory sizes based on generics
function get_bram_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return 0;
else
return MEMORY_SIZE;
end if;
end function;

function get_payload_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return MEMORY_SIZE;
else
return 0;
end if;
end function;
constant BRAM_SIZE : natural := get_bram_size;
constant PAYLOAD_SIZE : natural := get_payload_size;
begin

uart_pmod_rts_n <= '0';
@ -92,13 +115,14 @@ begin
-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => MEMORY_SIZE,
MEMORY_SIZE => BRAM_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 256 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
)
port map (
@ -159,7 +183,7 @@ begin
);
ddram_clk_dummy <= '0';

end generate;
end generate;

has_dram: if USE_LITEDRAM generate
signal dram_init_done : std_ulogic;
@ -189,7 +213,9 @@ begin
dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 14
DRAM_ALINES => 14,
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk_in => ext_clk,

@ -10,11 +10,12 @@ use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : positive := 16384;
MEMORY_SIZE : integer := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_FREQUENCY : positive := 100000000;
USE_LITEDRAM : boolean := false;
NO_BRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false
);
port(
@ -70,18 +71,40 @@ architecture behaviour of toplevel is
-- Control/status
signal core_alt_reset : std_ulogic;

-- Fixup various memory sizes based on generics
function get_bram_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return 0;
else
return MEMORY_SIZE;
end if;
end function;

function get_payload_size return natural is
begin
if USE_LITEDRAM and NO_BRAM then
return MEMORY_SIZE;
else
return 0;
end if;
end function;
constant BRAM_SIZE : natural := get_bram_size;
constant PAYLOAD_SIZE : natural := get_payload_size;
begin

-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => MEMORY_SIZE,
MEMORY_SIZE => BRAM_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 512 * 1024 * 1024,
DRAM_INIT_SIZE => PAYLOAD_SIZE,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
)
port map (
@ -171,7 +194,9 @@ begin
dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 25,
DRAM_ALINES => 15
DRAM_ALINES => 15,
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk_in => ext_clk,

@ -23,6 +23,7 @@
#define SYS_REG_INFO 0x08
#define SYS_REG_INFO_HAS_UART (1ull << 0)
#define SYS_REG_INFO_HAS_DRAM (1ull << 1)
#define SYS_REG_INFO_HAS_BRAM (1ull << 2)
#define SYS_REG_BRAMINFO 0x10
#define SYS_REG_DRAMINFO 0x18
#define SYS_REG_CLKINFO 0x20
@ -30,6 +31,7 @@
#define SYS_REG_CTRL_DRAM_AT_0 (1ull << 0)
#define SYS_REG_CTRL_CORE_RESET (1ull << 1)
#define SYS_REG_CTRL_SOC_RESET (1ull << 2)
#define SYS_REG_DRAMINITINFO 0x30

/*
* Register definitions for the potato UART

@ -6,7 +6,8 @@ import pathlib

class LiteDRAMGenerator(Generator):
def run(self):
board = self.config.get('board')
board = self.config.get('board')
payload = self.config.get('payload')

# Collect a bunch of directory path
script_dir = os.path.dirname(sys.argv[0])

@ -10,6 +10,9 @@ entity litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive;
-- Pseudo-ROM payload
PAYLOAD_SIZE : natural;
PAYLOAD_FILE : string;
-- Debug
LITEDRAM_TRACE : boolean := false
);
@ -144,6 +147,10 @@ begin

-- Init code BRAM memory slave
init_ram_0: entity work.dram_init_mem
generic map(
EXTRA_PAYLOAD_FILE => PAYLOAD_FILE,
EXTRA_PAYLOAD_SIZE => PAYLOAD_SIZE
)
port map(
clk => system_clk,
wb_in => wb_init_in,

@ -5,66 +5,117 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
port (
clk : in std_ulogic;
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
);
end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
return temp_ram;
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
if RND_PAYLOAD_SIZE /= 0 then
init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
end if;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
wb_out.dat <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_out.ack <= '1';
end if;
end if;
if rising_edge(clk) then
oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;

wb_out.stall <= '0';

@ -54,12 +54,18 @@ void main(void)
printf("UART ");
if (ftr & SYS_REG_INFO_HAS_DRAM)
printf("DRAM ");
if (ftr & SYS_REG_INFO_HAS_BRAM)
printf("BRAM ");
printf("\n");
val = readq(SYSCON_BASE + SYS_REG_BRAMINFO);
printf(" BRAM: %lld KB\n", val / 1024);
if (ftr & SYS_REG_INFO_HAS_BRAM) {
val = readq(SYSCON_BASE + SYS_REG_BRAMINFO);
printf(" BRAM: %lld KB\n", val / 1024);
}
if (ftr & SYS_REG_INFO_HAS_DRAM) {
val = readq(SYSCON_BASE + SYS_REG_DRAMINFO);
printf(" DRAM: %lld MB\n", val / (1024 * 1024));
val = readq(SYSCON_BASE + SYS_REG_DRAMINITINFO);
printf(" DRAM INIT: %lld KB\n", val / 1024);
}
val = readq(SYSCON_BASE + SYS_REG_CLKINFO);
printf(" CLK: %lld MHz\n", val / 1000000);
@ -70,5 +76,15 @@ void main(void)
MIGEN_GIT_SHA1, LITEX_GIT_SHA1);
sdrinit();
}
printf("Booting from BRAM...\n");
if (ftr & SYS_REG_INFO_HAS_BRAM)
printf("Booting from BRAM...\n");
else {
void *s = (void *)(DRAM_INIT_BASE + 0x4000);
void *d = (void *)DRAM_BASE;
int sz = (0x10000 - 0x4000);
printf("Copying payload to DRAM...\n");
memcpy(d, s, sz);
printf("Booting from DRAM...\n");
flush_cpu_icache();
}
}

@ -5,8 +5,13 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
port (
clk : in std_ulogic;
wb_in : in wb_io_master_out;
@ -16,11 +21,30 @@ end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
@ -28,6 +52,11 @@ architecture rtl of dram_init_mem is
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
@ -35,25 +64,45 @@ architecture rtl of dram_init_mem is
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
if RND_PAYLOAD_SIZE /= 0 then
init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
end if;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '0';
oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
wb_out.dat <= init_ram(adr);
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
@ -62,8 +111,10 @@ begin
end if;
end loop;
end if;
wb_out.ack <= '1';
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;


File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-22 17:57:16
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-26 20:37:38
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,

@ -5,66 +5,117 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
port (
clk : in std_ulogic;
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
);
end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
return temp_ram;
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
if RND_PAYLOAD_SIZE /= 0 then
init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
end if;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
wb_out.dat <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_out.ack <= '1';
end if;
end if;
if rising_edge(clk) then
oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;

wb_out.stall <= '0';

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-22 17:57:18
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-26 20:37:40
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,

@ -5,66 +5,118 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
port (
clk : in std_ulogic;
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out
);
end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram/generated/sim/litedram_core.init";
constant INIT_RAM_SIZE : integer := 16384;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE);
constant INIT_RAM_FILE : string := "litedram/generated/sim/litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);
type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
file ram_file : text open read_mode is name;
file payload_file : text open read_mode is EXTRA_PAYLOAD_FILE;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
return temp_ram;
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
end loop;
if RND_PAYLOAD_SIZE /= 0 then
procedure init_load_payload(ram: inout ram_t; filename: string) is
end if;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
variable adr : integer;
begin
if rising_edge(clk) then
wb_out.ack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
wb_out.dat <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_out.ack <= '1';
end if;
end if;
if rising_edge(clk) then
oack <= '0';
if (wb_in.cyc and wb_in.stb) = '1' then
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
if wb_in.we = '0' then
obuf <= init_ram(adr);
else
for i in 0 to 3 loop
if wb_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
end if;
end process;

wb_out.stall <= '0';

@ -7,7 +7,7 @@ a64b5a7d14004a39
6421f000782107c6
3d80000060213f00
798c07c6618c0000
618c108c658cf000
618c10a4658cf000
4e8004217d8903a6
0000000048000002
0000000000000000
@ -510,7 +510,7 @@ a64b5a7d14004a39
0000000000000000
0000000000000000
0000000000000000
384295003c4c0001
384296003c4c0001
fbc1fff07c0802a6
f8010010fbe1fff8
3be10020f821fe91
@ -519,61 +519,83 @@ f8c101a838800140
38c101987c651b78
7fe3fb78f8e101b0
f92101c0f90101b8
48000c89f94101c8
48000da5f94101c8
7c7e1b7860000000
4800080d7fe3fb78
480008bd7fe3fb78
3821017060000000
480012487fc3f378
480013647fc3f378
0100000000000000
4e80002000000280
0000000000000000
7c0007ac00000000
4e8000204c00012c
0000000000000000
3c4c000100000000
7c0802a638429474
7d908026fbe1fff8
f801001091810008
48000719f821ff91
7c0802a63842955c
7d800026fbe1fff8
91810008f8010010
480007b1f821ff91
3c62ffff60000000
4bffff4d38637dc8
4bffff3538637de8
548400023880ffff
7c8026ea7c0004ac
3fe0c0003c62ffff
63ff000838637de8
3c62ffff4bffff29
38637e087bff0020
7c0004ac4bffff19
63ff000838637e08
3c62ffff4bffff11
38637e287bff0020
7c0004ac4bffff01
73e900017fe0feea
3c62ffff41820010
4bfffefd38637e20
4e00000073e90002
4bfffee538637e40
4d80000073e90002
3c62ffff41820010
4bfffee538637e28
3bff7fc83fe2ffff
4bfffed57fe3fb78
608400103c80c000
7c0004ac78840020
3c62ffff7c8026ea
38637e307884b282
419200284bfffeb1
608400183c80c000
4bfffecd38637e48
4e00000073e90004
3c62ffff41820010
4bfffeb538637e50
3be2804860000000
4bfffea57fe3fb78
3c80c00041920028
7884002060840010
7c8026ea7c0004ac
7884b2823c62ffff
4bfffe7d38637e58
3c80c000418e004c
7884002060840018
7c8026ea7c0004ac
788465023c62ffff
4bfffe5538637e78
608400303c80c000
7c0004ac78840020
3c62ffff7c8026ea
38637e5078846502
3d20c0004bfffe89
38637e987884b282
3d20c0004bfffe31
7929002061290020
7d204eea7c0004ac
3c62ffff3c80000f
38637e7060844240
4bfffe5d7c892392
4bfffe557fe3fb78
3ca2ffff41920028
38637eb860844240
4bfffe057c892392
4bfffdfd7fe3fb78
3ca2ffff418e0028
3c62ffff3c82ffff
38847ea038a57e90
4bfffe3538637ea8
6000000048000469
38637ed83c62ffff
382100704bfffe21
7d90812081810008
00000000480010c0
38847ee838a57ed8
4bfffddd38637ef0
60000000480004c1
3c62ffff41920020
4bfffdc538637f20
8181000838210070
480011807d818120
38637f383c62ffff
3c80f0004bfffda9
6084400038a0ffff
7884002054a50422
480008553c604000
3c62ffff60000000
4bfffd7d38637f58
e801001038210070
ebe1fff881810008
7d8181207c0803a6
000000004bfffde4
0000018003000000
612908083d20c010
7c0004ac79290020
@ -583,26 +605,26 @@ f801001091810008
4e8000207d20572a
0000000000000000
3c4c000100000000
7c0802a6384292bc
7c0802a63842930c
614a08003d40c010
794a002039200001
f821ffa1f8010010
7d20572a7c0004ac
38637fa83c62ffff
600000004bfffd91
3862802860000000
600000004bfffce1
e801001038210060
4e8000207c0803a6
0100000000000000
3c4c000100000080
7c0802a638429264
7c0802a6384292b4
6129000c3d204000
3fc0aaaa48000f91
3fc0aaaa48000ffd
f821ff713f804000
63deaaaa3fa04000
639c00043fe04000
93df000063bd0008
93dd000093dc0000
4bfffd9993c90000
4bfffce993c90000
813f000060000000
7d29f278815c0000
7d2900347f8af000
@ -622,7 +644,7 @@ f821ff713f804000
93dd000093dc0000
3d20400093c90000
93c900006129000c
600000004bfffcfd
600000004bfffc4d
7f89f000813c0000
3bff0001419e000c
813d00007fff07b4
@ -638,7 +660,7 @@ f821ff713f804000
3bff0001419e0028
3c62ffff7fff07b4
7fe4fb7838a00100
4bfffc0538637ef0
4bfffb5538637f70
4800000c60000000
409effe02fbf0000
3ce0802039000004
@ -648,7 +670,7 @@ f821ff713f804000
7d2900d0792907e0
7d293838394a0004
912afffc7d294278
4bfffc294200ffe4
4bfffb794200ffe4
3900000460000000
7d0903a63ce08020
3d40400060e70003
@ -662,7 +684,7 @@ f821ff713f804000
2fbe00004200ffd4
3c62ffff419e001c
7fc4f37838a00004
4bfffb4538637f18
4bfffa9538637f98
3d20400060000000
6129000839400000
914900003ba00000
@ -672,7 +694,7 @@ f821ff713f804000
9149000061290010
394000033d204000
9149000061290014
600000004bfffb6d
600000004bfffabd
3940000039200004
3d2a10007d2903a6
8129000879291764
@ -682,12 +704,12 @@ f821ff713f804000
2fbd00004200ffdc
3c62ffff419e001c
7fa4eb7838a00004
4bfffaa538637f40
4bfff9f538637fc0
7ffefa1460000000
7fffea143bc00000
409e00a42f9f0000
38637f683c62ffff
600000004bfffa81
38637fe83c62ffff
600000004bfff9d1
3f8040007f5602a6
639c00043f604000
3fa0400039200001
@ -696,7 +718,7 @@ f821ff713f804000
63de000c39200002
39200003913d0000
7ff602a6913e0000
600000004bfffaad
600000004bfff9fd
815b00007d3602a6
815d0000815c0000
7cb602a6815e0000
@ -704,17 +726,17 @@ f821ff713f804000
7ca42b967d3fd050
3c62ffff7c844b96
788404a078a504a0
3bc0000138637f78
600000004bfff9f1
3bc0000138637ff8
600000004bfff941
7fc3f37838210090
0000000048000c68
0000000048000cd4
0000068001000000
38428ec83c4c0001
3c62ffff7c0802a6
48000bf538637fd0
38428f183c4c0001
600000007c0802a6
48000c6138628050
3f60c010f821ff71
637b10003be00000
4bfff9a57b7b0020
4bfff8f57b7b0020
7c0004ac60000000
3f40c0107fe0df2a
7b5a0020635a1008
@ -753,38 +775,38 @@ f821ff713f804000
4082001c2c230000
7f80df2a7c0004ac
7f80d72a7c0004ac
48000af438210090
48000b6038210090
7f80df2a7c0004ac
4bffffec38600001
0100000000000000
3c4c000100000680
3d20c00038428d44
3d20c00038428d94
6129200060000000
f922803879290020
f92280b879290020
612900203d20c000
7c0004ac79290020
3d40001c7d204eea
7d295392614a2000
394a0018e9428038
394a0018e94280b8
7c0004ac3929ffff
4e8000207d2057ea
0000000000000000
3c4c000100000000
6000000038428ce4
39290010e9228038
6000000038428d34
39290010e92280b8
7d204eea7c0004ac
4082ffe871290008
e94280385469063e
e94280b85469063e
7d2057ea7c0004ac
000000004e800020
0000000000000000
38428ca03c4c0001
38428cf03c4c0001
fbc1fff07c0802a6
3bc3fffffbe1fff8
f821ffd1f8010010
2fbf00008ffe0001
38210030409e0010
48000a2038600000
48000a8c38600000
409e000c2b9f000a
4bffff813860000d
4bffff797fe3fb78
@ -834,283 +856,297 @@ f924000039290002
392900014e800020
000000004bffffe8
0000000000000000
2b8900193923ff9f
3863ffe04d9d0020
4e8000207c6307b4
3900000078aae8c2
7d2903a6392a0001
78a9e8c242000030
1d29fff8792a1f24
7c8452147d035214
392000007ca92a14
7d4903a639450001
4e80002042000018
7d23412a7d24402a
4bffffc439080008
7d4849ae7d4448ae
4bffffdc39290001
0000000000000000
3923ff9f00000000
4d9d00202b890019
7c6307b43863ffe0
000000004e800020
0000000000000000
3c4c000100000000
7c0802a638428abc
7d9080263d203736
792907c661293534
9181000865293332
480007d961293130
7c7d1b78f821ffa1
3be000007cde3378
3d206665f9210020
792907c661296463
6129393865296261
7ca92b78f9210028
409e00802fa90000
409e00082fbf0000
7fbf20403be00001
419d005838600000
3b9fffff2e270000
7d3bf1d27f65f392
7ca12a147ca92850
4192001088650020
600000004bffff41
2fbb00005463063e
7f65db78e93d0000
3b9cffff7c69e1ae
e93d0000409effc8
7fe9fa1438600001
38210060fbfd0000
7d90812081810008
2b9e001048000774
7929e102409e0014
7fff07b43bff0001
7d29f3924bffff68
000000004bfffff0
0000058003000000
384289b03c4c0001
480006e97c0802a6
eb630000f821ffb1
7c9c23787c7f1b78
3bc000007cbd2b78
4bfffe797fa3eb78
7fa3f04060000000
e95f0000409d0014
7fa9e0407d3b5050
38210050419c0010
480006f038600001
3bde00017d3df0ae
e93f0000992a0000
f93f000039290001
000000004bffffb8
0000058001000000
384289303c4c0001
480006617c0802a6
7c7d1b78f821ffa1
7ca32b787c9b2378
38a0000a38800000
eb5d00007cde3378
7d1943787cfc3b78
4bfffcb57d3f4b78
3940000060000000
2fbe00007c6307b4
2faa0000409e006c
39400001409e0008
7f8348007d3f5214
409d00447d2a07b4
2f8300007c6a1850
3929000178690020
3d408000419c0010
409e00087f835000
2c29000139200001
418200143929ffff
7d5a3850e8fd0000
419c00307faad840
3860000038210060
2b9c001048000604
7bdee102409e0014
7d4a07b4394a0001
7fdee3924bffff7c
9b2700004bfffff0
394a0001e95d0000
4bffffa8f95d0000
38428aa03c4c0001
3d2037367c0802a6
612935347d908026
65293332792907c6
6129313091810008
f821ffa1480007d9
7cde33787c7d1b78
f92100203be00000
612964633d206665
65296261792907c6
f921002861293938
2fa900007ca92b78
2fbf0000409e0080
3be00001409e0008
386000007fbf2040
2e270000419d0058
7f65f3923b9fffff
7ca928507d3bf1d2
886500207ca12a14
4bffff4141920010
5463063e60000000
e93d00002fbb0000
7c69e1ae7f65db78
409effc83b9cffff
38600001e93d0000
fbfd00007fe9fa14
8181000838210060
480007747d908120
409e00142b9e0010
3bff00017929e102
4bffff687fff07b4
4bfffff07d29f392
0300000000000000
3c4c000100000580
7c0802a638428994
f821ffb1480006e9
7c7f1b78eb630000
7cbd2b787c9c2378
7fa3eb783bc00000
600000004bfffe0d
409d00147fa3f040
7d3b5050e95f0000
419c00107fa9e040
3860000138210050
7d3df0ae480006f0
992a00003bde0001
39290001e93f0000
4bffffb8f93f0000
0100000000000000
3c4c000100000780
7c0802a638428834
f821fed148000539
f86100607c741b79
4182006838600000
419e00602fa40000
3e42ffff39210040
3b4100203ac4ffff
60000000f9210070
392280303ae00000
3ba100603a527fe8
89250000f9210078
2fa90000ebc10060
7ff4f050419e0010
419c00207fbfb040
993e000039200000
7e941850e8610060
382101307e8307b4
2b89002548000508
409e048839450001
8925000038e00000
f8a10068e9010070
7d2741ae7cea07b4
8d25000139070001
2b8900647d0807b4
2b890069419e0058
2b890075419e0050
2b890078419e0048
2b890058419e0040
2b890070419e0038
2b890063419e0030
2b890073419e0028
2b890025419e0020
2b89004f419e0018
2b89006f419e0010
409eff8838e70001
2b890025394a0002
7d1a42147d4a07b4
992800207d5a5214
409e00209aea0020
f9210060393e0001
993e000039200025
38a90002e9210068
892100414bffff04
3a2600087fffb050
3a600030eb660000
3929ffd23b010042
4082039c712900fd
3b2000043aa00000
3a0000013b800000
7ddb00d039e0002d
2b89006c48000108
88f8000138d80001
419d0118419e033c
419e02402b890063
2b89004f419d0038
2b890058419e01e8
3949ffd0419e0188
2b8a0009554a063e
395c0001419d00c4
993c00207f81e214
480000b0795c0020
419e03042b890068
419e000c2b890069
409effc82b890064
7d41e2142b890075
7f6adb789aea0020
57291838419e0034
7e0948363929ffff
418200207f694839
e921006099e80000
f921006039290001
7d52482a7b291f24
e88100607dca5038
38e0000a7d465378
7f45d378f9410080
7e689b7839200000
7c9e20507fa3eb78
4bfffc9d7c84f850
e9410080e8810060
38c0000a7ea7ab78
7d4553787c9e2050
7fa3eb787c84f850
3b1800014bfffaed
e901006089380000
3c4c000100000580
7c0802a638428914
f821ffa148000661
7c9b23787c7d1b78
388000007ca32b78
7cde337838a0000a
7cfc3b78eb5d0000
7d3f4b787d194378
600000004bfffc49
7c6307b439400000
409e006c2fbe0000
409e00082faa0000
7d3f521439400001
7d2a07b47f834800
7c6a1850409d0044
786900202f830000
419c001039290001
7f8350003d408000
39200001409e0008
3929ffff2c290001
e8fd000041820014
7faad8407d5a3850
38210060419c0030
4800060438600000
409e00142b9c0010
394a00017bdee102
4bffff7c7d4a07b4
4bfffff07fdee392
e95d00009b270000
f95d0000394a0001
000000004bffffa8
0000078001000000
384288183c4c0001
480005397c0802a6
7c741b79f821fed1
38600000f8610060
2fa4000041820068
39210040419e0060
3ac4ffff60000000
f92100703b410020
3ae0000060000000
3a428068392280b0
f92100783ba10060
ebc1006089250000
419e00102fa90000
7fbf50407d5e4050
7e268b78419dfee4
2b8900734bfffe90
419d006c419e016c
419e00d42b89006f
409efef02b890070
38e000107d21e214
7c8af8507f66db78
390000209ae90020
7f45d37839200002
4bfffc0d7fa3eb78
e8a10078e8810060
7c9e20507fa3eb78
4bfffb757c84f850
7ea7ab78e8810060
7f65db7838c00010
4bffff5c7c9e2050
419e00182b890078
419e01cc2b89007a
4bfffeb82b890075
7d21e2143aa00001
7c8af85038e00010
9ae900207e689b78
7f45d3787b291f24
7d72482a7fa3eb78
7f6b583839200000
f96100807d665b78
e88100604bfffb89
7fbfb0407ff4f050
39200000419c0020
e8610060993e0000
7e8307b47e941850
4800050838210130
394500012b890025
38e00000409e0488
e901007089250000
7cea07b4f8a10068
390700017d2741ae
7d0807b48d250001
419e00582b890064
419e00502b890069
419e00482b890075
419e00402b890078
419e00382b890058
419e00302b890070
419e00282b890063
419e00202b890073
419e00182b890025
419e00102b89004f
38e700012b89006f
394a0002409eff88
7d4a07b42b890025
7d5a52147d1a4214
9aea002099280020
393e0001409e0020
39200025f9210060
e9210068993e0000
4bffff0438a90002
7fffb05089210041
eb6600003a260008
3b0100423a600030
712900fd3929ffd2
3aa000004082039c
3b8000003b200004
39e0002d3a000001
480001087ddb00d0
38d800012b89006c
419e033c88f80001
2b890063419d0118
419d0038419e0240
419e01e82b89004f
419e01882b890058
554a063e3949ffd0
419d00c42b8a0009
7f81e214395c0001
795c0020993c0020
2b890068480000b0
2b890069419e0304
2b890064419e000c
2b890075409effc8
9aea00207d41e214
419e00347f6adb78
3929ffff57291838
7f6948397e094836
99e8000041820020
39290001e9210060
7b291f24f9210060
7dca50387d52482a
7d465378e8810060
f941008038e0000a
392000007f45d378
7fa3eb787e689b78
7c84f8507c9e2050
e88100604bfffc9d
7ea7ab78e9410080
7c9e205038c0000a
7c84f8507d455378
4bfffaed7fa3eb78
893800003b180001
2fa90000e9010060
7d5e4050419e0010
419dfee47fbf5040
4bfffe907e268b78
419e016c2b890073
2b89006f419d006c
2b890070419e00d4
7d21e214409efef0
7f66db7838e00010
9ae900207c8af850
3920000239000020
7fa3eb787f45d378
e88100604bfffc0d
7fa3eb78e8a10078
7c84f8507c9e2050
e88100604bfffb75
38c000107ea7ab78
e96100807c9e2050
4bfffeec7d655b78
38e000087d21e214
7c9e20507f65db78
2b8900784bffff5c
2b89007a419e0018
2b890075419e01cc
3aa000014bfffeb8
38e000107d21e214
7e689b787c8af850
7b291f249ae90020
7fa3eb787f45d378
392000007d72482a
7d665b787f6b5838
4bfffb35f9610080
4bfffb89f9610080
7ea7ab78e8810060
7c9e205038c00008
7d21e2144bffffac
38e0000a39000020
9ae9002038c00001
392000007f45d378
7fa3eb787c8af850
e92100604bfffaf9
e92100609b690000
f921006039290001
7d21e2144bfffe6c
f901009038a0000a
38800000f9410088
9ae900207f43d378
600000004bfff7a9
7f63db78f8610080
600000004bfff8cd
7fa91840e9210080
7c634850409d0040
e9010090e9410088
392300012fa30000
409e00087d4af850
2c29000139200001
3929ffffe8c10060
7ce8305041820010
419d00207faa3840
7f65db78e8810060
7c9e20507fa3eb78
4bfff9cd7c84f850
38e000204bfffdd4
e8e1006098e60000
f8e1006038e70001
2b87006c4bffffb4
409efdb03b200008
4bfffda87cd83378
3b2000022b870068
7cd83378409efd9c
4bfffd903b200001
4bfffd883b200008
3b0100413a600020
993e00004bfffc60
e92100607d455378
f921006039290001
000000004bfffb24
0000128001000000
f9e1ff78f9c1ff70
fa21ff88fa01ff80
fa61ff98fa41ff90
faa1ffa8fa81ffa0
fae1ffb8fac1ffb0
fb21ffc8fb01ffc0
fb61ffd8fb41ffd0
fba1ffe8fb81ffe0
fbe1fff8fbc1fff0
4e800020f8010010
e9e1ff78e9c1ff70
ea21ff88ea01ff80
ea61ff98ea41ff90
eaa1ffa8ea81ffa0
eae1ffb8eac1ffb0
eb21ffc8eb01ffc0
eb61ffd8eb41ffd0
e8010010eb81ffe0
7c0803a6eba1ffe8
ebe1fff8ebc1fff0
ebc1fff04e800020
ebe1fff8e8010010
4e8000207c0803a6
7c9e205038c00010
7d655b78e9610080
7d21e2144bfffeec
7c8af85038e00008
9ae900207e689b78
7f45d3787b291f24
7d72482a7fa3eb78
7f6b583839200000
f96100807d665b78
e88100604bfffb35
38c000087ea7ab78
4bffffac7c9e2050
390000207d21e214
38c0000138e0000a
7f45d3789ae90020
7c8af85039200000
4bfffaf97fa3eb78
9b690000e9210060
39290001e9210060
4bfffe6cf9210060
38a0000a7d21e214
f9410088f9010090
7f43d37838800000
4bfff73d9ae90020
f861008060000000
4bfff8617f63db78
e921008060000000
409d00407fa91840
e94100887c634850
2fa30000e9010090
7d4af85039230001
39200001409e0008
e8c100602c290001
418200103929ffff
7faa38407ce83050
e8810060419d0020
7fa3eb787f65db78
7c84f8507c9e2050
4bfffdd44bfff9cd
98e6000038e00020
38e70001e8e10060
4bffffb4f8e10060
3b2000082b87006c
7cd83378409efdb0
2b8700684bfffda8
409efd9c3b200002
3b2000017cd83378
3b2000084bfffd90
3a6000204bfffd88
4bfffc603b010041
7d455378993e0000
39290001e9210060
4bfffb24f9210060
0100000000000000
f9c1ff7000001280
fa01ff80f9e1ff78
fa41ff90fa21ff88
fa81ffa0fa61ff98
fac1ffb0faa1ffa8
fb01ffc0fae1ffb8
fb41ffd0fb21ffc8
fb81ffe0fb61ffd8
fbc1fff0fba1ffe8
f8010010fbe1fff8
e9c1ff704e800020
ea01ff80e9e1ff78
ea41ff90ea21ff88
ea81ffa0ea61ff98
eac1ffb0eaa1ffa8
eb01ffc0eae1ffb8
eb41ffd0eb21ffc8
eb81ffe0eb61ffd8
eba1ffe8e8010010
ebc1fff07c0803a6
4e800020ebe1fff8
e8010010ebc1fff0
7c0803a6ebe1fff8
000000004e800020
6d6f636c65570a0a
63694d206f742065
2120747461776f72
@ -1124,6 +1160,7 @@ ebe1fff8e8010010
0000000000000000
0000002054524155
000000204d415244
000000204d415242
2020202020202020
203a4d4152422020
0a424b20646c6c25
@ -1132,6 +1169,10 @@ ebe1fff8e8010010
203a4d4152442020
0a424d20646c6c25
0000000000000000
4152442020202020
203a54494e49204d
0a424b20646c6c25
0000000000000000
2020202020202020
203a4b4c43202020
7a484d20646c6c25
@ -1148,6 +1189,13 @@ ebe1fff8e8010010
20676e69746f6f42
415242206d6f7266
0000000a2e2e2e4d
20676e6979706f43
2064616f6c796170
2e4d415244206f74
00000000000a2e2e
20676e69746f6f42
415244206d6f7266
0000000a2e2e2e4d
20747365746d654d
6c69616620737562
252f6425203a6465

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-22 17:57:20
// Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-26 20:37:42
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,

@ -130,6 +130,7 @@ targets:
- ram_init_file
- use_litedram=true
- disable_flatten_core
- no_bram
generate: [dram_nexys_video]
tools:
vivado: {part : xc7a200tsbg484-1}
@ -156,6 +157,7 @@ targets:
- ram_init_file
- use_litedram=true
- disable_flatten_core
- no_bram
generate: [dram_arty]
tools:
vivado: {part : xc7a35ticsg324-1L}
@ -182,6 +184,7 @@ targets:
- ram_init_file
- use_litedram=true
- disable_flatten_core
- no_bram
generate: [dram_arty]
tools:
vivado: {part : xc7a100ticsg324-1L}
@ -219,7 +222,7 @@ generate:
parameters:
memory_size:
datatype : int
description : On-chip memory size (bytes)
description : On-chip memory size (bytes). If no_bram is set, this is the size carved out for the DRAM payload
paramtype : generic
default : 16384

@ -256,3 +259,9 @@ parameters:
description : Use liteDRAM
paramtype : generic
default : false

no_bram:
datatype : bool
description : No internal block RAM (only DRAM and init code carrying payload)
paramtype : generic
default : false

@ -26,14 +26,15 @@ use work.wishbone_types.all;

entity soc is
generic (
MEMORY_SIZE : positive;
RAM_INIT_FILE : string;
RESET_LOW : boolean;
CLK_FREQ : positive;
SIM : boolean;
MEMORY_SIZE : natural;
RAM_INIT_FILE : string;
RESET_LOW : boolean;
CLK_FREQ : positive;
SIM : boolean;
DISABLE_FLATTEN_CORE : boolean := false;
HAS_DRAM : boolean := false;
DRAM_SIZE : integer := 0
HAS_DRAM : boolean := false;
DRAM_SIZE : integer := 0;
DRAM_INIT_SIZE : integer := 0
);
port(
rst : in std_ulogic;
@ -105,7 +106,6 @@ architecture behaviour of soc is
-- Main memory signals:
signal wb_bram_in : wishbone_master_out;
signal wb_bram_out : wishbone_slave_out;
constant mem_adr_bits : positive := positive(ceil(log2(real(MEMORY_SIZE))));

-- DMI debug bus signals
signal dmi_addr : std_ulogic_vector(7 downto 0);
@ -466,6 +466,7 @@ begin
HAS_DRAM => HAS_DRAM,
BRAM_SIZE => MEMORY_SIZE,
DRAM_SIZE => DRAM_SIZE,
DRAM_INIT_SIZE => DRAM_INIT_SIZE,
CLK_FREQ => CLK_FREQ
)
port map(
@ -516,17 +517,25 @@ begin
);

-- BRAM Memory slave
bram0: entity work.wishbone_bram_wrapper
generic map(
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE
)
port map(
clk => system_clk,
rst => rst_bram,
wishbone_in => wb_bram_in,
wishbone_out => wb_bram_out
);
bram: if MEMORY_SIZE /= 0 generate
bram0: entity work.wishbone_bram_wrapper
generic map(
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE
)
port map(
clk => system_clk,
rst => rst_bram,
wishbone_in => wb_bram_in,
wishbone_out => wb_bram_out
);
end generate;

no_bram: if MEMORY_SIZE = 0 generate
wb_bram_out.ack <= wb_bram_in.cyc and wb_bram_in.stb;
wb_bram_out.dat <= x"FFFFFFFFFFFFFFFF";
wb_bram_out.stall <= wb_bram_in.cyc and not wb_bram_out.ack;
end generate;

-- DMI(debug bus) <-> JTAG bridge
dtm: entity work.dmi_dtm

@ -8,12 +8,13 @@ use work.wishbone_types.all;

entity syscon is
generic (
SIG_VALUE : std_ulogic_vector(63 downto 0) := x"f00daa5500010001";
CLK_FREQ : integer;
HAS_UART : boolean;
HAS_DRAM : boolean;
BRAM_SIZE : integer;
DRAM_SIZE : integer
SIG_VALUE : std_ulogic_vector(63 downto 0) := x"f00daa5500010001";
CLK_FREQ : integer;
HAS_UART : boolean;
HAS_DRAM : boolean;
BRAM_SIZE : integer;
DRAM_SIZE : integer;
DRAM_INIT_SIZE : integer
);
port (
clk : in std_ulogic;
@ -36,12 +37,13 @@ architecture behaviour of syscon is
constant SYS_REG_BITS : positive := 3;

-- Register addresses (matches wishbone addr downto 3, ie, 8 bytes per reg)
constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000";
constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001";
constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "010";
constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "011";
constant SYS_REG_CLKINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "100";
constant SYS_REG_CTRL : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "101";
constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000";
constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001";
constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "010";
constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "011";
constant SYS_REG_CLKINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "100";
constant SYS_REG_CTRL : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "101";
constant SYS_REG_DRAMINITINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "110";

-- Muxed reg read signal
signal reg_out : std_ulogic_vector(63 downto 0);
@ -49,6 +51,7 @@ architecture behaviour of syscon is
-- INFO register bits
constant SYS_REG_INFO_HAS_UART : integer := 0;
constant SYS_REG_INFO_HAS_DRAM : integer := 1;
constant SYS_REG_INFO_HAS_BRAM : integer := 2;

-- BRAMINFO contains the BRAM size in the bottom 52 bits
-- DRAMINFO contains the DRAM size if any in the bottom 52 bits
@ -69,14 +72,16 @@ architecture behaviour of syscon is
signal reg_info : std_ulogic_vector(63 downto 0);
signal reg_braminfo : std_ulogic_vector(63 downto 0);
signal reg_draminfo : std_ulogic_vector(63 downto 0);
signal reg_dramiinfo : std_ulogic_vector(63 downto 0);
signal reg_clkinfo : std_ulogic_vector(63 downto 0);
signal info_has_dram : std_ulogic;
signal info_has_bram : std_ulogic;
signal info_has_uart : std_ulogic;
signal info_clk : std_ulogic_vector(39 downto 0);
begin

-- Generated output signals
dram_at_0 <= reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
dram_at_0 <= '1' when BRAM_SIZE = 0 else reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
soc_reset <= reg_ctrl(SYS_REG_CTRL_SOC_RESET);
core_reset <= reg_ctrl(SYS_REG_CTRL_CORE_RESET);

@ -87,13 +92,17 @@ begin
-- Info register is hard wired
info_has_uart <= '1' when HAS_UART else '0';
info_has_dram <= '1' when HAS_DRAM else '0';
info_has_bram <= '1' when BRAM_SIZE /= 0 else '0';
info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
reg_info <= (0 => info_has_uart,
1 => info_has_dram,
2 => info_has_bram,
others => '0');
reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52));
reg_draminfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_SIZE, 52)) when HAS_DRAM
else (others => '0');
reg_dramiinfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_INIT_SIZE, 52)) when HAS_DRAM
else (others => '0');
reg_clkinfo <= (39 downto 0 => info_clk,
others => '0');

@ -107,6 +116,7 @@ begin
reg_info when SYS_REG_INFO,
reg_braminfo when SYS_REG_BRAMINFO,
reg_draminfo when SYS_REG_DRAMINFO,
reg_dramiinfo when SYS_REG_DRAMINITINFO,
reg_clkinfo when SYS_REG_CLKINFO,
reg_ctrl_out when SYS_REG_CTRL,
(others => '0') when others;
@ -136,6 +146,11 @@ begin
if reg_ctrl(SYS_REG_CTRL_CORE_RESET) = '1' then
reg_ctrl(SYS_REG_CTRL_CORE_RESET) <= '0';
end if;

-- If BRAM doesn't exist, force DRAM at 0
if BRAM_SIZE = 0 then
reg_ctrl(SYS_REG_CTRL_DRAM_AT_0) <= '1';
end if;
end if;
end if;
end process;

@ -7,7 +7,7 @@ package utils is
function log2(i : natural) return integer;
function log2ceil(i : natural) return integer;
function ispow2(i : integer) return boolean;

function round_up(i : integer; s : integer) return integer;
end utils;

package body utils is
@ -43,5 +43,9 @@ package body utils is
end if;
end function;

function round_up(i : integer; s : integer) return integer is
begin
return ((i + (s - 1)) / s) * s;
end function;
end utils;


Loading…
Cancel
Save