Merge pull request #178 from antonblanchard/intercon

Interconnect timing improvements from Ben
pull/185/head
Anton Blanchard 5 years ago committed by GitHub
commit 84ab28b3d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -399,10 +399,6 @@ package common is
write_cr_mask => (others => '0'),
write_cr_data => (others => '0'));

type XicsToExecute1Type is record
irq : std_ulogic;
end record;

end common;

package body common is

@ -34,7 +34,7 @@ entity core is
dmi_wr : in std_ulogic;
dmi_ack : out std_ulogic;

xics_in : in XicsToExecute1Type;
ext_irq : in std_ulogic;

terminated_out : out std_logic
);
@ -291,8 +291,8 @@ begin
flush_out => flush,
stall_out => ex1_stall_out,
e_in => decode2_to_execute1,
i_in => xics_in,
l_in => loadstore1_to_execute1,
ext_irq_in => ext_irq,
l_out => execute1_to_loadstore1,
f_out => execute1_to_fetch1,
e_out => execute1_to_writeback,

@ -18,6 +18,8 @@ architecture behave of core_tb is
-- Dummy 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;
begin

soc0: entity work.soc
@ -35,6 +37,8 @@ begin
uart0_txd => open,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
wb_dram_ctrl_in => wb_dram_ctrl_in,
wb_dram_ctrl_out => wb_dram_ctrl_out,
alt_reset => '0'
);

@ -59,6 +63,9 @@ begin
-- Dummy DRAM
wb_dram_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
wb_dram_out.dat <= x"FFFFFFFFFFFFFFFF";
wb_dram_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;
wb_dram_out.stall <= '0';
wb_dram_ctrl_out.ack <= wb_dram_ctrl_in.cyc and wb_dram_ctrl_in.stb;
wb_dram_ctrl_out.dat <= x"FFFFFFFF";
wb_dram_ctrl_out.stall <= '0';

end;

@ -25,7 +25,7 @@ entity execute1 is
e_in : in Decode2ToExecute1Type;
l_in : in Loadstore1ToExecute1Type;

i_in : in XicsToExecute1Type;
ext_irq_in : std_ulogic;

-- asynchronous
l_out : out Execute1ToLoadstore1Type;
@ -419,7 +419,7 @@ begin
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#900#, 64));
report "IRQ valid: DEC";
irq_valid := '1';
elsif i_in.irq = '1' then
elsif ext_irq_in = '1' then
ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#500#, 64));
report "IRQ valid: External";
irq_valid := '1';

@ -65,11 +65,15 @@ architecture behaviour of toplevel is
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- DRAM wishbone connection
-- DRAM main data wishbone connection
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_ctrl : std_ulogic;
signal wb_dram_init : std_ulogic;

-- DRAM control wishbone connection
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;

-- Control/status
signal core_alt_reset : std_ulogic;
@ -104,8 +108,10 @@ begin
uart0_rxd => uart_main_rx,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
wb_dram_ctrl => wb_dram_ctrl,
wb_dram_init => wb_dram_init,
wb_dram_ctrl_in => wb_dram_ctrl_in,
wb_dram_ctrl_out => wb_dram_ctrl_out,
wb_dram_is_csr => wb_dram_is_csr,
wb_dram_is_init => wb_dram_is_init,
alt_reset => core_alt_reset
);

@ -195,8 +201,10 @@ begin

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_is_ctrl => wb_dram_ctrl,
wb_is_init => wb_dram_init,
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 => uart_pmod_tx,
serial_rx => uart_pmod_rx,

@ -33,10 +33,16 @@ architecture behaviour of toplevel is
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- Dummy DRAM
-- DRAM main data wishbone connection
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;

-- DRAM control wishbone connection
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;

begin

reset_controller: entity work.soc_reset
@ -79,7 +85,12 @@ begin
rst => soc_rst,
uart0_txd => uart0_txd,
uart0_rxd => uart0_rxd,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
wb_dram_ctrl_in => wb_dram_ctrl_in,
wb_dram_ctrl_out => wb_dram_ctrl_out,
wb_dram_is_csr => wb_dram_is_csr,
wb_dram_is_init => wb_dram_is_init,
alt_reset => '0'
);

@ -87,5 +98,8 @@ begin
wb_dram_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
wb_dram_out.dat <= x"FFFFFFFFFFFFFFFF";
wb_dram_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;
wb_dram_ctrl_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
wb_dram_ctrl_out.dat <= x"FFFFFFFF";
wb_dram_ctrl_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;

end architecture behaviour;

@ -57,11 +57,15 @@ architecture behaviour of toplevel is
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- DRAM wishbone connection
-- DRAM main data wishbone connection
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_ctrl : std_ulogic;
signal wb_dram_init : std_ulogic;

-- DRAM control wishbone connection
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;

-- Control/status
signal core_alt_reset : std_ulogic;
@ -87,8 +91,10 @@ begin
uart0_rxd => uart_main_rx,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
wb_dram_ctrl => wb_dram_ctrl,
wb_dram_init => wb_dram_init,
wb_dram_ctrl_in => wb_dram_ctrl_in,
wb_dram_ctrl_out => wb_dram_ctrl_out,
wb_dram_is_csr => wb_dram_is_csr,
wb_dram_is_init => wb_dram_is_init,
alt_reset => core_alt_reset
);

@ -176,8 +182,10 @@ begin

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_is_ctrl => wb_dram_ctrl,
wb_is_init => wb_dram_init,
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 => '0',

@ -2,9 +2,22 @@
#define __MICROWATT_SOC_H

/*
* Definitions for the syscon registers
* Microwatt SoC memory map
*/

#define MEMORY_BASE 0x00000000 /* "Main" memory alias, either BRAM or DRAM */
#define DRAM_BASE 0x40000000 /* DRAM if present */
#define BRAM_BASE 0x80000000 /* Internal BRAM */

#define SYSCON_BASE 0xc0000000 /* System control regs */
#define UART_BASE 0xc0002000 /* UART */
#define XICS_BASE 0xc0004000 /* Interrupt controller */
#define DRAM_CTRL_BASE 0xc0100000 /* LiteDRAM control registers */
#define DRAM_INIT_BASE 0xf0000000 /* Internal DRAM init firmware */

/*
* Register definitions for the syscon registers
*/
#define SYSCON_BASE 0xc0000000

#define SYS_REG_SIGNATURE 0x00
#define SYS_REG_INFO 0x08
@ -18,9 +31,9 @@
#define SYS_REG_CTRL_CORE_RESET (1ull << 1)
#define SYS_REG_CTRL_SOC_RESET (1ull << 2)

/* Definition for the "Potato" UART */
#define UART_BASE 0xc0002000

/*
* Register definitions for the potato UART
*/
#define POTATO_CONSOLE_TX 0x00
#define POTATO_CONSOLE_RX 0x08
#define POTATO_CONSOLE_STATUS 0x10
@ -31,7 +44,5 @@
#define POTATO_CONSOLE_CLOCK_DIV 0x18
#define POTATO_CONSOLE_IRQ_EN 0x20

/* Definition for the LiteDRAM control registers */
#define DRAM_CTRL_BASE 0xc0100000

#endif /* __MICROWATT_SOC_H */

@ -29,6 +29,8 @@ class LiteDRAMGenerator(Generator):
files.append({f : {'file_type' : 'verilogSource'}})
f = os.path.join(gen_dir, "litedram-wrapper.vhdl")
files.append({f : {'file_type' : 'vhdlSource-2008'}})
f = os.path.join(gen_dir, "litedram-initmem.vhdl")
files.append({f : {'file_type' : 'vhdlSource-2008'}})
f = os.path.join(gen_dir, "litedram_core.init")
files.append({f : {'file_type' : 'user'}})


@ -0,0 +1,72 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;

