litedram: Add support for Microwatt-initialized controller

This adds support for initializing the memory controller from microwatt
rather than using a built-in RiscV processor. This might require some
fixes to LiteX and LiteDRAM (they haven't been merged as of this commit
yet).

This is enabled in the shipped generated files and can be changed via
modifying the generator script to pass False to "mw_init"

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
pull/170/head
Benjamin Herrenschmidt 5 years ago
parent c5f5f50738
commit 7f1f6b8525

@ -39,4 +39,5 @@
# CSR Port ----------------------------------------------------------------- # CSR Port -----------------------------------------------------------------
"csr_expose": "False", # expose access to CSR (I/O) ports "csr_expose": "False", # expose access to CSR (I/O) ports
"csr_align" : 32, # CSR alignment "csr_align" : 32, # CSR alignment
"csr_base" : 0xc0100000 # For cpu=None only
} }

@ -35,7 +35,7 @@ def build_init_code(build_dir):


# More path fudging # More path fudging
sw_dir = os.path.join(build_dir, "software"); sw_dir = os.path.join(build_dir, "software");
sw_inc_dir = os.path.join(build_dir, "include") sw_inc_dir = os.path.join(sw_dir, "include")
gen_inc_dir = os.path.join(sw_inc_dir, "generated") gen_inc_dir = os.path.join(sw_inc_dir, "generated")
src_dir = os.path.join(gen_src_dir, "sdram_init") src_dir = os.path.join(gen_src_dir, "sdram_init")
lxbios_src_dir = os.path.join(soc_directory, "software", "bios") lxbios_src_dir = os.path.join(soc_directory, "software", "bios")
@ -59,7 +59,7 @@ def build_init_code(build_dir):


add_var("BUILD_DIR", sw_dir) add_var("BUILD_DIR", sw_dir)
add_var("SRC_DIR", src_dir) add_var("SRC_DIR", src_dir)
add_var("GENINC_DIR", gen_inc_dir) add_var("GENINC_DIR", sw_inc_dir)
add_var("LXSRC_DIR", lxbios_src_dir) add_var("LXSRC_DIR", lxbios_src_dir)
add_var("LXINC_DIR", lxbios_inc_dir) add_var("LXINC_DIR", lxbios_inc_dir)
write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars)) write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars))
@ -72,7 +72,7 @@ def build_init_code(build_dir):


return os.path.join(sw_dir, "obj", "sdram_init.hex") return os.path.join(sw_dir, "obj", "sdram_init.hex")


def generate_one(t): def generate_one(t, mw_init):


print("Generating target:", t) print("Generating target:", t)


@ -101,6 +101,12 @@ def generate_one(t):
if k == "sdram_phy": if k == "sdram_phy":
core_config[k] = getattr(litedram_phys, core_config[k]) core_config[k] = getattr(litedram_phys, core_config[k])


# Override values for mw_init
if mw_init:
core_config["cpu"] = None
core_config["csr_expose"] = True
core_config["csr_align"] = 64

# Generate core # Generate core
if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]: if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
platform = LatticePlatform("LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis") platform = LatticePlatform("LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis")
@ -120,8 +126,7 @@ def generate_one(t):


# Generate init-cpu.txt if any and generate init code if none # Generate init-cpu.txt if any and generate init code if none
cpu = core_config["cpu"] cpu = core_config["cpu"]
if cpu is None: if mw_init:
print("Microwatt based inits not supported yet !")
src_wrap_file = os.path.join(gen_src_dir, "wrapper-mw-init.vhdl") src_wrap_file = os.path.join(gen_src_dir, "wrapper-mw-init.vhdl")
src_init_file = build_init_code(build_dir) src_init_file = build_init_code(build_dir)
else: else:
@ -141,8 +146,10 @@ def generate_one(t):
def main(): def main():


targets = ['arty','nexys-video'] targets = ['arty','nexys-video']

# XXX Set mw_init to False to use a local VexRiscV for memory inits
for t in targets: for t in targets:
generate_one(t) generate_one(t, mw_init = True)


# XXX TODO: Remove build dir unless told not to via cmdline option # XXX TODO: Remove build dir unless told not to via cmdline option

@ -22,7 +22,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
#### Flags #### Flags


