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 4 years ago
parent c5f5f50738
commit 7f1f6b8525

@ -39,4 +39,5 @@
# CSR Port -----------------------------------------------------------------
"csr_expose": "False", # expose access to CSR (I/O) ports
"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
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")
src_dir = os.path.join(gen_src_dir, "sdram_init")
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("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("LXINC_DIR", lxbios_inc_dir)
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")

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

print("Generating target:", t)

@ -101,6 +101,12 @@ def generate_one(t):
if k == "sdram_phy":
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
if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
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
cpu = core_config["cpu"]
if cpu is None:
print("Microwatt based inits not supported yet !")
if mw_init:
src_wrap_file = os.path.join(gen_src_dir, "wrapper-mw-init.vhdl")
src_init_file = build_init_code(build_dir)
else:
@ -141,8 +146,10 @@ def generate_one(t):
def main():

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

# XXX Set mw_init to False to use a local VexRiscV for memory inits
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

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

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)
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)
@ -30,7 +30,7 @@ LDFLAGS = -static -nostdlib -Ttext-segment=0xffff0000 -T $(SRC_DIR)/$(PROGRAM).l

#### Pretty print

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

@ -1,3 +1,17 @@
static inline void flush_cpu_dcache(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 ?
*/
potato_uart_init();
for (i = 0; i < 10000; i++)
for (i = 0; i < 100000; i++)
potato_uart_reg_read(POTATO_CONSOLE_STATUS);
printf("\n\nWelcome to Microwatt !\n\n");


@ -45,8 +45,8 @@ entity litedram_wrapper is
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : out std_ulogic_vector(1 downto 0);
ddram_dqs_n : out std_ulogic_vector(1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : 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_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : out std_ulogic_vector(1 downto 0);
ddram_dqs_n : out std_ulogic_vector(1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : 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_dat_w : in 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_port0_cmd_ready : out std_ulogic;
user_port0_cmd_we : in std_ulogic;
user_port0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port0_wdata_valid : in std_ulogic;
user_port0_wdata_ready : out std_ulogic;
user_port0_wdata_we : in std_ulogic_vector(15 downto 0);
user_port0_wdata_data : in std_ulogic_vector(127 downto 0);
user_port0_rdata_valid : out std_ulogic;
user_port0_rdata_ready : in std_ulogic;
user_port0_rdata_data : out std_ulogic_vector(127 downto 0)
user_port_native_0_cmd_valid : in 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_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port_native_0_wdata_valid : in std_ulogic;
user_port_native_0_wdata_ready : out std_ulogic;
user_port_native_0_wdata_we : in std_ulogic_vector(15 downto 0);
user_port_native_0_wdata_data : in std_ulogic_vector(127 downto 0);
user_port_native_0_rdata_valid : out std_ulogic;
user_port_native_0_rdata_ready : in std_ulogic;
user_port_native_0_rdata_data : out std_ulogic_vector(127 downto 0)
);
end component;
@ -130,7 +130,7 @@ architecture behaviour of litedram_wrapper is

constant INIT_RAM_SIZE : integer := 16384;
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);

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

wb_init_in.adr <= wb_in.adr;
@ -205,7 +205,7 @@ begin
-- 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_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_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_dat_w => csr_port0_dat_w,
csr_port0_dat_r => csr_port0_dat_r,
user_port0_cmd_valid => user_port0_cmd_valid,
user_port0_cmd_ready => user_port0_cmd_ready,
user_port0_cmd_we => user_port0_cmd_we,
user_port0_cmd_addr => user_port0_cmd_addr,
user_port0_wdata_valid => user_port0_wdata_valid,
user_port0_wdata_ready => user_port0_wdata_ready,
user_port0_wdata_we => user_port0_wdata_we,
user_port0_wdata_data => user_port0_wdata_data,
user_port0_rdata_valid => user_port0_rdata_valid,
user_port0_rdata_ready => user_port0_rdata_ready,
user_port0_rdata_data => user_port0_rdata_data
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_we => user_port0_cmd_we,
user_port_native_0_cmd_addr => user_port0_cmd_addr,
user_port_native_0_wdata_valid => user_port0_wdata_valid,
user_port_native_0_wdata_ready => user_port0_wdata_ready,
user_port_native_0_wdata_we => user_port0_wdata_we,
user_port_native_0_wdata_data => user_port0_wdata_data,
user_port_native_0_rdata_valid => user_port0_rdata_valid,
user_port_native_0_rdata_ready => user_port0_rdata_ready,
user_port_native_0_rdata_data => user_port0_rdata_data
);

end architecture behaviour;

@ -60,8 +60,6 @@ architecture behaviour of litedram_wrapper is
component litedram_core port (
clk : in std_ulogic;
rst : in std_ulogic;
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;
pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 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;
user_clk : 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_ready : out 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;

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;

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

-- 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)
--
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)
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
"00000000" & wb_in.sel;

-- Wishbone out signals. CSR and init memory do nothing, just ack
wb_out.ack <= '1' when (wb_is_csr = '1' or wb_is_init = '1') else
-- 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_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_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(63 downto 0);
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;

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

-- State machine
sm: process(system_clk)
@ -156,7 +239,9 @@ begin
else
case state is
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;
end if;
when MWRITE =>
@ -167,6 +252,8 @@ begin
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
when CSR =>
state <= CMD;
end case;
end if;
end if;
@ -176,8 +263,6 @@ begin
port map(
clk => clk_in,
rst => rst,
serial_tx => serial_tx,
serial_rx => serial_rx,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
@ -198,6 +283,10 @@ begin
init_error => init_error,
user_clk => system_clk,
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_ready => user_port0_cmd_ready,
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 (
clk : in std_ulogic;
rst : in std_ulogic;
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;
pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 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;
user_clk : 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_ready : out 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;

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;

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

-- 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)
--
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)
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
"00000000" & wb_in.sel;

-- Wishbone out signals. CSR and init memory do nothing, just ack
wb_out.ack <= '1' when (wb_is_csr = '1' or wb_is_init = '1') else
-- 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_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_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(63 downto 0);
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;

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

-- State machine
sm: process(system_clk)
@ -156,7 +239,9 @@ begin
else
case state is
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;
end if;
when MWRITE =>
@ -167,6 +252,8 @@ begin
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
when CSR =>
state <= CMD;
end case;
end if;
end if;
@ -176,8 +263,6 @@ begin
port map(
clk => clk_in,
rst => rst,
serial_tx => serial_tx,
serial_rx => serial_rx,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
@ -198,6 +283,10 @@ begin
init_error => init_error,
user_clk => system_clk,
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_ready => user_port0_cmd_ready,
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
-- 0xc0002000: UART0
-- 0xc0004000: XICS ICP
-- 0xc0100000: DRAM CSRs
-- 0xf0000000: Block RAM (aliased & repeated)
-- 0xffff0000: DRAM init code (if any)


Loading…
Cancel
Save