entity dram_init_mem is
port (
clk : in std_ulogic;
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";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 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*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
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

init_ram_0: process(clk)
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;
end process;

wb_out.stall <= '0';

end architecture rtl;

@ -128,19 +128,23 @@ def generate_one(t, mw_init):
if mw_init:
src_wrap_file = os.path.join(gen_src_dir, "wrapper-mw-init.vhdl")
src_init_file = build_init_code(build_dir)
src_initram_file = os.path.join(gen_src_dir, "dram-init-mem.vhdl")
else:
write_to_file(os.path.join(t_dir, "init-cpu.txt"), cpu)
src_wrap_file = os.path.join(gen_src_dir, "wrapper-self-init.vhdl")
src_init_file = os.path.join(gw_dir, "mem.init")
src_initram_file = os.path.join(gen_src_dir, "no-init-mem.vhdl")

# Copy generated files to target dir, amend them if necessary
core_file = os.path.join(gw_dir, "litedram_core.v")
dst_init_file = os.path.join(t_dir, "litedram_core.init")
dst_wrap_file = os.path.join(t_dir, "litedram-wrapper.vhdl")
dst_initram_file = os.path.join(t_dir, "litedram-initmem.vhdl")
replace_in_file(core_file, "mem.init", "litedram_core.init")
shutil.copy(core_file, t_dir)
shutil.copyfile(src_init_file, dst_init_file)
shutil.copyfile(src_wrap_file, dst_wrap_file)
shutil.copyfile(src_initram_file, dst_initram_file)

def main():


@ -0,0 +1,23 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;

entity dram_init_mem is
port (
clk : in std_ulogic;
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

wb_out.dat <= (others => '0');
wb_out.stall <= '0';
wb_out.ack <= wb_in.stb and wb_in.cyc;

end architecture rtl;

@ -26,7 +26,7 @@ CPPFLAGS += -I$(SRC_DIR)/libc/include -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(GENINC_D
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)
LDFLAGS = -static -nostdlib -Ttext-segment=0xffff0000 -T $(SRC_DIR)/$(PROGRAM).lds --gc-sections
LDFLAGS = -static -nostdlib -T $(OBJ)/$(PROGRAM).lds --gc-sections

#### Pretty print

@ -58,13 +58,15 @@ $(OBJ)/%.o : $(SRC_DIR)/%.S
$(call Q,AS, $(CC) $(ASFLAGS) -c $< -o $@, $@)
$(OBJ)/%.o : $(SRC_DIR)/libc/src/%.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)
$(OBJ)/%.lds : $(SRC_DIR)/%.lds.S
$(call Q,CC, $(CC) $(CPPFLAGS) -P -E $< -o $@, $@)

LIBC_SRC := $(wildcard $(SRC_DIR)/libc/src/*.c)
LIBC_OBJ := $(patsubst $(SRC_DIR)/libc/src/%.c, $(OBJ)/%.o,$(LIBC_SRC))
$(OBJ)/libc.o: $(LIBC_OBJ)
$(call Q,LD, $(LD) -r -o $@ $^, $@)

$(OBJ)/$(PROGRAM).elf: $(OBJECTS) $(OBJ)/libc.o
$(OBJ)/$(PROGRAM).elf: $(OBJECTS) $(OBJ)/libc.o $(OBJ)/$(PROGRAM).lds
$(call Q,LD, $(LD) $(LDFLAGS) -o $@ $^, $@)

$(OBJ)/$(PROGRAM).bin: $(OBJ)/$(PROGRAM).elf

@ -14,7 +14,7 @@
* limitations under the License.
*/

#define STACK_TOP 0xffff4000
#define STACK_TOP 0xf0004000

#define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \

@ -1,11 +1,14 @@
#include "microwatt_soc.h"

SECTIONS
{
. = 0xffff0000;
. = DRAM_INIT_BASE;
start = .;
.head : {
KEEP(*(.head))
}
. = 0xffff1000;
. = DRAM_INIT_BASE | 0x1000;

.text : { *(.text*) *(.sfpr) *(.rodata*) }
.data : { *(.data*) }
.bss : { *(.bss*) }

@ -5,7 +5,6 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
@ -25,8 +24,10 @@ entity litedram_wrapper is
-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_ctrl : in std_ulogic;
wb_is_init : in std_ulogic;
wb_ctrl_in : in wb_io_master_out;
wb_ctrl_out : out wb_io_slave_out;
wb_ctrl_is_csr : in std_ulogic;
wb_ctrl_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
@ -128,78 +129,66 @@ architecture behaviour of litedram_wrapper is
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;
signal wb_init_in : wb_io_master_out;
signal wb_init_out : wb_io_slave_out;

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

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

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);
-- alternate core reset address set when DRAM is not initialized.
core_alt_reset <= not init_done;

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;
-- Init code BRAM memory slave
init_ram_0: entity work.dram_init_mem
port map(
clk => system_clk,
wb_in => wb_init_in,
wb_out => wb_init_out
);

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
--
-- Control bus wishbone: This muxes the wishbone to the CSRs
-- and an internal small one to the init BRAM
--

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";
-- Init DRAM wishbone IN signals
wb_init_in.adr <= wb_ctrl_in.adr;
wb_init_in.dat <= wb_ctrl_in.dat;
wb_init_in.sel <= wb_ctrl_in.sel;
wb_init_in.we <= wb_ctrl_in.we;
wb_init_in.stb <= wb_ctrl_in.stb;
wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;

begin
-- DRAM CSR IN signals
wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
wb_ctrl_dat_w <= wb_ctrl_in.dat;
wb_ctrl_sel <= wb_ctrl_in.sel;
wb_ctrl_we <= wb_ctrl_in.we;
wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;

-- 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;
-- Ctrl bus wishbone OUT signals
wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
else wb_init_out.ack;
wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
else wb_init_out.dat;
wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
'0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;

--
-- Data bus wishbone to LiteDRAM native port
--
-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
-- XXX TODO: Figure out how to pipeline this
--
ad3 <= wb_in.adr(3);

-- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
when state = CMD else '0';
-- Wishbone port IN signals
user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
@ -208,33 +197,17 @@ begin
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- DRAM ctrl interface signals
wb_ctrl_adr <= x"0000" & wb_in.adr(15 downto 2);
wb_ctrl_dat_w <= wb_in.dat(31 downto 0);
wb_ctrl_sel <= wb_in.sel(3 downto 0);
wb_ctrl_cyc <= wb_in.cyc and wb_is_ctrl;
wb_ctrl_stb <= wb_in.stb and wb_is_ctrl;
wb_ctrl_we <= wb_in.we;

-- Wishbone out signals
wb_out.ack <= wb_ctrl_ack when wb_is_ctrl ='1' else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else
-- Wishbone OUT signals
wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';

wb_out.dat <= (x"00000000" & wb_ctrl_dat_r) when wb_is_ctrl = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else
wb_out.dat <= 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 ignored, the reset controller use the pll lock signal,
-- and alternate core reset address set when DRAM is not initialized.
--
core_alt_reset <= not init_done;

-- State machine
-- DRAM user port State machine
sm: process(system_clk)
begin

@ -5,7 +5,6 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
@ -25,8 +24,10 @@ entity litedram_wrapper is
-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_ctrl : in std_ulogic;
wb_is_init : in std_ulogic;
wb_ctrl_in : in wb_io_master_out;
wb_ctrl_out : out wb_io_slave_out;
wb_ctrl_is_csr : in std_ulogic;
wb_ctrl_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
@ -52,7 +53,6 @@ entity litedram_wrapper is
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity litedram_wrapper;

architecture behaviour of litedram_wrapper is
@ -117,14 +117,28 @@ architecture behaviour of litedram_wrapper is

begin

-- Reset, lift it when init done, no alt core reset
system_reset <= dram_user_reset or not init_done;
core_alt_reset <= '0';

-- Control bus is unused
wb_ctrl_out.ack <= (wb_is_ctrl = '1' or wb_is_init = '1') and wb_ctrl_in.cyc;
else wb_init_out.ack;
wb_ctrl_out.dat <= (others => '0');
wb_ctrl_out.stall <= '0';

--
-- Data bus wishbone to LiteDRAM native port
--
-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
-- XXX TODO: Figure out how to pipeline this
--
ad3 <= wb_in.adr(3);

-- DRAM interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
when state = CMD else '0';
-- Wishbone port IN signals
user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
@ -133,20 +147,17 @@ 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_ctrl = '1' or wb_is_init = '1') else
user_port0_wdata_ready when state = MWRITE else
-- Wishbone OUT signals
wb_out.ack <= 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_ctrl = '1' or wb_is_init = '1') else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else

wb_out.dat <= user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
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';
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;

-- State machine
-- DRAM user port State machine
sm: process(system_clk)
begin

@ -0,0 +1,72 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;

entity dram_init_mem is
port (
clk : in std_ulogic;
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";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 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*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
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

init_ram_0: process(clk)
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;
end process;

wb_out.stall <= '0';

end architecture rtl;

@ -5,7 +5,6 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
@ -25,8 +24,10 @@ entity litedram_wrapper is
-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_ctrl : in std_ulogic;
wb_is_init : in std_ulogic;
wb_ctrl_in : in wb_io_master_out;
wb_ctrl_out : out wb_io_slave_out;
wb_ctrl_is_csr : in std_ulogic;
wb_ctrl_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
@ -128,78 +129,66 @@ architecture behaviour of litedram_wrapper is
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;
signal wb_init_in : wb_io_master_out;
signal wb_init_out : wb_io_slave_out;

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

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

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);
-- alternate core reset address set when DRAM is not initialized.
core_alt_reset <= not init_done;

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;
-- Init code BRAM memory slave
init_ram_0: entity work.dram_init_mem
port map(
clk => system_clk,
wb_in => wb_init_in,
wb_out => wb_init_out
);

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
--
-- Control bus wishbone: This muxes the wishbone to the CSRs
-- and an internal small one to the init BRAM
--

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";
-- Init DRAM wishbone IN signals
wb_init_in.adr <= wb_ctrl_in.adr;
wb_init_in.dat <= wb_ctrl_in.dat;
wb_init_in.sel <= wb_ctrl_in.sel;
wb_init_in.we <= wb_ctrl_in.we;
wb_init_in.stb <= wb_ctrl_in.stb;
wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;

begin
-- DRAM CSR IN signals
wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
wb_ctrl_dat_w <= wb_ctrl_in.dat;
wb_ctrl_sel <= wb_ctrl_in.sel;
wb_ctrl_we <= wb_ctrl_in.we;
wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;

-- 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;
-- Ctrl bus wishbone OUT signals
wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
else wb_init_out.ack;
wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
else wb_init_out.dat;
wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
'0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;

--
-- Data bus wishbone to LiteDRAM native port
--
-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
-- XXX TODO: Figure out how to pipeline this
--
ad3 <= wb_in.adr(3);

-- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
when state = CMD else '0';
-- Wishbone port IN signals
user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
@ -208,33 +197,17 @@ begin
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- DRAM ctrl interface signals
wb_ctrl_adr <= x"0000" & wb_in.adr(15 downto 2);
wb_ctrl_dat_w <= wb_in.dat(31 downto 0);
wb_ctrl_sel <= wb_in.sel(3 downto 0);
wb_ctrl_cyc <= wb_in.cyc and wb_is_ctrl;
wb_ctrl_stb <= wb_in.stb and wb_is_ctrl;
wb_ctrl_we <= wb_in.we;

-- Wishbone out signals
wb_out.ack <= wb_ctrl_ack when wb_is_ctrl ='1' else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else
-- Wishbone OUT signals
wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';

wb_out.dat <= (x"00000000" & wb_ctrl_dat_r) when wb_is_ctrl = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else
wb_out.dat <= 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 ignored, the reset controller use the pll lock signal,
-- and alternate core reset address set when DRAM is not initialized.
--
core_alt_reset <= not init_done;