CPPFLAGS = -nostdinc CPPFLAGS = -nostdinc
CPPFLAGS += -I$(SRC_DIR)/libc/include -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../include CPPFLAGS += -I$(SRC_DIR)/libc/include -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../../include
CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include) CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include)
CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks
ASFLAGS = $(CPPFLAGS) $(CFLAGS) ASFLAGS = $(CPPFLAGS) $(CFLAGS)
@ -30,7 +30,7 @@ LDFLAGS = -static -nostdlib -Ttext-segment=0xffff0000 -T $(SRC_DIR)/$(PROGRAM).l


#### Pretty print #### Pretty print


ifeq ($(VERBOSE),1) ifeq ($(V),1)
define Q define Q
$(2) $(2)
endef endef

@ -1,3 +1,17 @@
static inline void flush_cpu_dcache(void) { } static inline void flush_cpu_dcache(void) { }
static inline void flush_l2_cache(void) { } static inline void flush_l2_cache(void) { }


#define CONFIG_CPU_NOP "nop"
#define CONFIG_CLOCK_FREQUENCY 100000000

static inline void timer0_en_write(int e) { }
static inline void timer0_reload_write(int r) { }
static inline void timer0_load_write(int l) { }
static inline void timer0_update_value_write(int v) { }
static inline uint64_t timer0_value_read(void)
{
uint64_t val;

__asm__ volatile ("mfdec %0" : "=r" (val));
return val;
}

@ -0,0 +1,32 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _LIMITS_H
#define _LIMITS_H

#define UCHAR_MAX 255
#define SCHAR_MAX 127
#define SCHAR_MIN (-128)

#define USHRT_MAX 65535
#define SHRT_MAX 32767
#define SHRT_MIN (-32768)

#define UINT_MAX (4294967295U)
#define INT_MAX 2147483647
#define INT_MIN (-2147483648)

#define ULONG_MAX ((unsigned long)-1L)
#define LONG_MAX (ULONG_MAX/2)
#define LONG_MIN ((-LONG_MAX)-1)

#endif

@ -121,7 +121,7 @@ void main(void)
* not happy otherwise. The PLL might need to settle ? * not happy otherwise. The PLL might need to settle ?
*/ */
potato_uart_init(); potato_uart_init();
for (i = 0; i < 10000; i++) for (i = 0; i < 100000; i++)
potato_uart_reg_read(POTATO_CONSOLE_STATUS); potato_uart_reg_read(POTATO_CONSOLE_STATUS);
printf("\n\nWelcome to Microwatt !\n\n"); printf("\n\nWelcome to Microwatt !\n\n");



@ -45,8 +45,8 @@ entity litedram_wrapper is
ddram_cs_n : out std_ulogic; ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0); ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0); ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : out std_ulogic_vector(1 downto 0); ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : out std_ulogic_vector(1 downto 0); ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic; ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic; ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic; ddram_cke : out std_ulogic;
@ -69,8 +69,8 @@ architecture behaviour of litedram_wrapper is
ddram_cs_n : out std_ulogic; ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0); ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0); ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : out std_ulogic_vector(1 downto 0); ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : out std_ulogic_vector(1 downto 0); ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic; ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic; ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic; ddram_cke : out std_ulogic;
@ -84,17 +84,17 @@ architecture behaviour of litedram_wrapper is
csr_port0_we : in std_ulogic; csr_port0_we : in std_ulogic;
csr_port0_dat_w : in std_ulogic_vector(7 downto 0); csr_port0_dat_w : in std_ulogic_vector(7 downto 0);
csr_port0_dat_r : out std_ulogic_vector(7 downto 0); csr_port0_dat_r : out std_ulogic_vector(7 downto 0);
user_port0_cmd_valid : in std_ulogic; user_port_native_0_cmd_valid : in std_ulogic;
user_port0_cmd_ready : out std_ulogic; user_port_native_0_cmd_ready : out std_ulogic;
user_port0_cmd_we : in std_ulogic; user_port_native_0_cmd_we : in std_ulogic;
user_port0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0); user_port_native_0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port0_wdata_valid : in std_ulogic; user_port_native_0_wdata_valid : in std_ulogic;
user_port0_wdata_ready : out std_ulogic; user_port_native_0_wdata_ready : out std_ulogic;
user_port0_wdata_we : in std_ulogic_vector(15 downto 0); user_port_native_0_wdata_we : in std_ulogic_vector(15 downto 0);
user_port0_wdata_data : in std_ulogic_vector(127 downto 0); user_port_native_0_wdata_data : in std_ulogic_vector(127 downto 0);
user_port0_rdata_valid : out std_ulogic; user_port_native_0_rdata_valid : out std_ulogic;
user_port0_rdata_ready : in std_ulogic; user_port_native_0_rdata_ready : in std_ulogic;
user_port0_rdata_data : out std_ulogic_vector(127 downto 0) user_port_native_0_rdata_data : out std_ulogic_vector(127 downto 0)
); );
end component; end component;
@ -130,7 +130,7 @@ architecture behaviour of litedram_wrapper is


