litedram: Add simulation support

This adds a simulated litedram model along with the necessary
Makefile gunk to verilate it and wrap it for use by ghdl.

The core_dram_tb test bench is a variant of core_tb with
LiteDRAM simulated. It's not built by default, an explicit

make core_dram_tb

is necessary as to not require verilator to be installed for
the normal build process (also it's slow'ish).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
pull/190/head
Benjamin Herrenschmidt 5 years ago
parent 42e138e539
commit 6fe077910b

@ -1,6 +1,6 @@
GHDL ?= ghdl GHDL ?= ghdl
GHDLFLAGS=--std=08 --work=unisim GHDLFLAGS=--std=08 --work=unisim
CFLAGS=-O2 -Wall CFLAGS=-O3 -Wall


GHDLSYNTH ?= ghdl.so GHDLSYNTH ?= ghdl.so
YOSYS ?= yosys YOSYS ?= yosys
@ -66,6 +66,7 @@ soc_sim_link=$(patsubst %,-Wl$(comma)%,$(soc_sim_obj_files))


core_tbs = multiply_tb divider_tb rotator_tb countzero_tb core_tbs = multiply_tb divider_tb rotator_tb countzero_tb
soc_tbs = core_tb icache_tb dcache_tb dmi_dtm_tb wishbone_bram_tb soc_tbs = core_tb icache_tb dcache_tb dmi_dtm_tb wishbone_bram_tb
soc_dram_tbs = core_dram_tb