-- State machine
-- DRAM user port State machine
sm: process(system_clk)
begin

@ -4,10 +4,10 @@ a602487d05009f42
a64b5a7d14004a39
2402004ca64b7b7d
602100003c200000
6421ffff782107c6
6421f000782107c6
3d80000060213f00
798c07c6618c0000
618c108c658cffff
618c108c658cf000
4e8004217d8903a6
0000000048000002
0000000000000000

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-15 13:30:46
// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-21 19:21:27
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,
@ -831,13 +831,13 @@ reg litedramcore_bankmachine0_row_open = 1'd0;
reg litedramcore_bankmachine0_row_close = 1'd0;
reg litedramcore_bankmachine0_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine0_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine0_twtpcon_count = 3'd0;
wire litedramcore_bankmachine0_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine0_trccon_count = 3'd0;
wire litedramcore_bankmachine0_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine0_trascon_count = 3'd0;
wire litedramcore_bankmachine1_req_valid;
wire litedramcore_bankmachine1_req_ready;
@ -915,13 +915,13 @@ reg litedramcore_bankmachine1_row_open = 1'd0;
reg litedramcore_bankmachine1_row_close = 1'd0;
reg litedramcore_bankmachine1_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine1_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine1_twtpcon_count = 3'd0;
wire litedramcore_bankmachine1_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine1_trccon_count = 3'd0;
wire litedramcore_bankmachine1_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine1_trascon_count = 3'd0;
wire litedramcore_bankmachine2_req_valid;
wire litedramcore_bankmachine2_req_ready;
@ -999,13 +999,13 @@ reg litedramcore_bankmachine2_row_open = 1'd0;
reg litedramcore_bankmachine2_row_close = 1'd0;
reg litedramcore_bankmachine2_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine2_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine2_twtpcon_count = 3'd0;
wire litedramcore_bankmachine2_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine2_trccon_count = 3'd0;
wire litedramcore_bankmachine2_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine2_trascon_count = 3'd0;
wire litedramcore_bankmachine3_req_valid;
wire litedramcore_bankmachine3_req_ready;
@ -1083,13 +1083,13 @@ reg litedramcore_bankmachine3_row_open = 1'd0;
reg litedramcore_bankmachine3_row_close = 1'd0;
reg litedramcore_bankmachine3_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine3_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine3_twtpcon_count = 3'd0;
wire litedramcore_bankmachine3_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine3_trccon_count = 3'd0;
wire litedramcore_bankmachine3_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine3_trascon_count = 3'd0;
wire litedramcore_bankmachine4_req_valid;
wire litedramcore_bankmachine4_req_ready;
@ -1167,13 +1167,13 @@ reg litedramcore_bankmachine4_row_open = 1'd0;
reg litedramcore_bankmachine4_row_close = 1'd0;
reg litedramcore_bankmachine4_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine4_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine4_twtpcon_count = 3'd0;
wire litedramcore_bankmachine4_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine4_trccon_count = 3'd0;
wire litedramcore_bankmachine4_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine4_trascon_count = 3'd0;
wire litedramcore_bankmachine5_req_valid;
wire litedramcore_bankmachine5_req_ready;
@ -1251,13 +1251,13 @@ reg litedramcore_bankmachine5_row_open = 1'd0;
reg litedramcore_bankmachine5_row_close = 1'd0;
reg litedramcore_bankmachine5_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine5_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine5_twtpcon_count = 3'd0;
wire litedramcore_bankmachine5_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine5_trccon_count = 3'd0;
wire litedramcore_bankmachine5_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine5_trascon_count = 3'd0;
wire litedramcore_bankmachine6_req_valid;
wire litedramcore_bankmachine6_req_ready;
@ -1335,13 +1335,13 @@ reg litedramcore_bankmachine6_row_open = 1'd0;
reg litedramcore_bankmachine6_row_close = 1'd0;
reg litedramcore_bankmachine6_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine6_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine6_twtpcon_count = 3'd0;
wire litedramcore_bankmachine6_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine6_trccon_count = 3'd0;
wire litedramcore_bankmachine6_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine6_trascon_count = 3'd0;
wire litedramcore_bankmachine7_req_valid;
wire litedramcore_bankmachine7_req_ready;
@ -1419,13 +1419,13 @@ reg litedramcore_bankmachine7_row_open = 1'd0;
reg litedramcore_bankmachine7_row_close = 1'd0;
reg litedramcore_bankmachine7_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine7_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine7_twtpcon_count = 3'd0;
wire litedramcore_bankmachine7_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine7_trccon_count = 3'd0;
wire litedramcore_bankmachine7_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine7_trascon_count = 3'd0;
wire litedramcore_ras_allowed;
wire litedramcore_cas_allowed;
@ -1480,17 +1480,17 @@ reg litedramcore_steerer5 = 1'd1;
reg litedramcore_steerer6 = 1'd1;
reg litedramcore_steerer7 = 1'd1;
wire litedramcore_trrdcon_valid;
(* dont_touch = "true" *) reg litedramcore_trrdcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_trrdcon_ready = 1'd0;
reg litedramcore_trrdcon_count = 1'd0;
wire litedramcore_tfawcon_valid;
(* dont_touch = "true" *) reg litedramcore_tfawcon_ready = 1'd1;
wire [2:0] litedramcore_tfawcon_count;
reg [4:0] litedramcore_tfawcon_window = 5'd0;
wire litedramcore_tccdcon_valid;
(* dont_touch = "true" *) reg litedramcore_tccdcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_tccdcon_ready = 1'd0;
reg litedramcore_tccdcon_count = 1'd0;
wire litedramcore_twtrcon_valid;
(* dont_touch = "true" *) reg litedramcore_twtrcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_twtrcon_ready = 1'd0;
reg [2:0] litedramcore_twtrcon_count = 3'd0;
wire litedramcore_read_available;
wire litedramcore_write_available;
@ -14764,11 +14764,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine0_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine0_row <= 14'd0;
litedramcore_bankmachine0_row_opened <= 1'd0;
litedramcore_bankmachine0_twtpcon_ready <= 1'd1;
litedramcore_bankmachine0_twtpcon_ready <= 1'd0;
litedramcore_bankmachine0_twtpcon_count <= 3'd0;
litedramcore_bankmachine0_trccon_ready <= 1'd1;
litedramcore_bankmachine0_trccon_ready <= 1'd0;
litedramcore_bankmachine0_trccon_count <= 3'd0;
litedramcore_bankmachine0_trascon_ready <= 1'd1;
litedramcore_bankmachine0_trascon_ready <= 1'd0;
litedramcore_bankmachine0_trascon_count <= 3'd0;
litedramcore_bankmachine1_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine1_cmd_buffer_lookahead_produce <= 4'd0;
@ -14776,11 +14776,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine1_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine1_row <= 14'd0;
litedramcore_bankmachine1_row_opened <= 1'd0;
litedramcore_bankmachine1_twtpcon_ready <= 1'd1;
litedramcore_bankmachine1_twtpcon_ready <= 1'd0;
litedramcore_bankmachine1_twtpcon_count <= 3'd0;
litedramcore_bankmachine1_trccon_ready <= 1'd1;
litedramcore_bankmachine1_trccon_ready <= 1'd0;
litedramcore_bankmachine1_trccon_count <= 3'd0;
litedramcore_bankmachine1_trascon_ready <= 1'd1;
litedramcore_bankmachine1_trascon_ready <= 1'd0;
litedramcore_bankmachine1_trascon_count <= 3'd0;
litedramcore_bankmachine2_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine2_cmd_buffer_lookahead_produce <= 4'd0;
@ -14788,11 +14788,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine2_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine2_row <= 14'd0;
litedramcore_bankmachine2_row_opened <= 1'd0;
litedramcore_bankmachine2_twtpcon_ready <= 1'd1;
litedramcore_bankmachine2_twtpcon_ready <= 1'd0;
litedramcore_bankmachine2_twtpcon_count <= 3'd0;
litedramcore_bankmachine2_trccon_ready <= 1'd1;
litedramcore_bankmachine2_trccon_ready <= 1'd0;
litedramcore_bankmachine2_trccon_count <= 3'd0;
litedramcore_bankmachine2_trascon_ready <= 1'd1;
litedramcore_bankmachine2_trascon_ready <= 1'd0;
litedramcore_bankmachine2_trascon_count <= 3'd0;
litedramcore_bankmachine3_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine3_cmd_buffer_lookahead_produce <= 4'd0;
@ -14800,11 +14800,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine3_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine3_row <= 14'd0;
litedramcore_bankmachine3_row_opened <= 1'd0;
litedramcore_bankmachine3_twtpcon_ready <= 1'd1;
litedramcore_bankmachine3_twtpcon_ready <= 1'd0;
litedramcore_bankmachine3_twtpcon_count <= 3'd0;
litedramcore_bankmachine3_trccon_ready <= 1'd1;
litedramcore_bankmachine3_trccon_ready <= 1'd0;
litedramcore_bankmachine3_trccon_count <= 3'd0;
litedramcore_bankmachine3_trascon_ready <= 1'd1;
litedramcore_bankmachine3_trascon_ready <= 1'd0;
litedramcore_bankmachine3_trascon_count <= 3'd0;
litedramcore_bankmachine4_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine4_cmd_buffer_lookahead_produce <= 4'd0;
@ -14812,11 +14812,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine4_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine4_row <= 14'd0;
litedramcore_bankmachine4_row_opened <= 1'd0;
litedramcore_bankmachine4_twtpcon_ready <= 1'd1;
litedramcore_bankmachine4_twtpcon_ready <= 1'd0;
litedramcore_bankmachine4_twtpcon_count <= 3'd0;
litedramcore_bankmachine4_trccon_ready <= 1'd1;
litedramcore_bankmachine4_trccon_ready <= 1'd0;
litedramcore_bankmachine4_trccon_count <= 3'd0;
litedramcore_bankmachine4_trascon_ready <= 1'd1;
litedramcore_bankmachine4_trascon_ready <= 1'd0;
litedramcore_bankmachine4_trascon_count <= 3'd0;
litedramcore_bankmachine5_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine5_cmd_buffer_lookahead_produce <= 4'd0;
@ -14824,11 +14824,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine5_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine5_row <= 14'd0;
litedramcore_bankmachine5_row_opened <= 1'd0;
litedramcore_bankmachine5_twtpcon_ready <= 1'd1;
litedramcore_bankmachine5_twtpcon_ready <= 1'd0;
litedramcore_bankmachine5_twtpcon_count <= 3'd0;
litedramcore_bankmachine5_trccon_ready <= 1'd1;
litedramcore_bankmachine5_trccon_ready <= 1'd0;
litedramcore_bankmachine5_trccon_count <= 3'd0;
litedramcore_bankmachine5_trascon_ready <= 1'd1;
litedramcore_bankmachine5_trascon_ready <= 1'd0;
litedramcore_bankmachine5_trascon_count <= 3'd0;
litedramcore_bankmachine6_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine6_cmd_buffer_lookahead_produce <= 4'd0;
@ -14836,11 +14836,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine6_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine6_row <= 14'd0;
litedramcore_bankmachine6_row_opened <= 1'd0;
litedramcore_bankmachine6_twtpcon_ready <= 1'd1;
litedramcore_bankmachine6_twtpcon_ready <= 1'd0;
litedramcore_bankmachine6_twtpcon_count <= 3'd0;
litedramcore_bankmachine6_trccon_ready <= 1'd1;
litedramcore_bankmachine6_trccon_ready <= 1'd0;
litedramcore_bankmachine6_trccon_count <= 3'd0;
litedramcore_bankmachine6_trascon_ready <= 1'd1;
litedramcore_bankmachine6_trascon_ready <= 1'd0;
litedramcore_bankmachine6_trascon_count <= 3'd0;
litedramcore_bankmachine7_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine7_cmd_buffer_lookahead_produce <= 4'd0;
@ -14848,21 +14848,21 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine7_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine7_row <= 14'd0;
litedramcore_bankmachine7_row_opened <= 1'd0;
litedramcore_bankmachine7_twtpcon_ready <= 1'd1;
litedramcore_bankmachine7_twtpcon_ready <= 1'd0;
litedramcore_bankmachine7_twtpcon_count <= 3'd0;
litedramcore_bankmachine7_trccon_ready <= 1'd1;
litedramcore_bankmachine7_trccon_ready <= 1'd0;
litedramcore_bankmachine7_trccon_count <= 3'd0;
litedramcore_bankmachine7_trascon_ready <= 1'd1;
litedramcore_bankmachine7_trascon_ready <= 1'd0;
litedramcore_bankmachine7_trascon_count <= 3'd0;
litedramcore_choose_cmd_grant <= 3'd0;
litedramcore_choose_req_grant <= 3'd0;
litedramcore_trrdcon_ready <= 1'd1;
litedramcore_trrdcon_ready <= 1'd0;
litedramcore_trrdcon_count <= 1'd0;
litedramcore_tfawcon_ready <= 1'd1;
litedramcore_tfawcon_window <= 5'd0;
litedramcore_tccdcon_ready <= 1'd1;
litedramcore_tccdcon_ready <= 1'd0;
litedramcore_tccdcon_count <= 1'd0;
litedramcore_twtrcon_ready <= 1'd1;
litedramcore_twtrcon_ready <= 1'd0;
litedramcore_twtrcon_count <= 3'd0;
litedramcore_time0 <= 5'd0;
litedramcore_time1 <= 4'd0;

