mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-15 23:51:40 +00:00
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
32
litedram/gen-src/sdram_init/libc/include/limits.h
Normal file
32
litedram/gen-src/sdram_init/libc/include/limits.h
Normal file
@@ -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;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
vexriscv
|
||||
@@ -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
@@ -1 +0,0 @@
|
||||
vexriscv
|
||||
@@ -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
Reference in New Issue
Block a user