constant INIT_RAM_SIZE : integer := 16384; constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14; constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "sdram_init.hex"; constant INIT_RAM_FILE : string := "litedram_core.init";


type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0); type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);


@ -176,7 +176,7 @@ begin
end if; end if;
wb_init_out.ack <= not wb_init_out.ack; wb_init_out.ack <= not wb_init_out.ack;
end if; end if;
end if; end if;
end process; end process;


wb_init_in.adr <= wb_in.adr; wb_init_in.adr <= wb_in.adr;
@ -205,7 +205,7 @@ begin
-- DRAM CSR interface signals. We only support access to the bottom byte -- DRAM CSR interface signals. We only support access to the bottom byte
csr_valid <= wb_in.cyc and wb_in.stb and wb_is_csr; csr_valid <= wb_in.cyc and wb_in.stb and wb_is_csr;
csr_write_valid <= wb_in.we and wb_in.sel(0); csr_write_valid <= wb_in.we and wb_in.sel(0);
csr_port0_adr <= wb_in.adr(15 downto 3) & '0' when wb_is_csr = '1' else (others => '0'); csr_port0_adr <= wb_in.adr(13 downto 0) when wb_is_csr = '1' else (others => '0');
csr_port0_dat_w <= wb_in.dat(7 downto 0); csr_port0_dat_w <= wb_in.dat(7 downto 0);
csr_port0_we <= (csr_valid and csr_write_valid) when state = CMD else '0'; csr_port0_we <= (csr_valid and csr_write_valid) when state = CMD else '0';


@ -287,17 +287,17 @@ begin
csr_port0_we => csr_port0_we, csr_port0_we => csr_port0_we,
csr_port0_dat_w => csr_port0_dat_w, csr_port0_dat_w => csr_port0_dat_w,
csr_port0_dat_r => csr_port0_dat_r, csr_port0_dat_r => csr_port0_dat_r,
user_port0_cmd_valid => user_port0_cmd_valid, user_port_native_0_cmd_valid => user_port0_cmd_valid,
user_port0_cmd_ready => user_port0_cmd_ready, user_port_native_0_cmd_ready => user_port0_cmd_ready,
user_port0_cmd_we => user_port0_cmd_we, user_port_native_0_cmd_we => user_port0_cmd_we,
user_port0_cmd_addr => user_port0_cmd_addr, user_port_native_0_cmd_addr => user_port0_cmd_addr,
user_port0_wdata_valid => user_port0_wdata_valid, user_port_native_0_wdata_valid => user_port0_wdata_valid,
user_port0_wdata_ready => user_port0_wdata_ready, user_port_native_0_wdata_ready => user_port0_wdata_ready,
user_port0_wdata_we => user_port0_wdata_we, user_port_native_0_wdata_we => user_port0_wdata_we,
user_port0_wdata_data => user_port0_wdata_data, user_port_native_0_wdata_data => user_port0_wdata_data,
user_port0_rdata_valid => user_port0_rdata_valid, user_port_native_0_rdata_valid => user_port0_rdata_valid,
user_port0_rdata_ready => user_port0_rdata_ready, user_port_native_0_rdata_ready => user_port0_rdata_ready,
user_port0_rdata_data => user_port0_rdata_data user_port_native_0_rdata_data => user_port0_rdata_data
); );


end architecture behaviour; end architecture behaviour;