@ -0,0 +1,72 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;

entity dram_init_mem is
port (
clk : in std_ulogic;
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";

type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 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*2) := temp_word(31 downto 0);
temp_ram(i*2+1) := temp_word(63 downto 32);
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

init_ram_0: process(clk)
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;
end process;

wb_out.stall <= '0';

end architecture rtl;

@ -5,7 +5,6 @@ use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
@ -25,8 +24,10 @@ entity litedram_wrapper is
-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_ctrl : in std_ulogic;
wb_is_init : in std_ulogic;
wb_ctrl_in : in wb_io_master_out;
wb_ctrl_out : out wb_io_slave_out;
wb_ctrl_is_csr : in std_ulogic;
wb_ctrl_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
@ -128,78 +129,66 @@ architecture behaviour of litedram_wrapper is
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;
signal wb_init_in : wb_io_master_out;
signal wb_init_out : wb_io_slave_out;

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

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

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);
-- alternate core reset address set when DRAM is not initialized.
core_alt_reset <= not init_done;

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;
-- Init code BRAM memory slave
init_ram_0: entity work.dram_init_mem
port map(
clk => system_clk,
wb_in => wb_init_in,
wb_out => wb_init_out
);

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);
--
-- Control bus wishbone: This muxes the wishbone to the CSRs
-- and an internal small one to the init BRAM
--

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";
-- Init DRAM wishbone IN signals
wb_init_in.adr <= wb_ctrl_in.adr;
wb_init_in.dat <= wb_ctrl_in.dat;
wb_init_in.sel <= wb_ctrl_in.sel;
wb_init_in.we <= wb_ctrl_in.we;
wb_init_in.stb <= wb_ctrl_in.stb;
wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;

begin
-- DRAM CSR IN signals
wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
wb_ctrl_dat_w <= wb_ctrl_in.dat;
wb_ctrl_sel <= wb_ctrl_in.sel;
wb_ctrl_we <= wb_ctrl_in.we;
wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;

-- 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;
-- Ctrl bus wishbone OUT signals
wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
else wb_init_out.ack;
wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
else wb_init_out.dat;
wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
'0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;

--
-- Data bus wishbone to LiteDRAM native port
--
-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
-- XXX TODO: Figure out how to pipeline this
--
ad3 <= wb_in.adr(3);

-- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_ctrl and not wb_is_init)
when state = CMD else '0';
-- Wishbone port IN signals
user_port0_cmd_valid <= wb_in.cyc and wb_in.stb when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
@ -208,33 +197,17 @@ begin
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- DRAM ctrl interface signals
wb_ctrl_adr <= x"0000" & wb_in.adr(15 downto 2);
wb_ctrl_dat_w <= wb_in.dat(31 downto 0);
wb_ctrl_sel <= wb_in.sel(3 downto 0);
wb_ctrl_cyc <= wb_in.cyc and wb_is_ctrl;
wb_ctrl_stb <= wb_in.stb and wb_is_ctrl;
wb_ctrl_we <= wb_in.we;

-- Wishbone out signals
wb_out.ack <= wb_ctrl_ack when wb_is_ctrl ='1' else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else
-- Wishbone OUT signals
wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';

wb_out.dat <= (x"00000000" & wb_ctrl_dat_r) when wb_is_ctrl = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else
wb_out.dat <= 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 ignored, the reset controller use the pll lock signal,
-- and alternate core reset address set when DRAM is not initialized.
--
core_alt_reset <= not init_done;

-- State machine
-- DRAM user port State machine
sm: process(system_clk)
begin