$(soc_tbs): %: $(core_files) $(soc_files) $(soc_sim_files) $(soc_sim_obj_files) %.vhdl $(soc_tbs): %: $(core_files) $(soc_files) $(soc_sim_files) $(soc_sim_obj_files) %.vhdl
$(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(core_files) $(soc_files) $(soc_sim_files) $@.vhdl -e $@ $(GHDL) -c $(GHDLFLAGS) $(soc_sim_link) $(core_files) $(soc_files) $(soc_sim_files) $@.vhdl -e $@
@ -76,6 +77,34 @@ $(core_tbs): %: $(core_files) glibc_random.vhdl glibc_random_helpers.vhdl %.vhdl
soc_reset_tb: fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl soc_reset_tb: fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl
$(GHDL) -c $(GHDLFLAGS) fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl -e $@ $(GHDL) -c $(GHDLFLAGS) fpga/soc_reset_tb.vhdl fpga/soc_reset.vhdl -e $@


# LiteDRAM sim
VERILATOR_ROOT=$(shell verilator -getenv VERILATOR_ROOT 2>/dev/null)
ifeq (, $(VERILATOR_ROOT))
$(soc_dram_tbs):
$(error "Verilator is required to make this target !")
else

VERILATOR_CFLAGS=-O3
VERILATOR_FLAGS=-O3
verilated_dram: litedram/generated/sim/litedram_core.v
verilator $(VERILATOR_FLAGS) -CFLAGS $(VERILATOR_CFLAGS) -Wno-fatal --cc $< --trace
make -C obj_dir -f ../litedram/extras/sim_dram_verilate.mk VERILATOR_ROOT=$(VERILATOR_ROOT)

SIM_DRAM_CFLAGS = -I. -Iobj_dir -Ilitedram/generated/sim -I$(VERILATOR_ROOT)/include -I$(VERILATOR_ROOT)/include/vltstd
SIM_DRAM_CFLAGS += -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -DVL_PRINTF=printf -faligned-new
sim_litedram_c.o: litedram/extras/sim_litedram_c.cpp verilated_dram
$(CC) $(CPPFLAGS) $(SIM_DRAM_CFLAGS) $(CFLAGS) -c $< -o $@

soc_dram_files = $(soc_files) litedram/extras/wrapper-mw-init.vhdl litedram/generated/sim/litedram-initmem.vhdl
soc_dram_sim_files = $(soc_sim_files) litedram/extras/sim_litedram.vhdl
soc_dram_sim_obj_files = $(soc_sim_obj_files) sim_litedram_c.o
dram_link_files=-Wl,obj_dir/Vlitedram_core__ALL.a -Wl,obj_dir/verilated.o -Wl,obj_dir/verilated_vcd_c.o -Wl,-lstdc++
soc_dram_sim_link=$(patsubst %,-Wl$(comma)%,$(soc_dram_sim_obj_files)) $(dram_link_files)

$(soc_dram_tbs): %: $(core_files) $(soc_dram_files) $(soc_dram_sim_files) $(soc_dram_sim_obj_files) %.vhdl
$(GHDL) -c $(GHDLFLAGS) $(soc_dram_sim_link) $(core_files) $(soc_dram_files) $(soc_dram_sim_files) $@.vhdl -e $@
endif

# Hello world # Hello world
MEMORY_SIZE=8192 MEMORY_SIZE=8192
RAM_INIT_FILE=hello_world/hello_world.hex RAM_INIT_FILE=hello_world/hello_world.hex
@ -167,6 +196,7 @@ _clean:
rm -f *.o work-*cf unisim-*cf $(all) rm -f *.o work-*cf unisim-*cf $(all)
rm -f fpga/*.o fpga/work-*cf rm -f fpga/*.o fpga/work-*cf
rm -f sim-unisim/*.o sim-unisim/unisim-*cf rm -f sim-unisim/*.o sim-unisim/unisim-*cf
rm -f litedram/extras/*.o
rm -f TAGS rm -f TAGS
rm -f scripts/mw_debug/*.o rm -f scripts/mw_debug/*.o
rm -f scripts/mw_debug/mw_debug rm -f scripts/mw_debug/mw_debug

@ -0,0 +1,114 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.common.all;
use work.wishbone_types.all;

entity core_dram_tb is
end core_dram_tb;

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

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

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

soc0: entity work.soc
generic map(
SIM => true,
MEMORY_SIZE => (384*1024),
RAM_INIT_FILE => "main_ram.bin",
RESET_LOW => false,
HAS_DRAM => true,
DRAM_SIZE => 256 * 1024 * 1024,
CLK_FREQ => 100000000
)
port map(
rst => soc_rst,
system_clk => system_clk,
uart0_rxd => '0',
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,
wb_dram_is_csr => wb_dram_is_csr,
wb_dram_is_init => wb_dram_is_init,
alt_reset => core_alt_reset
);

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

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

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

init_done => open,
init_error => open,

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

clk_process: process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;

rst_process: process
begin
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait;
end process;

jtag: entity work.sim_jtag;

end;

@ -21,14 +21,14 @@ class LiteDRAMGenerator(Generator):
if os.path.exists(cpu_file): if os.path.exists(cpu_file):
cpu = pathlib.Path(cpu_file).read_text() cpu = pathlib.Path(cpu_file).read_text()
else: else:
cpu = None cpu = "none"

print("CPU is ", cpu)


# Add files to fusesoc # Add files to fusesoc
files = [] files = []
f = os.path.join(gen_dir, "litedram_core.v") f = os.path.join(gen_dir, "litedram_core.v")
files.append({f : {'file_type' : 'verilogSource'}}) 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") f = os.path.join(gen_dir, "litedram-initmem.vhdl")
files.append({f : {'file_type' : 'vhdlSource-2008'}}) files.append({f : {'file_type' : 'vhdlSource-2008'}})
f = os.path.join(gen_dir, "litedram_core.init") f = os.path.join(gen_dir, "litedram_core.init")
@ -36,8 +36,15 @@ class LiteDRAMGenerator(Generator):


# Look for init CPU types and add corresponding files # Look for init CPU types and add corresponding files
if cpu == "vexriscv": if cpu == "vexriscv":
f = os.path.join(base_dir, "extras", "VexRiscv.v") print("Adding VexRiscv files and wrapper")
f = os.path.join(extras_dir, "VexRiscv.v")
files.append({f : {'file_type' : 'verilogSource'}}) files.append({f : {'file_type' : 'verilogSource'}})
f = os.path.join(extras_dir, "wrapper-self-init.vhdl")
files.append({f : {'file_type' : 'vhdlSource-2008'}})
else:
print("Adding wrapper")
f = os.path.join(extras_dir, "wrapper-mw-init.vhdl")
files.append({f : {'file_type' : 'vhdlSource-2008'}})


self.add_files(files) self.add_files(files)



@ -0,0 +1,10 @@
OPT_FAST=-O3 -fstrict-aliasing
OPT_SLOW=-O3 -fstrict-aliasing

top_all: top_all2

include Vlitedram_core.mk

top_all2: default $(VK_GLOBAL_OBJS)

.PHONY: top_all top_all2

@ -0,0 +1,214 @@
library ieee;
use ieee.std_logic_1164.all;

package sim_litedram is
-- WB req format:
-- 73 .. 71 : cti(2..0)
-- 70 .. 69 : bte(1..0)
-- 68 .. 65 : sel(3..0)
-- 64 : we
-- 63 : stb
-- 62 : cyc
-- 61 .. 32 : addr(29..0)
-- 31 .. 0 : write_data(31..0)
--
procedure litedram_set_wb(req : in std_ulogic_vector(73 downto 0));
attribute foreign of litedram_set_wb : procedure is "VHPIDIRECT litedram_set_wb";

-- WB rsp format:
-- 35 : init_error;
-- 34 : init_done;
-- 33 : err
-- 32 : ack
-- 31 .. 0 : read_data(31..0)
--
procedure litedram_get_wb(rsp : out std_ulogic_vector(35 downto 0));
attribute foreign of litedram_get_wb : procedure is "VHPIDIRECT litedram_get_wb";

-- User req format:
-- 171 : cmd_valid
-- 170 : cmd_we
-- 169 : wdata_valid
-- 168 : rdata_ready
-- 167 .. 144 : cmd_addr(23..0)
-- 143 .. 128 : wdata_we(15..0)
-- 127 .. 0 : wdata_data(127..0)
--
procedure litedram_set_user(req: in std_ulogic_vector(171 downto 0));
attribute foreign of litedram_set_user : procedure is "VHPIDIRECT litedram_set_user";

-- User rsp format:
-- 130 : cmd_ready
-- 129 : wdata_ready
-- 128 : rdata_valid
-- 127 .. 0 : rdata_data(127..0)
procedure litedram_get_user(req: in std_ulogic_vector(130 downto 0));
attribute foreign of litedram_get_user : procedure is "VHPIDIRECT litedram_get_user";
procedure litedram_clock;
attribute foreign of litedram_clock : procedure is "VHPIDIRECT litedram_clock";

procedure litedram_init(trace: integer);
attribute foreign of litedram_init : procedure is "VHPIDIRECT litedram_init";
end sim_litedram;

package body sim_litedram is
procedure litedram_set_wb(req : in std_ulogic_vector(73 downto 0)) is
begin
assert false report "VHPI" severity failure;
end procedure;
procedure litedram_get_wb(rsp : out std_ulogic_vector(35 downto 0)) is
begin
assert false report "VHPI" severity failure;
end procedure;
procedure litedram_set_user(req: in std_ulogic_vector(171 downto 0)) is
begin
assert false report "VHPI" severity failure;
end procedure;
procedure litedram_get_user(req: in std_ulogic_vector(130 downto 0)) is
begin
assert false report "VHPI" severity failure;
end procedure;
procedure litedram_clock is
begin
assert false report "VHPI" severity failure;
end procedure;
procedure litedram_init(trace: integer) is
begin
assert false report "VHPI" severity failure;
end procedure;
end sim_litedram;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.sim_litedram.all;

entity litedram_core is
port(
clk : in std_ulogic;
rst : in std_ulogic;
pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(0 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
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 : 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;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;
init_done : out std_ulogic;
init_error : out std_ulogic;
user_clk : out std_ulogic;
user_rst : out std_ulogic;
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
wb_ctrl_cyc : in std_ulogic;
wb_ctrl_stb : in std_ulogic;
wb_ctrl_ack : out std_ulogic;
wb_ctrl_we : in std_ulogic;
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
wb_ctrl_err : out std_ulogic;
user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_we : in std_ulogic;
user_port_native_0_cmd_addr : in std_ulogic_vector(23 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 entity litedram_core;

architecture behaviour of litedram_core is
signal idone : std_ulogic := '0';
signal ierr : std_ulogic := '0';
signal old_wb_cyc : std_ulogic := '1';
begin
user_rst <= rst;
user_clk <= clk;
pll_locked <= '1';
init_done <= idone;
init_error <= ierr;

poll: process(user_clk)
procedure send_signals is
begin
litedram_set_wb(wb_ctrl_cti & wb_ctrl_bte &
wb_ctrl_sel & wb_ctrl_we &
wb_ctrl_stb & wb_ctrl_cyc &
wb_ctrl_adr & wb_ctrl_dat_w);
litedram_set_user(user_port_native_0_cmd_valid &
user_port_native_0_cmd_we &
user_port_native_0_wdata_valid &
user_port_native_0_rdata_ready &
user_port_native_0_cmd_addr &
user_port_native_0_wdata_we &
user_port_native_0_wdata_data);
end procedure;

procedure recv_signals is
variable wb_response : std_ulogic_vector(35 downto 0);
variable ur_response : std_ulogic_vector(130 downto 0);
begin
litedram_get_wb(wb_response);
wb_ctrl_dat_r <= wb_response(31 downto 0);
wb_ctrl_ack <= wb_response(32);
wb_ctrl_err <= wb_response(33);
idone <= wb_response(34);
ierr <= wb_response(35);
litedram_get_user(ur_response);
user_port_native_0_cmd_ready <= ur_response(130);
user_port_native_0_wdata_ready <= ur_response(129);
user_port_native_0_rdata_valid <= ur_response(128);
user_port_native_0_rdata_data <= ur_response(127 downto 0);
end procedure;

begin
if rising_edge(user_clk) then

send_signals;
recv_signals;
-- Then generate a clock cycle ( 0->1 then 1->0 )
litedram_clock;
recv_signals;
end if;

if falling_edge(user_clk) then
send_signals;
recv_signals;
end if;
end process;

end architecture;

library work;
use work.sim_litedram.all;

entity litedram_trace_stub is
end entity;

architecture behaviour of litedram_trace_stub is
begin
process
begin
litedram_init(1);
wait;
end process;
end architecture;

@ -0,0 +1,198 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <poll.h>

#include "sim_vhpi_c.h"
#include "Vlitedram_core.h"
#include "verilated_vcd_c.h"

static Vlitedram_core *v;
vluint64_t main_time = 0;

#if VM_TRACE
VerilatedVcdC *tfp;
#endif

static void cleanup(void)
{
#if VM_TRACE
if (tfp) {
tfp->flush();
tfp->close();
delete tfp;
}
#endif
}

static inline void check_init(bool traces)
{
if (v)
return;
// XX Catch exceptions ?
v = new Vlitedram_core;
if (!v) {
fprintf(stderr, "Failure allocating litedram core\n");
exit(1);
}
#if VM_TRACE
if (traces) {
// init trace dump
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
v->trace(tfp, 99);
tfp->open("litedram.vcd");
}
#endif
atexit(cleanup);
}

unsigned char get_bit(unsigned char **p)
{
unsigned char b = **p;

*p = *p + 1;

return b == vhpi1 ? 1 : 0;
}

uint64_t get_bits(unsigned char **p, int len)
{
uint64_t r = 0;

while(len--)
r = (r << 1) | get_bit(p);
return r;
}

void set_bit(unsigned char **p, int bit)
{
**p = bit ? vhpi1 : vhpi0;
*p = *p + 1;
}

void set_bits(unsigned char **p, uint64_t val, int len)
{
while(len--)
set_bit(p, (val >> len) & 1);
}

double sc_time_stamp(void)
{
return main_time;
}

#define check_size(s, exp) \
do { \
int __s = (s); \
int __e = (exp); \
if (__s != __e) \
fprintf(stderr, "WARNING: %s exp %d got %d\n", __func__, __e, __s); \
} while(0)

static void do_eval(void)
{
v->eval();
#if VM_TRACE
if (tfp)
tfp->dump((double) main_time);
#endif
}

extern "C" void litedram_set_wb(unsigned char *req)
{
unsigned char *orig = req;

check_init(false);
v->wb_ctrl_cti = get_bits(&req, 3);
v->wb_ctrl_bte = get_bits(&req, 2);
v->wb_ctrl_sel = get_bits(&req, 4);
v->wb_ctrl_we = get_bit(&req);
v->wb_ctrl_stb = get_bit(&req);
v->wb_ctrl_cyc = get_bit(&req);
v->wb_ctrl_adr = get_bits(&req, 30);
v->wb_ctrl_dat_w = get_bits(&req, 32);

check_size(req - orig, 74);

do_eval();
}

extern "C" void litedram_get_wb(unsigned char *req)
{
unsigned char *orig = req;

check_init(false);

set_bit(&req, v->init_error);
set_bit(&req, v->init_done);
set_bit(&req, v->wb_ctrl_err);
set_bit(&req, v->wb_ctrl_ack);
set_bits(&req, v->wb_ctrl_dat_r, 32);

check_size(req - orig, 36);
}

extern "C" void litedram_set_user(unsigned char *req)
{
unsigned char *orig = req;

check_init(false);

v->user_port_native_0_cmd_valid = get_bit(&req);
v->user_port_native_0_cmd_we = get_bit(&req);
v->user_port_native_0_wdata_valid = get_bit(&req);
v->user_port_native_0_rdata_ready = get_bit(&req);
v->user_port_native_0_cmd_addr = get_bits(&req, 24);
v->user_port_native_0_wdata_we = get_bits(&req, 16);
v->user_port_native_0_wdata_data[3] = get_bits(&req, 32);
v->user_port_native_0_wdata_data[2] = get_bits(&req, 32);
v->user_port_native_0_wdata_data[1] = get_bits(&req, 32);
v->user_port_native_0_wdata_data[0] = get_bits(&req, 32);

check_size(req - orig, 172);

do_eval();
}

extern "C" void litedram_get_user(unsigned char *req)
{
unsigned char *orig = req;

check_init(false);

set_bit(&req, v->user_port_native_0_cmd_ready);
set_bit(&req, v->user_port_native_0_wdata_ready);
set_bit(&req, v->user_port_native_0_rdata_valid);
set_bits(&req, v->user_port_native_0_rdata_data[3], 32);
set_bits(&req, v->user_port_native_0_rdata_data[2], 32);
set_bits(&req, v->user_port_native_0_rdata_data[1], 32);
set_bits(&req, v->user_port_native_0_rdata_data[0], 32);

check_size(req - orig, 131);
}

extern "C" void litedram_clock(void)
{
check_init(false);

v->clk = 1;
do_eval();
main_time++;
v->clk = 0;
do_eval();
main_time++;
}

extern "C" void litedram_init(int trace_on)
{
check_init(!!trace_on);
}

@ -9,7 +9,9 @@ use work.wishbone_types.all;
entity litedram_wrapper is entity litedram_wrapper is
generic ( generic (
DRAM_ABITS : positive; DRAM_ABITS : positive;
DRAM_ALINES : positive DRAM_ALINES : positive;
-- Debug
LITEDRAM_TRACE : boolean := false
); );
port( port(
-- LiteDRAM generates the system clock and reset -- LiteDRAM generates the system clock and reset
@ -233,6 +235,13 @@ begin
end if; end if;
end process; end process;


may_trace: if LITEDRAM_TRACE generate
component litedram_trace_stub
end component;
begin
litedram_trace: litedram_trace_stub;
end generate;
litedram: litedram_core litedram: litedram_core
port map( port map(
clk => clk_in, clk => clk_in,

@ -22,7 +22,7 @@ def make_new_dir(base, added):
return r return r
gen_src_dir = os.path.dirname(os.path.realpath(__file__)) gen_src_dir = os.path.dirname(os.path.realpath(__file__))
base_dir = os.path.join(gen_src_dir, os.pardir) base_dir = os.path.normpath(os.path.join(gen_src_dir, os.pardir))
build_top_dir = make_new_dir(base_dir, "build") build_top_dir = make_new_dir(base_dir, "build")
gen_src_dir = os.path.join(base_dir, "gen-src") gen_src_dir = os.path.join(base_dir, "gen-src")
gen_dir = make_new_dir(base_dir, "generated") gen_dir = make_new_dir(base_dir, "generated")
@ -31,7 +31,7 @@ gen_dir = make_new_dir(base_dir, "generated")
# #
# XXX Not working yet # XXX Not working yet
# #
def build_init_code(build_dir): def build_init_code(build_dir, is_sim):


# More path fudging # More path fudging
sw_dir = os.path.join(build_dir, "software"); sw_dir = os.path.join(build_dir, "software");
@ -62,6 +62,8 @@ def build_init_code(build_dir):
add_var("GENINC_DIR", sw_inc_dir) add_var("GENINC_DIR", sw_inc_dir)
add_var("LXSRC_DIR", lxbios_src_dir) add_var("LXSRC_DIR", lxbios_src_dir)
add_var("LXINC_DIR", lxbios_inc_dir) add_var("LXINC_DIR", lxbios_inc_dir)
if is_sim:
add_var("EXTRA_CFLAGS", "-D__SIM__")
write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars)) write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars))


# Build init code # Build init code
@ -76,6 +78,9 @@ def generate_one(t, mw_init):


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


# Is it a simulation ?
is_sim = t is "sim"

# Muck with directory path # Muck with directory path
build_dir = make_new_dir(build_top_dir, t) build_dir = make_new_dir(build_top_dir, t)
t_dir = make_new_dir(gen_dir, t) t_dir = make_new_dir(gen_dir, t)
@ -107,14 +112,16 @@ def generate_one(t, mw_init):
core_config["csr_alignment"] = 64 core_config["csr_alignment"] = 64


# Generate core # Generate core
if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]: if is_sim:
platform = SimPlatform("", io=[])
elif core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
platform = LatticePlatform("LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis") platform = LatticePlatform("LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis")
elif core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]: elif core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]:
platform = XilinxPlatform("", io=[], toolchain="vivado") platform = XilinxPlatform("", io=[], toolchain="vivado")
else: else:
raise ValueError("Unsupported SDRAM PHY: {}".format(core_config["sdram_phy"])) raise ValueError("Unsupported SDRAM PHY: {}".format(core_config["sdram_phy"]))


soc = LiteDRAMCore(platform, core_config, integrated_rom_size=0x6000, csr_data_width=32) soc = LiteDRAMCore(platform, core_config, is_sim = is_sim, integrated_rom_size=0x6000, csr_data_width=32)


# Build into build_dir # Build into build_dir
builder = Builder(soc, output_dir=build_dir, compile_gateware=False) builder = Builder(soc, output_dir=build_dir, compile_gateware=False)
@ -123,32 +130,35 @@ def generate_one(t, mw_init):
# Grab generated gatewar dir # Grab generated gatewar dir
gw_dir = os.path.join(build_dir, "gateware") gw_dir = os.path.join(build_dir, "gateware")


# Generate init-cpu.txt if any and generate init code if none # Generate init-cpu.txt and generate init code
cpu = core_config["cpu"] cpu = core_config["cpu"]
if mw_init: if mw_init:
src_wrap_file = os.path.join(gen_src_dir, "wrapper-mw-init.vhdl") write_to_file(os.path.join(t_dir, "init-cpu.txt"), "none")
src_init_file = build_init_code(build_dir) src_init_file = build_init_code(build_dir, is_sim)
src_initram_file = os.path.join(gen_src_dir, "dram-init-mem.vhdl") src_initram_file = os.path.join(gen_src_dir, "dram-init-mem.vhdl")
else: else:
write_to_file(os.path.join(t_dir, "init-cpu.txt"), cpu) 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_init_file = os.path.join(gw_dir, "mem.init")
src_initram_file = os.path.join(gen_src_dir, "no-init-mem.vhdl") src_initram_file = os.path.join(gen_src_dir, "no-init-mem.vhdl")


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


def main(): def main():


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


# XXX Set mw_init to False to use a local VexRiscV for memory inits # XXX Set mw_init to False to use a local VexRiscV for memory inits
for t in targets: for t in targets:

@ -21,7 +21,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy


#### Flags #### Flags


CPPFLAGS = -nostdinc -D__USE_LIBC CPPFLAGS = -nostdinc -D__USE_LIBC $(EXTRA_CFLAGS)
CPPFLAGS += -I$(SRC_DIR)/libc/include -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../../include CPPFLAGS += -I$(SRC_DIR)/libc/include -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../../include
CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include) CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include)
CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks

@ -8,6 +8,13 @@
#define CSR_BASE DRAM_CTRL_BASE #define CSR_BASE DRAM_CTRL_BASE
#define CONFIG_CPU_NOP "nop" #define CONFIG_CPU_NOP "nop"


#ifdef __SIM__
#define MEMTEST_BUS_SIZE 16
#define MEMTEST_DATA_SIZE 16
#define MEMTEST_ADDR_SIZE 16
#define CONFIG_SIM_DISABLE_DELAYS
#endif

extern void flush_cpu_dcache(void); extern void flush_cpu_dcache(void);
extern void flush_cpu_icache(void); extern void flush_cpu_icache(void);
static inline void flush_l2_cache(void) { } static inline void flush_l2_cache(void) { }

@ -0,0 +1,39 @@
# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

{
# General ------------------------------------------------------------------
"cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"minimal",
"speedgrade": -1, # FPGA speedgrade
"memtype": "DDR3", # DRAM type
"sim" : "True",

# PHY ----------------------------------------------------------------------
"cmd_delay": 0, # Command additional delay (in taps)
"cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K128M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": "A7DDRPHY", # Type of FPGA PHY

# Electrical ---------------------------------------------------------------
"rtt_nom": "60ohm", # Nominal termination
"rtt_wr": "60ohm", # Write termination
"ron": "34ohm", # Output driver impedance

# Frequency ----------------------------------------------------------------
"input_clk_freq": 100e6, # Input clock frequency
"sys_clk_freq": 100e6, # System clock frequency (DDR_clk = 4 x sys_clk)
"iodelay_clk_freq": 200e6, # IODELAYs reference clock frequency

# Core ---------------------------------------------------------------------
"cmd_buffer_depth": 16, # Depth of the command buffer

# User Ports ---------------------------------------------------------------
"user_ports": {
"native_0": {
"type": "native",
},
},
}

@ -1,284 +0,0 @@
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 litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive
);
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
clk_in : in std_ulogic;
rst : in std_ulogic;
system_clk : out std_ulogic;
system_reset : out std_ulogic;
core_alt_reset : out std_ulogic;
pll_locked : out std_ulogic;

-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
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;
serial_rx : in std_ulogic;

-- Misc
init_done : out std_ulogic;
init_error : out std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
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 : 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;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity litedram_wrapper;

architecture behaviour of litedram_wrapper is

component litedram_core port (
clk : in std_ulogic;
rst : 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);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
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 : 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;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;
init_done : out std_ulogic;
init_error : out std_ulogic;
user_clk : out std_ulogic;
user_rst : out std_ulogic;
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
wb_ctrl_cyc : in std_ulogic;
wb_ctrl_stb : in std_ulogic;
wb_ctrl_ack : out std_ulogic;
wb_ctrl_we : in std_ulogic;
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
wb_ctrl_err : out std_ulogic;
user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_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;
signal user_port0_cmd_valid : std_ulogic;
signal user_port0_cmd_ready : std_ulogic;
signal user_port0_cmd_we : std_ulogic;
signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0);
signal user_port0_wdata_valid : std_ulogic;
signal user_port0_wdata_ready : std_ulogic;
signal user_port0_wdata_we : std_ulogic_vector(15 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(127 downto 0);
signal user_port0_rdata_valid : std_ulogic;
signal user_port0_rdata_ready : std_ulogic;
signal user_port0_rdata_data : std_ulogic_vector(127 downto 0);

signal ad3 : std_ulogic;

signal wb_ctrl_adr : std_ulogic_vector(29 downto 0);
signal wb_ctrl_dat_w : std_ulogic_vector(31 downto 0);
signal wb_ctrl_dat_r : std_ulogic_vector(31 downto 0);
signal wb_ctrl_sel : std_ulogic_vector(3 downto 0);
signal wb_ctrl_cyc : std_ulogic;
signal wb_ctrl_stb : std_ulogic;
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;

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;

begin

-- alternate core reset address set when DRAM is not initialized.
core_alt_reset <= not init_done;

-- 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
);

--
-- Control bus wishbone: This muxes the wishbone to the CSRs
-- and an internal small one to the init BRAM
--

-- 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;

-- 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;

-- 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);

-- 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';
user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
user_port0_wdata_data <= wb_in.dat & wb_in.dat;
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- 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 <= 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;

-- DRAM user port State machine
sm: process(system_clk)
begin
if rising_edge(system_clk) then
if system_reset = '1' then
state <= CMD;
else
case state is
when CMD =>
if (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD;
end if;
when MWRITE =>
if user_port0_wdata_ready = '1' then
state <= CMD;
end if;
when MREAD =>
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
end case;
end if;
end if;
end process;

litedram: litedram_core
port map(
clk => clk_in,
rst => rst,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n,
init_done => init_done,
init_error => init_error,
user_clk => system_clk,
user_rst => system_reset,
wb_ctrl_adr => wb_ctrl_adr,
wb_ctrl_dat_w => wb_ctrl_dat_w,
wb_ctrl_dat_r => wb_ctrl_dat_r,
wb_ctrl_sel => wb_ctrl_sel,
wb_ctrl_cyc => wb_ctrl_cyc,
wb_ctrl_stb => wb_ctrl_stb,
wb_ctrl_ack => wb_ctrl_ack,
wb_ctrl_we => wb_ctrl_we,
wb_ctrl_cti => "000",
wb_ctrl_bte => "00",
wb_ctrl_err => open,
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;

@ -1443,7 +1443,7 @@ e8010010ebc1fff0
203a4b4c43202020 203a4b4c43202020
7a484d20646c6c25 7a484d20646c6c25
000000000000000a 000000000000000a
6138393331393333 6131333764343635
0000000000000000 0000000000000000
0033306536316430 0033306536316430
4d4152446574694c 4d4152446574694c

@ -1,5 +1,5 @@
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-21 19:21:27 // Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-22 17:57:16
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
module litedram_core( module litedram_core(
input wire clk, input wire clk,

@ -1,284 +0,0 @@
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 litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive
);
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
clk_in : in std_ulogic;
rst : in std_ulogic;
system_clk : out std_ulogic;
system_reset : out std_ulogic;
core_alt_reset : out std_ulogic;
pll_locked : out std_ulogic;

-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
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;
serial_rx : in std_ulogic;

-- Misc
init_done : out std_ulogic;
init_error : out std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
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 : 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;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity litedram_wrapper;

architecture behaviour of litedram_wrapper is

component litedram_core port (
clk : in std_ulogic;
rst : 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);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
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 : 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;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;
init_done : out std_ulogic;
init_error : out std_ulogic;
user_clk : out std_ulogic;
user_rst : out std_ulogic;
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
wb_ctrl_cyc : in std_ulogic;
wb_ctrl_stb : in std_ulogic;
wb_ctrl_ack : out std_ulogic;
wb_ctrl_we : in std_ulogic;
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
wb_ctrl_err : out std_ulogic;
user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_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;
signal user_port0_cmd_valid : std_ulogic;
signal user_port0_cmd_ready : std_ulogic;
signal user_port0_cmd_we : std_ulogic;
signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0);
signal user_port0_wdata_valid : std_ulogic;
signal user_port0_wdata_ready : std_ulogic;
signal user_port0_wdata_we : std_ulogic_vector(15 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(127 downto 0);
signal user_port0_rdata_valid : std_ulogic;
signal user_port0_rdata_ready : std_ulogic;
signal user_port0_rdata_data : std_ulogic_vector(127 downto 0);

signal ad3 : std_ulogic;

signal wb_ctrl_adr : std_ulogic_vector(29 downto 0);
signal wb_ctrl_dat_w : std_ulogic_vector(31 downto 0);
signal wb_ctrl_dat_r : std_ulogic_vector(31 downto 0);
signal wb_ctrl_sel : std_ulogic_vector(3 downto 0);
signal wb_ctrl_cyc : std_ulogic;
signal wb_ctrl_stb : std_ulogic;
signal wb_ctrl_ack : std_ulogic;
signal wb_ctrl_we : std_ulogic;

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;

begin

-- alternate core reset address set when DRAM is not initialized.
core_alt_reset <= not init_done;

-- 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
);

--
-- Control bus wishbone: This muxes the wishbone to the CSRs
-- and an internal small one to the init BRAM
--

-- 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;

-- 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;

-- 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);

-- 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';
user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
user_port0_wdata_data <= wb_in.dat & wb_in.dat;
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- 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 <= 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;

-- DRAM user port State machine
sm: process(system_clk)
begin
if rising_edge(system_clk) then
if system_reset = '1' then
state <= CMD;
else
case state is
when CMD =>
if (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD;
end if;
when MWRITE =>
if user_port0_wdata_ready = '1' then
state <= CMD;
end if;
when MREAD =>
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
end case;
end if;
end if;
end process;

litedram: litedram_core
port map(
clk => clk_in,
rst => rst,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n,
init_done => init_done,
init_error => init_error,
user_clk => system_clk,
user_rst => system_reset,
wb_ctrl_adr => wb_ctrl_adr,
wb_ctrl_dat_w => wb_ctrl_dat_w,
wb_ctrl_dat_r => wb_ctrl_dat_r,
wb_ctrl_sel => wb_ctrl_sel,
wb_ctrl_cyc => wb_ctrl_cyc,
wb_ctrl_stb => wb_ctrl_stb,
wb_ctrl_ack => wb_ctrl_ack,
wb_ctrl_we => wb_ctrl_we,
wb_ctrl_cti => "000",
wb_ctrl_bte => "00",
wb_ctrl_err => open,
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;

@ -1443,7 +1443,7 @@ e8010010ebc1fff0
203a4b4c43202020 203a4b4c43202020
7a484d20646c6c25 7a484d20646c6c25
000000000000000a 000000000000000a
6138393331393333 6131333764343635
0000000000000000 0000000000000000
0033306536316430 0033306536316430
4d4152446574694c 4d4152446574694c

@ -1,5 +1,5 @@
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Auto-generated by Migen (0d16e03) & LiteX (3391398a) on 2020-05-21 19:21:29 // Auto-generated by Migen (0d16e03) & LiteX (564d731a) on 2020-05-22 17:57:18
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
module litedram_core( module litedram_core(
input wire clk, input wire clk,

@ -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/generated/sim/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;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save