@ -60,8 +60,6 @@ architecture behaviour of litedram_wrapper is
component litedram_core port ( component litedram_core port (
clk : in std_ulogic; clk : in std_ulogic;
rst : in std_ulogic; rst : in std_ulogic;
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;
pll_locked : out std_ulogic; pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0); ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0); ddram_ba : out std_ulogic_vector(2 downto 0);
@ -82,6 +80,10 @@ architecture behaviour of litedram_wrapper is
init_error : out std_ulogic; init_error : out std_ulogic;
user_clk : out std_ulogic; user_clk : out std_ulogic;
user_rst : out std_ulogic; user_rst : out std_ulogic;
csr_port0_adr : in std_ulogic_vector(13 downto 0);
csr_port0_we : in std_ulogic;
csr_port0_dat_w : in std_ulogic_vector(7 downto 0);
csr_port0_dat_r : out std_ulogic_vector(7 downto 0);
user_port_native_0_cmd_valid : in std_ulogic; user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic; user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_we : in std_ulogic; user_port_native_0_cmd_we : in std_ulogic;
@ -112,17 +114,84 @@ architecture behaviour of litedram_wrapper is


signal dram_user_reset : std_ulogic; signal dram_user_reset : std_ulogic;


type state_t is (CMD, MWRITE, MREAD); signal csr_port0_adr : std_ulogic_vector(13 downto 0);
signal csr_port0_we : std_ulogic;
signal csr_port0_dat_w : std_ulogic_vector(7 downto 0);
signal csr_port0_dat_r : std_ulogic_vector(7 downto 0);
signal csr_port_read_comb : std_ulogic_vector(63 downto 0);
signal csr_valid : std_ulogic;
signal csr_write_valid : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;

type state_t is (CMD, MWRITE, MREAD, CSR);
signal state : state_t; signal state : state_t;


constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);

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;
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) := temp_word;
end loop;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);

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

begin begin


-- Address bit 3 selects the top or bottom half of the data -- BRAM Memory slave
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
for i in 0 to 7 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_init_out.ack <= not wb_init_out.ack;
end if;
end if;
end process;

wb_init_in.adr <= wb_in.adr;
wb_init_in.dat <= wb_in.dat;
wb_init_in.sel <= wb_in.sel;
wb_init_in.we <= wb_in.we;
wb_init_in.stb <= wb_in.stb;
wb_init_in.cyc <= wb_in.cyc and wb_is_init;

-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface) -- bus (64-bit wishbone vs. 128-bit DRAM interface)
-- --
ad3 <= wb_in.adr(3); ad3 <= wb_in.adr(3);


-- DRAM interface signals -- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init) user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init)
when state = CMD else '0'; when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0'; user_port0_cmd_we <= wb_in.we when state = CMD else '0';
@ -133,18 +202,32 @@ begin
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel; "00000000" & wb_in.sel;


-- Wishbone out signals. CSR and init memory do nothing, just ack -- DRAM CSR interface signals. We only support access to the bottom byte
wb_out.ack <= '1' when (wb_is_csr = '1' or wb_is_init = '1') else csr_valid <= wb_in.cyc and wb_in.stb and wb_is_csr;
csr_write_valid <= wb_in.we and wb_in.sel(0);
csr_port0_adr <= wb_in.adr(13 downto 0) when wb_is_csr = '1' else (others => '0');
csr_port0_dat_w <= wb_in.dat(7 downto 0);
csr_port0_we <= (csr_valid and csr_write_valid) when state = CMD else '0';

-- Wishbone out signals
wb_out.ack <= '1' when state = CSR else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0'; user_port0_rdata_valid when state = MREAD else '0';
wb_out.dat <= (others => '0') when (wb_is_csr = '1' or wb_is_init = '1') else
csr_port_read_comb <= x"00000000000000" & csr_port0_dat_r;
wb_out.dat <= csr_port_read_comb when wb_is_csr = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0); user_port0_rdata_data(63 downto 0);
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack; wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;


-- Reset, lift it when init done, no alt core reset -- Reset ignored, the reset controller use the pll lock signal,
system_reset <= dram_user_reset or not init_done; -- and alternate core reset address set when DRAM is not initialized.
core_alt_reset <= '0'; --
system_reset <= '0';
core_alt_reset <= not init_done;