@ -4,10 +4,10 @@ a602487d05009f42
a64b5a7d14004a39
2402004ca64b7b7d
602100003c200000
6421ffff782107c6
6421f000782107c6
3d80000060213f00
798c07c6618c0000
618c108c658cffff
618c108c658cf000
4e8004217d8903a6
0000000048000002
0000000000000000

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-15 13:30:49
// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-21 19:21:29
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,
@ -831,13 +831,13 @@ reg litedramcore_bankmachine0_row_open = 1'd0;
reg litedramcore_bankmachine0_row_close = 1'd0;
reg litedramcore_bankmachine0_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine0_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine0_twtpcon_count = 3'd0;
wire litedramcore_bankmachine0_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine0_trccon_count = 3'd0;
wire litedramcore_bankmachine0_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine0_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine0_trascon_count = 3'd0;
wire litedramcore_bankmachine1_req_valid;
wire litedramcore_bankmachine1_req_ready;
@ -915,13 +915,13 @@ reg litedramcore_bankmachine1_row_open = 1'd0;
reg litedramcore_bankmachine1_row_close = 1'd0;
reg litedramcore_bankmachine1_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine1_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine1_twtpcon_count = 3'd0;
wire litedramcore_bankmachine1_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine1_trccon_count = 3'd0;
wire litedramcore_bankmachine1_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine1_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine1_trascon_count = 3'd0;
wire litedramcore_bankmachine2_req_valid;
wire litedramcore_bankmachine2_req_ready;
@ -999,13 +999,13 @@ reg litedramcore_bankmachine2_row_open = 1'd0;
reg litedramcore_bankmachine2_row_close = 1'd0;
reg litedramcore_bankmachine2_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine2_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine2_twtpcon_count = 3'd0;
wire litedramcore_bankmachine2_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine2_trccon_count = 3'd0;
wire litedramcore_bankmachine2_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine2_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine2_trascon_count = 3'd0;
wire litedramcore_bankmachine3_req_valid;
wire litedramcore_bankmachine3_req_ready;
@ -1083,13 +1083,13 @@ reg litedramcore_bankmachine3_row_open = 1'd0;
reg litedramcore_bankmachine3_row_close = 1'd0;
reg litedramcore_bankmachine3_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine3_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine3_twtpcon_count = 3'd0;
wire litedramcore_bankmachine3_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine3_trccon_count = 3'd0;
wire litedramcore_bankmachine3_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine3_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine3_trascon_count = 3'd0;
wire litedramcore_bankmachine4_req_valid;
wire litedramcore_bankmachine4_req_ready;
@ -1167,13 +1167,13 @@ reg litedramcore_bankmachine4_row_open = 1'd0;
reg litedramcore_bankmachine4_row_close = 1'd0;
reg litedramcore_bankmachine4_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine4_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine4_twtpcon_count = 3'd0;
wire litedramcore_bankmachine4_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine4_trccon_count = 3'd0;
wire litedramcore_bankmachine4_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine4_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine4_trascon_count = 3'd0;
wire litedramcore_bankmachine5_req_valid;
wire litedramcore_bankmachine5_req_ready;
@ -1251,13 +1251,13 @@ reg litedramcore_bankmachine5_row_open = 1'd0;
reg litedramcore_bankmachine5_row_close = 1'd0;
reg litedramcore_bankmachine5_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine5_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine5_twtpcon_count = 3'd0;
wire litedramcore_bankmachine5_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine5_trccon_count = 3'd0;
wire litedramcore_bankmachine5_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine5_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine5_trascon_count = 3'd0;
wire litedramcore_bankmachine6_req_valid;
wire litedramcore_bankmachine6_req_ready;
@ -1335,13 +1335,13 @@ reg litedramcore_bankmachine6_row_open = 1'd0;
reg litedramcore_bankmachine6_row_close = 1'd0;
reg litedramcore_bankmachine6_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine6_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine6_twtpcon_count = 3'd0;
wire litedramcore_bankmachine6_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine6_trccon_count = 3'd0;
wire litedramcore_bankmachine6_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine6_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine6_trascon_count = 3'd0;
wire litedramcore_bankmachine7_req_valid;
wire litedramcore_bankmachine7_req_ready;
@ -1419,13 +1419,13 @@ reg litedramcore_bankmachine7_row_open = 1'd0;
reg litedramcore_bankmachine7_row_close = 1'd0;
reg litedramcore_bankmachine7_row_col_n_addr_sel = 1'd0;
wire litedramcore_bankmachine7_twtpcon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_twtpcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_twtpcon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine7_twtpcon_count = 3'd0;
wire litedramcore_bankmachine7_trccon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trccon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trccon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine7_trccon_count = 3'd0;
wire litedramcore_bankmachine7_trascon_valid;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trascon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_bankmachine7_trascon_ready = 1'd0;
reg [2:0] litedramcore_bankmachine7_trascon_count = 3'd0;
wire litedramcore_ras_allowed;
wire litedramcore_cas_allowed;
@ -1480,17 +1480,17 @@ reg litedramcore_steerer5 = 1'd1;
reg litedramcore_steerer6 = 1'd1;
reg litedramcore_steerer7 = 1'd1;
wire litedramcore_trrdcon_valid;
(* dont_touch = "true" *) reg litedramcore_trrdcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_trrdcon_ready = 1'd0;
reg litedramcore_trrdcon_count = 1'd0;
wire litedramcore_tfawcon_valid;
(* dont_touch = "true" *) reg litedramcore_tfawcon_ready = 1'd1;
wire [2:0] litedramcore_tfawcon_count;
reg [4:0] litedramcore_tfawcon_window = 5'd0;
wire litedramcore_tccdcon_valid;
(* dont_touch = "true" *) reg litedramcore_tccdcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_tccdcon_ready = 1'd0;
reg litedramcore_tccdcon_count = 1'd0;
wire litedramcore_twtrcon_valid;
(* dont_touch = "true" *) reg litedramcore_twtrcon_ready = 1'd1;
(* dont_touch = "true" *) reg litedramcore_twtrcon_ready = 1'd0;
reg [2:0] litedramcore_twtrcon_count = 3'd0;
wire litedramcore_read_available;
wire litedramcore_write_available;
@ -14764,11 +14764,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine0_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine0_row <= 15'd0;
litedramcore_bankmachine0_row_opened <= 1'd0;
litedramcore_bankmachine0_twtpcon_ready <= 1'd1;
litedramcore_bankmachine0_twtpcon_ready <= 1'd0;
litedramcore_bankmachine0_twtpcon_count <= 3'd0;
litedramcore_bankmachine0_trccon_ready <= 1'd1;
litedramcore_bankmachine0_trccon_ready <= 1'd0;
litedramcore_bankmachine0_trccon_count <= 3'd0;
litedramcore_bankmachine0_trascon_ready <= 1'd1;
litedramcore_bankmachine0_trascon_ready <= 1'd0;
litedramcore_bankmachine0_trascon_count <= 3'd0;
litedramcore_bankmachine1_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine1_cmd_buffer_lookahead_produce <= 4'd0;
@ -14776,11 +14776,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine1_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine1_row <= 15'd0;
litedramcore_bankmachine1_row_opened <= 1'd0;
litedramcore_bankmachine1_twtpcon_ready <= 1'd1;
litedramcore_bankmachine1_twtpcon_ready <= 1'd0;
litedramcore_bankmachine1_twtpcon_count <= 3'd0;
litedramcore_bankmachine1_trccon_ready <= 1'd1;
litedramcore_bankmachine1_trccon_ready <= 1'd0;
litedramcore_bankmachine1_trccon_count <= 3'd0;
litedramcore_bankmachine1_trascon_ready <= 1'd1;
litedramcore_bankmachine1_trascon_ready <= 1'd0;
litedramcore_bankmachine1_trascon_count <= 3'd0;
litedramcore_bankmachine2_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine2_cmd_buffer_lookahead_produce <= 4'd0;
@ -14788,11 +14788,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine2_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine2_row <= 15'd0;
litedramcore_bankmachine2_row_opened <= 1'd0;
litedramcore_bankmachine2_twtpcon_ready <= 1'd1;
litedramcore_bankmachine2_twtpcon_ready <= 1'd0;
litedramcore_bankmachine2_twtpcon_count <= 3'd0;
litedramcore_bankmachine2_trccon_ready <= 1'd1;
litedramcore_bankmachine2_trccon_ready <= 1'd0;
litedramcore_bankmachine2_trccon_count <= 3'd0;
litedramcore_bankmachine2_trascon_ready <= 1'd1;
litedramcore_bankmachine2_trascon_ready <= 1'd0;
litedramcore_bankmachine2_trascon_count <= 3'd0;
litedramcore_bankmachine3_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine3_cmd_buffer_lookahead_produce <= 4'd0;
@ -14800,11 +14800,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine3_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine3_row <= 15'd0;
litedramcore_bankmachine3_row_opened <= 1'd0;
litedramcore_bankmachine3_twtpcon_ready <= 1'd1;
litedramcore_bankmachine3_twtpcon_ready <= 1'd0;
litedramcore_bankmachine3_twtpcon_count <= 3'd0;
litedramcore_bankmachine3_trccon_ready <= 1'd1;
litedramcore_bankmachine3_trccon_ready <= 1'd0;
litedramcore_bankmachine3_trccon_count <= 3'd0;
litedramcore_bankmachine3_trascon_ready <= 1'd1;
litedramcore_bankmachine3_trascon_ready <= 1'd0;
litedramcore_bankmachine3_trascon_count <= 3'd0;
litedramcore_bankmachine4_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine4_cmd_buffer_lookahead_produce <= 4'd0;
@ -14812,11 +14812,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine4_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine4_row <= 15'd0;
litedramcore_bankmachine4_row_opened <= 1'd0;
litedramcore_bankmachine4_twtpcon_ready <= 1'd1;
litedramcore_bankmachine4_twtpcon_ready <= 1'd0;
litedramcore_bankmachine4_twtpcon_count <= 3'd0;
litedramcore_bankmachine4_trccon_ready <= 1'd1;
litedramcore_bankmachine4_trccon_ready <= 1'd0;
litedramcore_bankmachine4_trccon_count <= 3'd0;
litedramcore_bankmachine4_trascon_ready <= 1'd1;
litedramcore_bankmachine4_trascon_ready <= 1'd0;
litedramcore_bankmachine4_trascon_count <= 3'd0;
litedramcore_bankmachine5_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine5_cmd_buffer_lookahead_produce <= 4'd0;
@ -14824,11 +14824,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine5_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine5_row <= 15'd0;
litedramcore_bankmachine5_row_opened <= 1'd0;
litedramcore_bankmachine5_twtpcon_ready <= 1'd1;
litedramcore_bankmachine5_twtpcon_ready <= 1'd0;
litedramcore_bankmachine5_twtpcon_count <= 3'd0;
litedramcore_bankmachine5_trccon_ready <= 1'd1;
litedramcore_bankmachine5_trccon_ready <= 1'd0;
litedramcore_bankmachine5_trccon_count <= 3'd0;
litedramcore_bankmachine5_trascon_ready <= 1'd1;
litedramcore_bankmachine5_trascon_ready <= 1'd0;
litedramcore_bankmachine5_trascon_count <= 3'd0;
litedramcore_bankmachine6_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine6_cmd_buffer_lookahead_produce <= 4'd0;
@ -14836,11 +14836,11 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine6_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine6_row <= 15'd0;
litedramcore_bankmachine6_row_opened <= 1'd0;
litedramcore_bankmachine6_twtpcon_ready <= 1'd1;
litedramcore_bankmachine6_twtpcon_ready <= 1'd0;
litedramcore_bankmachine6_twtpcon_count <= 3'd0;
litedramcore_bankmachine6_trccon_ready <= 1'd1;
litedramcore_bankmachine6_trccon_ready <= 1'd0;
litedramcore_bankmachine6_trccon_count <= 3'd0;
litedramcore_bankmachine6_trascon_ready <= 1'd1;
litedramcore_bankmachine6_trascon_ready <= 1'd0;
litedramcore_bankmachine6_trascon_count <= 3'd0;
litedramcore_bankmachine7_cmd_buffer_lookahead_level <= 5'd0;
litedramcore_bankmachine7_cmd_buffer_lookahead_produce <= 4'd0;
@ -14848,21 +14848,21 @@ always @(posedge sys_clk) begin
litedramcore_bankmachine7_cmd_buffer_source_valid <= 1'd0;
litedramcore_bankmachine7_row <= 15'd0;
litedramcore_bankmachine7_row_opened <= 1'd0;
litedramcore_bankmachine7_twtpcon_ready <= 1'd1;
litedramcore_bankmachine7_twtpcon_ready <= 1'd0;
litedramcore_bankmachine7_twtpcon_count <= 3'd0;
litedramcore_bankmachine7_trccon_ready <= 1'd1;
litedramcore_bankmachine7_trccon_ready <= 1'd0;
litedramcore_bankmachine7_trccon_count <= 3'd0;
litedramcore_bankmachine7_trascon_ready <= 1'd1;
litedramcore_bankmachine7_trascon_ready <= 1'd0;
litedramcore_bankmachine7_trascon_count <= 3'd0;
litedramcore_choose_cmd_grant <= 3'd0;
litedramcore_choose_req_grant <= 3'd0;
litedramcore_trrdcon_ready <= 1'd1;
litedramcore_trrdcon_ready <= 1'd0;
litedramcore_trrdcon_count <= 1'd0;
litedramcore_tfawcon_ready <= 1'd1;
litedramcore_tfawcon_window <= 5'd0;
litedramcore_tccdcon_ready <= 1'd1;
litedramcore_tccdcon_ready <= 1'd0;
litedramcore_tccdcon_count <= 1'd0;
litedramcore_twtrcon_ready <= 1'd1;
litedramcore_twtrcon_ready <= 1'd0;
litedramcore_twtrcon_count <= 3'd0;
litedramcore_time0 <= 5'd0;
litedramcore_time1 <= 4'd0;

@ -10,16 +10,19 @@ use work.common.all;
use work.wishbone_types.all;


-- Memory map:
-- Memory map. *** Keep include/microwatt_soc.h updated on changes ***
--
-- Main bus:
-- 0x00000000: Block RAM (MEMORY_SIZE) or DRAM depending on syscon
-- 0x40000000: DRAM (when present)
-- 0x80000000: Block RAM (aliased & repeated)

-- IO Bus:
-- 0xc0000000: SYSCON
-- 0xc0002000: UART0
-- 0xc0004000: XICS ICP
-- 0xc0100000: LiteDRAM control (CSRs)
-- 0xf0000000: Block RAM (aliased & repeated)
-- 0xffff0000: DRAM init code (if any)
-- 0xf0000000: DRAM init code (if any)

entity soc is
generic (
@ -39,8 +42,10 @@ entity soc is
-- DRAM controller signals
wb_dram_in : out wishbone_master_out;
wb_dram_out : in wishbone_slave_out;
wb_dram_ctrl : out std_ulogic;
wb_dram_init : out std_ulogic;
wb_dram_ctrl_in : out wb_io_master_out;
wb_dram_ctrl_out : in wb_io_slave_out;
wb_dram_is_csr : out std_ulogic;
wb_dram_is_init : out std_ulogic;

-- UART0 signals:
uart0_txd : out std_ulogic;
@ -71,23 +76,31 @@ architecture behaviour of soc is
signal wb_master_in : wishbone_slave_out;
signal wb_master_out : wishbone_master_out;

-- Main "IO" bus, from main slave decoder to the latch
signal wb_io_in : wishbone_master_out;
signal wb_io_out : wishbone_slave_out;

-- Secondary (smaller) IO bus after the IO bus latch
signal wb_sio_out : wb_io_master_out;
signal wb_sio_in : wb_io_slave_out;

-- Syscon signals
signal dram_at_0 : std_ulogic;
signal do_core_reset : std_ulogic;
signal wb_syscon_in : wishbone_master_out;
signal wb_syscon_out : wishbone_slave_out;
signal wb_syscon_in : wb_io_master_out;
signal wb_syscon_out : wb_io_slave_out;

-- UART0 signals:
signal wb_uart0_in : wishbone_master_out;
signal wb_uart0_out : wishbone_slave_out;
signal wb_uart0_in : wb_io_master_out;
signal wb_uart0_out : wb_io_slave_out;
signal uart_dat8 : std_ulogic_vector(7 downto 0);

-- XICS0 signals:
signal wb_xics0_in : wishbone_master_out;
signal wb_xics0_out : wishbone_slave_out;
signal wb_xics0_in : wb_io_master_out;
signal wb_xics0_out : wb_io_slave_out;
signal int_level_in : std_ulogic_vector(15 downto 0);

signal xics_to_execute1 : XicsToExecute1Type;
signal core_ext_irq : std_ulogic;

-- Main memory signals:
signal wb_bram_in : wishbone_master_out;
@ -141,7 +154,7 @@ begin
generic map(
SIM => SIM,
DISABLE_FLATTEN => DISABLE_FLATTEN_CORE,
ALT_RESET_ADDRESS => (15 downto 0 => '0', others => '1')
ALT_RESET_ADDRESS => (27 downto 0 => '0', others => '1')
)
port map(
clk => system_clk,
@ -157,7 +170,7 @@ begin
dmi_wr => dmi_wr,
dmi_ack => dmi_core_ack,
dmi_req => dmi_core_req,
xics_in => xics_to_execute1
ext_irq => core_ext_irq
);

-- Wishbone bus master arbiter & mux
@ -180,90 +193,271 @@ begin
wb_slave_in => wb_master_in
);

-- Wishbone slaves address decoder & mux
slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out, wb_dram_out, wb_syscon_out)
-- Selected slave
type slave_type is (SLAVE_SYSCON,
SLAVE_UART,
SLAVE_BRAM,
SLAVE_DRAM,
SLAVE_DRAM_INIT,
SLAVE_DRAM_CTRL,
SLAVE_ICP_0,
SLAVE_NONE);
variable slave : slave_type;
-- Top level Wishbone slaves address decoder & mux
--
-- From CPU to BRAM, DRAM, IO, selected on top 3 bits and dram_at_0
-- 0000 - BRAM
-- 0001 - DRAM
-- 01xx - DRAM
-- 10xx - BRAM
-- 11xx - IO
--
slave_top_intercon: process(wb_master_out, wb_bram_out, wb_dram_out, wb_io_out, dram_at_0)
type slave_top_type is (SLAVE_TOP_BRAM,
SLAVE_TOP_DRAM,
SLAVE_TOP_IO);
variable slave_top : slave_top_type;
variable top_decode : std_ulogic_vector(3 downto 0);
begin
-- Simple address decoder.
slave := SLAVE_NONE;
-- Simple address decoder. Ignore top bits to save silicon for now
slave := SLAVE_NONE;
if std_match(wb_master_out.adr, x"0-------") then
slave := SLAVE_DRAM when HAS_DRAM and dram_at_0 = '1' else
SLAVE_BRAM;
elsif std_match(wb_master_out.adr, x"FFFF----") then
slave := SLAVE_DRAM_INIT;
elsif std_match(wb_master_out.adr, x"F-------") then
slave := SLAVE_BRAM;
elsif std_match(wb_master_out.adr, x"4-------") and HAS_DRAM then
slave := SLAVE_DRAM;
elsif std_match(wb_master_out.adr, x"C0000---") then
slave := SLAVE_SYSCON;
elsif std_match(wb_master_out.adr, x"C0002---") then
slave := SLAVE_UART;
elsif std_match(wb_master_out.adr, x"C01-----") then
slave := SLAVE_DRAM_CTRL;
elsif std_match(wb_master_out.adr, x"C0004---") then
slave := SLAVE_ICP_0;
-- Top-level address decoder
top_decode := wb_master_out.adr(31 downto 29) & dram_at_0;
slave_top := SLAVE_TOP_BRAM;
if std_match(top_decode, "0000") then
slave_top := SLAVE_TOP_BRAM;
elsif std_match(top_decode, "0001") then
slave_top := SLAVE_TOP_DRAM;
elsif std_match(top_decode, "01--") then
slave_top := SLAVE_TOP_DRAM;
elsif std_match(top_decode, "10--") then
slave_top := SLAVE_TOP_BRAM;
elsif std_match(top_decode, "11--") then
slave_top := SLAVE_TOP_IO;
end if;

-- Wishbone muxing. Defaults:
-- Top level wishbone muxing.
wb_bram_in <= wb_master_out;
wb_bram_in.cyc <= '0';
wb_uart0_in <= wb_master_out;
wb_dram_in <= wb_master_out;
wb_dram_in.cyc <= '0';
wb_io_in <= wb_master_out;
wb_io_in.cyc <= '0';
case slave_top is
when SLAVE_TOP_BRAM =>
wb_bram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_bram_out;
when SLAVE_TOP_DRAM =>
wb_dram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_dram_out;
when SLAVE_TOP_IO =>
wb_io_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_io_out;
end case;
end process slave_top_intercon;

-- IO wishbone slave 64->32 bits converter
--
-- For timing reasons, this adds a one cycle latch on the way both
-- in and out. This relaxes timing and routing pressure on the "main"
-- memory bus by moving all simple IOs to a slower 32-bit bus.
--
-- This implementation is rather dumb at the moment, no stash buffer,
-- so we stall whenever that latch is busy. This can be improved.
--
slave_io_latch: process(system_clk)
-- State
type state_t is (IDLE, WAIT_ACK_BOT, WAIT_ACK_TOP);
variable state : state_t;