-- State machine -- State machine
sm: process(system_clk) sm: process(system_clk)
@ -156,7 +239,9 @@ begin
else else
case state is case state is
when CMD => when CMD =>
if (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then if csr_valid = '1' then
state <= CSR;
elsif (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD; state <= MWRITE when wb_in.we = '1' else MREAD;
end if; end if;
when MWRITE => when MWRITE =>
@ -167,6 +252,8 @@ begin
if user_port0_rdata_valid = '1' then if user_port0_rdata_valid = '1' then
state <= CMD; state <= CMD;
end if; end if;
when CSR =>
state <= CMD;
end case; end case;
end if; end if;
end if; end if;
@ -176,8 +263,6 @@ begin
port map( port map(
clk => clk_in, clk => clk_in,
rst => rst, rst => rst,
serial_tx => serial_tx,
serial_rx => serial_rx,
pll_locked => pll_locked, pll_locked => pll_locked,
ddram_a => ddram_a, ddram_a => ddram_a,
ddram_ba => ddram_ba, ddram_ba => ddram_ba,
@ -198,6 +283,10 @@ begin
init_error => init_error, init_error => init_error,
user_clk => system_clk, user_clk => system_clk,
user_rst => dram_user_reset, user_rst => dram_user_reset,
csr_port0_adr => csr_port0_adr,
csr_port0_we => csr_port0_we,
csr_port0_dat_w => csr_port0_dat_w,
csr_port0_dat_r => csr_port0_dat_r,
user_port_native_0_cmd_valid => user_port0_cmd_valid, user_port_native_0_cmd_valid => user_port0_cmd_valid,
user_port_native_0_cmd_ready => user_port0_cmd_ready, user_port_native_0_cmd_ready => user_port0_cmd_ready,
user_port_native_0_cmd_we => user_port0_cmd_we, user_port_native_0_cmd_we => user_port0_cmd_we,

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -60,8 +60,6 @@ architecture behaviour of litedram_wrapper is
component litedram_core port ( component litedram_core port (
clk : in std_ulogic; clk : in std_ulogic;
rst : in std_ulogic; rst : in std_ulogic;
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;
pll_locked : out std_ulogic; pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0); ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0); ddram_ba : out std_ulogic_vector(2 downto 0);
@ -82,6 +80,10 @@ architecture behaviour of litedram_wrapper is
init_error : out std_ulogic; init_error : out std_ulogic;
user_clk : out std_ulogic; user_clk : out std_ulogic;
user_rst : out std_ulogic; user_rst : out std_ulogic;
csr_port0_adr : in std_ulogic_vector(13 downto 0);
csr_port0_we : in std_ulogic;
csr_port0_dat_w : in std_ulogic_vector(7 downto 0);
csr_port0_dat_r : out std_ulogic_vector(7 downto 0);
user_port_native_0_cmd_valid : in std_ulogic; user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic; user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_we : in std_ulogic; user_port_native_0_cmd_we : in std_ulogic;
@ -112,17 +114,84 @@ architecture behaviour of litedram_wrapper is


signal dram_user_reset : std_ulogic; signal dram_user_reset : std_ulogic;


type state_t is (CMD, MWRITE, MREAD); signal csr_port0_adr : std_ulogic_vector(13 downto 0);
signal csr_port0_we : std_ulogic;
signal csr_port0_dat_w : std_ulogic_vector(7 downto 0);
signal csr_port0_dat_r : std_ulogic_vector(7 downto 0);
signal csr_port_read_comb : std_ulogic_vector(63 downto 0);
signal csr_valid : std_ulogic;
signal csr_write_valid : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;

type state_t is (CMD, MWRITE, MREAD, CSR);
signal state : state_t; signal state : state_t;


constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);

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;
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) := temp_word;
end loop;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);

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

begin begin


-- Address bit 3 selects the top or bottom half of the data -- BRAM Memory slave
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
for i in 0 to 7 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_init_out.ack <= not wb_init_out.ack;
end if;
end if;
end process;

wb_init_in.adr <= wb_in.adr;
wb_init_in.dat <= wb_in.dat;
wb_init_in.sel <= wb_in.sel;
wb_init_in.we <= wb_in.we;
wb_init_in.stb <= wb_in.stb;
wb_init_in.cyc <= wb_in.cyc and wb_is_init;

-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface) -- bus (64-bit wishbone vs. 128-bit DRAM interface)
-- --
ad3 <= wb_in.adr(3); ad3 <= wb_in.adr(3);