-- Misc
variable has_top : boolean;
variable has_bot : boolean;
begin
if rising_edge(system_clk) then
if (rst) then
state := IDLE;
wb_io_out.ack <= '0';
wb_io_out.stall <= '0';
wb_sio_out.cyc <= '0';
wb_sio_out.stb <= '0';
has_top := false;
has_bot := false;
else
case state is
when IDLE =>
-- Clear ACK in case it was set
wb_io_out.ack <= '0';

-- Do we have a cycle ?
if wb_io_in.cyc = '1' and wb_io_in.stb = '1' then
-- Stall master until we are done, we are't (yet) pipelining
-- this, it's all slow IOs.
wb_io_out.stall <= '1';

-- Start cycle downstream
wb_sio_out.cyc <= '1';
wb_sio_out.stb <= '1';

-- Copy write enable to IO out, copy address as well
wb_sio_out.we <= wb_io_in.we;
wb_sio_out.adr <= wb_io_in.adr(wb_sio_out.adr'left downto 3) & "000";

-- Do we have a top word and/or a bottom word ?
has_top := wb_io_in.sel(7 downto 4) /= "0000";
has_bot := wb_io_in.sel(3 downto 0) /= "0000";

-- If we have a bottom word, handle it first, otherwise
-- send the top word down. XXX Split the actual mux out
-- and only generate a control signal.
if has_bot then
if wb_io_in.we = '1' then
wb_sio_out.dat <= wb_io_in.dat(31 downto 0);
end if;
wb_sio_out.sel <= wb_io_in.sel(3 downto 0);

-- Wait for ack
state := WAIT_ACK_BOT;
else
if wb_io_in.we = '1' then
wb_sio_out.dat <= wb_io_in.dat(63 downto 32);
end if;
wb_sio_out.sel <= wb_io_in.sel(7 downto 4);

-- Bump address
wb_sio_out.adr(2) <= '1';

-- Wait for ack
state := WAIT_ACK_TOP;
end if;
end if;
when WAIT_ACK_BOT =>
-- If we aren't stalled by the device, clear stb
if wb_sio_in.stall = '0' then
wb_sio_out.stb <= '0';
end if;

-- Handle ack
if wb_sio_in.ack = '1' then
-- If it's a read, latch the data
if wb_sio_out.we = '0' then
wb_io_out.dat(31 downto 0) <= wb_sio_in.dat;
end if;

-- Do we have a "top" part as well ?
if has_top then
-- Latch data & sel
if wb_io_in.we = '1' then
wb_sio_out.dat <= wb_io_in.dat(63 downto 32);
end if;
wb_sio_out.sel <= wb_io_in.sel(7 downto 4);

-- Bump address and set STB
wb_sio_out.adr(2) <= '1';
wb_sio_out.stb <= '1';

-- Wait for new ack
state := WAIT_ACK_TOP;
else
-- We are done, ack up, clear cyc downstram
wb_sio_out.cyc <= '0';

-- And ack & unstall upstream
wb_io_out.ack <= '1';
wb_io_out.stall <= '0';

-- Wait for next one
state := IDLE;
end if;
end if;
when WAIT_ACK_TOP =>
-- If we aren't stalled by the device, clear stb
if wb_sio_in.stall = '0' then
wb_sio_out.stb <= '0';
end if;

-- Handle ack
if wb_sio_in.ack = '1' then
-- If it's a read, latch the data
if wb_sio_out.we = '0' then
wb_io_out.dat(63 downto 32) <= wb_sio_in.dat;
end if;

-- We are done, ack up, clear cyc downstram
wb_sio_out.cyc <= '0';

-- And ack & unstall upstream
wb_io_out.ack <= '1';
wb_io_out.stall <= '0';

-- Wait for next one
state := IDLE;
end if;
end case;
end if;
end if;
end process;
-- IO wishbone slave intercon.
--
slave_io_intercon: process(wb_sio_out, wb_syscon_out, wb_uart0_out,
wb_dram_ctrl_out, wb_xics0_out)
-- IO branch split:
type slave_io_type is (SLAVE_IO_SYSCON,
SLAVE_IO_UART,
SLAVE_IO_DRAM_INIT,
SLAVE_IO_DRAM_CSR,
SLAVE_IO_ICP_0,
SLAVE_IO_NONE);
variable slave_io : slave_io_type;

variable match : std_ulogic_vector(31 downto 12);
begin

-- Simple address decoder.
slave_io := SLAVE_IO_NONE;
match := "11" & wb_sio_out.adr(29 downto 12);
if std_match(match, x"F----") then
slave_io := SLAVE_IO_DRAM_INIT;
elsif std_match(match, x"C0000") then
slave_io := SLAVE_IO_SYSCON;
elsif std_match(match, x"C0002") then
slave_io := SLAVE_IO_UART;
elsif std_match(match, x"C01--") then
slave_io := SLAVE_IO_DRAM_CSR;
elsif std_match(match, x"C0004") then
slave_io := SLAVE_IO_ICP_0;
end if;
wb_uart0_in <= wb_sio_out;
wb_uart0_in.cyc <= '0';

-- Only give xics 8 bits of wb addr
wb_xics0_in <= wb_master_out;
wb_xics0_in <= wb_sio_out;
wb_xics0_in.adr <= (others => '0');
wb_xics0_in.adr(7 downto 0) <= wb_master_out.adr(7 downto 0);
wb_xics0_in.adr(7 downto 0) <= wb_sio_out.adr(7 downto 0);
wb_xics0_in.cyc <= '0';

wb_dram_in <= wb_master_out;
wb_dram_in.cyc <= '0';
wb_dram_ctrl <= '0';
wb_dram_init <= '0';
wb_syscon_in <= wb_master_out;
wb_dram_ctrl_in <= wb_sio_out;
wb_dram_ctrl_in.cyc <= '0';
wb_dram_is_csr <= '0';
wb_dram_is_init <= '0';

wb_syscon_in <= wb_sio_out;
wb_syscon_in.cyc <= '0';
case slave is
when SLAVE_BRAM =>
wb_bram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_bram_out;
when SLAVE_DRAM =>
wb_dram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_dram_out;
when SLAVE_DRAM_INIT =>
wb_dram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_dram_out;
wb_dram_init <= '1';
when SLAVE_DRAM_CTRL =>
wb_dram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_dram_out;
wb_dram_ctrl <= '1';
when SLAVE_SYSCON =>
wb_syscon_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_syscon_out;
when SLAVE_UART =>
wb_uart0_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_uart0_out;
when SLAVE_ICP_0 =>
wb_xics0_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_xics0_out;

case slave_io is
when SLAVE_IO_DRAM_INIT =>
wb_dram_ctrl_in.cyc <= wb_sio_out.cyc;
wb_sio_in <= wb_dram_ctrl_out;
wb_dram_is_init <= '1';
when SLAVE_IO_DRAM_CSR =>
wb_dram_ctrl_in.cyc <= wb_sio_out.cyc;
wb_sio_in <= wb_dram_ctrl_out;
wb_dram_is_csr <= '1';
when SLAVE_IO_SYSCON =>
wb_syscon_in.cyc <= wb_sio_out.cyc;
wb_sio_in <= wb_syscon_out;
when SLAVE_IO_UART =>
wb_uart0_in.cyc <= wb_sio_out.cyc;
wb_sio_in <= wb_uart0_out;
when SLAVE_IO_ICP_0 =>
wb_xics0_in.cyc <= wb_sio_out.cyc;
wb_sio_in <= wb_xics0_out;
when others =>
wb_master_in.dat <= (others => '1');
wb_master_in.ack <= wb_master_out.stb and wb_master_out.cyc;
wb_master_in.stall <= '0';
wb_sio_in.dat <= (others => '1');
wb_sio_in.ack <= wb_sio_out.stb and wb_sio_out.cyc;
wb_sio_in.stall <= '0';
end case;
end process slave_intercon;

end process;

-- Syscon slave
syscon0: entity work.syscon
@ -287,10 +481,6 @@ begin
-- Simulated memory and UART

-- UART0 wishbone slave
-- XXX FIXME: Need a proper wb64->wb8 adapter that
-- converts SELs into low address bits and muxes
-- data accordingly (either that or rejects large
-- cycles).
uart0: entity work.pp_soc_uart
generic map(
FIFO_DEPTH => 32
@ -309,7 +499,7 @@ begin
wb_we_in => wb_uart0_in.we,
wb_ack_out => wb_uart0_out.ack
);
wb_uart0_out.dat <= x"00000000000000" & uart_dat8;
wb_uart0_out.dat <= x"000000" & uart_dat8;
wb_uart0_out.stall <= '0' when wb_uart0_in.cyc = '0' else not wb_uart0_out.ack;

xics0: entity work.xics
@ -322,7 +512,7 @@ begin
wb_in => wb_xics0_in,
wb_out => wb_xics0_out,
int_level_in => int_level_in,
e_out => xics_to_execute1
core_irq_out => core_ext_irq
);

-- BRAM Memory slave

@ -20,8 +20,8 @@ entity syscon is
rst : in std_ulogic;

-- Wishbone ports:
wishbone_in : in wishbone_master_out;
wishbone_out : out wishbone_slave_out;
wishbone_in : in wb_io_master_out;
wishbone_out : out wb_io_slave_out;

-- System control ports
dram_at_0 : out std_ulogic;
@ -43,6 +43,9 @@ architecture behaviour of syscon is
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";

-- Muxed reg read signal
signal reg_out : std_ulogic_vector(63 downto 0);

-- INFO register bits
constant SYS_REG_INFO_HAS_UART : integer := 0;
constant SYS_REG_INFO_HAS_DRAM : integer := 1;
@ -99,7 +102,7 @@ begin
SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);

-- Register read mux
with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select wishbone_out.dat <=
with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select reg_out <=
SIG_VALUE when SYS_REG_SIG,
reg_info when SYS_REG_INFO,
reg_braminfo when SYS_REG_BRAMINFO,
@ -107,6 +110,8 @@ begin
reg_clkinfo when SYS_REG_CLKINFO,
reg_ctrl_out when SYS_REG_CTRL,
(others => '0') when others;
wishbone_out.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
reg_out(31 downto 0);

-- Register writes
regs_write: process(clk)
@ -116,7 +121,9 @@ begin
reg_ctrl <= (others => '0');
else
if wishbone_in.cyc and wishbone_in.stb and wishbone_in.we then
if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL then
-- Change this if CTRL ever has more than 32 bits
if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL and
wishbone_in.adr(2) = '0' then
reg_ctrl(SYS_REG_CTRL_BITS-1 downto 0) <=
wishbone_in.dat(SYS_REG_CTRL_BITS-1 downto 0);
end if;

@ -1,8 +1,7 @@
#include <stdint.h>

#define XICS_BASE 0xc0004000

static uint64_t xics_base = XICS_BASE;
#include "microwatt_soc.h"
#include "io.h"

#define XICS_XIRR_POLL 0x0
#define XICS_XIRR 0x4
@ -11,26 +10,20 @@ static uint64_t xics_base = XICS_BASE;

uint8_t xics_read8(int offset)
{
uint32_t val;

__asm__ volatile("lbzcix %0,%1,%2" : "=r" (val) : "b" (xics_base), "r" (offset));
return val;
return readb(XICS_BASE + offset);
}

void xics_write8(int offset, uint8_t val)
{
__asm__ volatile("stbcix %0,%1,%2" : : "r" (val), "b" (xics_base), "r" (offset));
writeb(val, XICS_BASE + offset);
}

uint32_t xics_read32(int offset)
{
uint32_t val;

__asm__ volatile("lwzcix %0,%1,%2" : "=r" (val) : "b" (xics_base), "r" (offset));
return val;
return readl(XICS_BASE + offset);
}

void xics_write32(int offset, uint32_t val)
{
__asm__ volatile("stwcix %0,%1,%2" : : "r" (val), "b" (xics_base), "r" (offset));
writel(val, XICS_BASE + offset);
}

@ -2,6 +2,9 @@ library ieee;
use ieee.std_logic_1164.all;

package wishbone_types is
--
-- Main CPU bus. 32-bit address, 64-bit data
--
constant wishbone_addr_bits : integer := 32;
constant wishbone_data_bits : integer := 64;
constant wishbone_sel_bits : integer := wishbone_data_bits/8;
@ -30,4 +33,22 @@ package wishbone_types is
type wishbone_master_out_vector is array (natural range <>) of wishbone_master_out;
type wishbone_slave_out_vector is array (natural range <>) of wishbone_slave_out;

--
-- IO Bus to a device, 30-bit address, 32-bits data
--
type wb_io_master_out is record
adr : std_ulogic_vector(29 downto 0);
dat : std_ulogic_vector(31 downto 0);
sel : std_ulogic_vector(3 downto 0);
cyc : std_ulogic;
stb : std_ulogic;
we : std_ulogic;
end record;

type wb_io_slave_out is record
dat : std_ulogic_vector(31 downto 0);
ack : std_ulogic;
stall : std_ulogic;
end record;
end package wishbone_types;

@ -30,12 +30,12 @@ entity xics is
clk : in std_logic;
rst : in std_logic;

wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_in : in wb_io_master_out;
wb_out : out wb_io_slave_out;

int_level_in : in std_ulogic_vector(LEVEL_NUM - 1 downto 0);

e_out : out XicsToExecute1Type
core_irq_out : out std_ulogic
);
end xics;

@ -47,7 +47,7 @@ architecture behaviour of xics is
mfrr : std_ulogic_vector(7 downto 0);
mfrr_pending : std_ulogic;
irq : std_ulogic;
wb_rd_data : wishbone_data_type;
wb_rd_data : std_ulogic_vector(31 downto 0);
wb_ack : std_ulogic;
end record;
constant reg_internal_init : reg_internal_t :=
@ -62,11 +62,11 @@ architecture behaviour of xics is
-- hardwire the hardware IRQ priority
constant HW_PRIORITY : std_ulogic_vector(7 downto 0) := x"80";

-- 32 bit offsets for each presentation
constant XIRR_POLL : std_ulogic_vector(31 downto 0) := x"00000000";
constant XIRR : std_ulogic_vector(31 downto 0) := x"00000004";
constant RESV0 : std_ulogic_vector(31 downto 0) := x"00000008";
constant MFRR : std_ulogic_vector(31 downto 0) := x"0000000c";
-- 8 bit offsets for each presentation
constant XIRR_POLL : std_ulogic_vector(7 downto 0) := x"00";
constant XIRR : std_ulogic_vector(7 downto 0) := x"04";
constant RESV0 : std_ulogic_vector(7 downto 0) := x"08";
constant MFRR : std_ulogic_vector(7 downto 0) := x"0c";

begin

@ -80,7 +80,7 @@ begin
wb_out.dat <= r.wb_rd_data;
wb_out.ack <= r.wb_ack;
wb_out.stall <= '0'; -- never stall wishbone
e_out.irq <= r.irq;
core_irq_out <= r.irq;

comb : process(all)
variable v : reg_internal_t;
@ -95,62 +95,73 @@ begin
irq_eoi := '0';

if wb_in.cyc = '1' and wb_in.stb = '1' then
-- wishbone addresses we get are 64 bit alligned, so we
-- need to use the sel bits to get 32 bit chunks.
v.wb_ack := '1'; -- always ack
if wb_in.we = '1' then -- write
-- writes to both XIRR are the same
if wb_in.adr = XIRR_POLL then
report "XICS XIRR_POLL/XIRR write";
if wb_in.sel = x"0f" then -- 4 bytes
case wb_in.adr(7 downto 0) is
when XIRR_POLL =>
report "XICS XIRR_POLL write";
if wb_in.sel = x"f" then -- 4 bytes
v.cppr := wb_in.dat(31 downto 24);
elsif wb_in.sel = x"1" then -- 1 byte
v.cppr := wb_in.dat(7 downto 0);
end if;
when XIRR =>
if wb_in.sel = x"f" then -- 4 byte
report "XICS XIRR write word:" & to_hstring(wb_in.dat);
v.cppr := wb_in.dat(31 downto 24);
elsif wb_in.sel = x"f0" then -- 4 byte
v.cppr := wb_in.dat(63 downto 56);
irq_eoi := '1';
elsif wb_in.sel = x"01" then -- 1 byte
elsif wb_in.sel = x"1" then -- 1 byte
report "XICS XIRR write byte:" & to_hstring(wb_in.dat(7 downto 0));
v.cppr := wb_in.dat(7 downto 0);
elsif wb_in.sel = x"10" then -- 1 byte
v.cppr := wb_in.dat(39 downto 32);
else
report "XICS XIRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
end if;

elsif wb_in.adr = RESV0 then
report "XICS MFRR write";
if wb_in.sel = x"f0" then -- 4 bytes
when MFRR =>
if wb_in.sel = x"f" then -- 4 bytes
report "XICS MFRR write word:" & to_hstring(wb_in.dat);
v.mfrr_pending := '1';
v.mfrr := wb_in.dat(63 downto 56);
elsif wb_in.sel = x"10" then -- 1 byte
v.mfrr := wb_in.dat(31 downto 24);
elsif wb_in.sel = x"1" then -- 1 byte
report "XICS MFRR write byte:" & to_hstring(wb_in.dat(7 downto 0));
v.mfrr_pending := '1';
v.mfrr := wb_in.dat(39 downto 32);
end if;

v.mfrr := wb_in.dat(7 downto 0);
else
report "XICS MFRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel);
end if;
when others =>
end case;

else -- read
v.wb_rd_data := (others => '0');

if wb_in.adr = XIRR_POLL then
report "XICS XIRR_POLL/XIRR read";
if wb_in.sel = x"0f" then
case wb_in.adr(7 downto 0) is
when XIRR_POLL =>
report "XICS XIRR_POLL read";
if wb_in.sel = x"f" then
v.wb_rd_data(23 downto 0) := r.xisr;
v.wb_rd_data(31 downto 24) := r.cppr;
elsif wb_in.sel = x"1" then
v.wb_rd_data(7 downto 0) := r.cppr;
end if;
when XIRR =>
report "XICS XIRR read";
if wb_in.sel = x"f" then
v.wb_rd_data(23 downto 0) := r.xisr;
v.wb_rd_data(31 downto 24) := r.cppr;
elsif wb_in.sel = x"f0" then
v.wb_rd_data(55 downto 32) := r.xisr;
v.wb_rd_data(63 downto 56) := r.cppr;
xirr_accept_rd := '1';
elsif wb_in.sel = x"01" then
elsif wb_in.sel = x"1" then
v.wb_rd_data(7 downto 0) := r.cppr;
elsif wb_in.sel = x"10" then
v.wb_rd_data(39 downto 32) := r.cppr;
end if;

elsif wb_in.adr = RESV0 then
when MFRR =>
report "XICS MFRR read";
if wb_in.sel = x"f0" then -- 4 bytes
v.wb_rd_data(63 downto 56) := r.mfrr;
elsif wb_in.sel = x"10" then -- 1 byte
if wb_in.sel = x"f" then -- 4 bytes
v.wb_rd_data(31 downto 24) := r.mfrr;
elsif wb_in.sel = x"1" then -- 1 byte
v.wb_rd_data( 7 downto 0) := r.mfrr;
end if;
end if;
when others =>
end case;
end if;
end if;


Loading…
Cancel
Save