-- DRAM interface signals -- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init) user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init)
when state = CMD else '0'; when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0'; user_port0_cmd_we <= wb_in.we when state = CMD else '0';
@ -133,18 +202,32 @@ begin
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel; "00000000" & wb_in.sel;


-- Wishbone out signals. CSR and init memory do nothing, just ack -- DRAM CSR interface signals. We only support access to the bottom byte
wb_out.ack <= '1' when (wb_is_csr = '1' or wb_is_init = '1') else csr_valid <= wb_in.cyc and wb_in.stb and wb_is_csr;
csr_write_valid <= wb_in.we and wb_in.sel(0);
csr_port0_adr <= wb_in.adr(13 downto 0) when wb_is_csr = '1' else (others => '0');
csr_port0_dat_w <= wb_in.dat(7 downto 0);
csr_port0_we <= (csr_valid and csr_write_valid) when state = CMD else '0';

-- Wishbone out signals
wb_out.ack <= '1' when state = CSR else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0'; user_port0_rdata_valid when state = MREAD else '0';
wb_out.dat <= (others => '0') when (wb_is_csr = '1' or wb_is_init = '1') else
csr_port_read_comb <= x"00000000000000" & csr_port0_dat_r;
wb_out.dat <= csr_port_read_comb when wb_is_csr = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0); user_port0_rdata_data(63 downto 0);
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack; wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;


-- Reset, lift it when init done, no alt core reset -- Reset ignored, the reset controller use the pll lock signal,
system_reset <= dram_user_reset or not init_done; -- and alternate core reset address set when DRAM is not initialized.
core_alt_reset <= '0'; --
system_reset <= '0';
core_alt_reset <= not init_done;


-- State machine -- State machine
sm: process(system_clk) sm: process(system_clk)
@ -156,7 +239,9 @@ begin
else else
case state is case state is
when CMD => when CMD =>
if (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then if csr_valid = '1' then
state <= CSR;
elsif (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD; state <= MWRITE when wb_in.we = '1' else MREAD;
end if; end if;
when MWRITE => when MWRITE =>
@ -167,6 +252,8 @@ begin
if user_port0_rdata_valid = '1' then if user_port0_rdata_valid = '1' then
state <= CMD; state <= CMD;
end if; end if;
when CSR =>
state <= CMD;
end case; end case;
end if; end if;
end if; end if;
@ -176,8 +263,6 @@ begin
port map( port map(
clk => clk_in, clk => clk_in,
rst => rst, rst => rst,
serial_tx => serial_tx,
serial_rx => serial_rx,
pll_locked => pll_locked, pll_locked => pll_locked,
ddram_a => ddram_a, ddram_a => ddram_a,
ddram_ba => ddram_ba, ddram_ba => ddram_ba,
@ -198,6 +283,10 @@ begin
init_error => init_error, init_error => init_error,
user_clk => system_clk, user_clk => system_clk,
user_rst => dram_user_reset, user_rst => dram_user_reset,
csr_port0_adr => csr_port0_adr,
csr_port0_we => csr_port0_we,
csr_port0_dat_w => csr_port0_dat_w,
csr_port0_dat_r => csr_port0_dat_r,
user_port_native_0_cmd_valid => user_port0_cmd_valid, user_port_native_0_cmd_valid => user_port0_cmd_valid,
user_port_native_0_cmd_ready => user_port0_cmd_ready, user_port_native_0_cmd_ready => user_port0_cmd_ready,
user_port_native_0_cmd_we => user_port0_cmd_we, user_port_native_0_cmd_we => user_port0_cmd_we,

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -17,6 +17,7 @@ use work.wishbone_types.all;
-- 0xc0000000: SYSCON -- 0xc0000000: SYSCON
-- 0xc0002000: UART0 -- 0xc0002000: UART0
-- 0xc0004000: XICS ICP -- 0xc0004000: XICS ICP
-- 0xc0100000: DRAM CSRs
-- 0xf0000000: Block RAM (aliased & repeated) -- 0xf0000000: Block RAM (aliased & repeated)
-- 0xffff0000: DRAM init code (if any) -- 0xffff0000: DRAM init code (if any)



Loading…
Cancel
Save