Merge pull request #229 from ozbenh/litedram

Litedram: Misc improvements and support for different DRAM geometries
jtag-port
Michael Neuling 4 years ago committed by GitHub
commit d200733252
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -120,6 +120,8 @@ begin
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 1,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => ROM_SIZE
)

@ -43,6 +43,8 @@ begin
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 1,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => DRAM_INIT_FILE,
PAYLOAD_SIZE => DRAM_INIT_SIZE
)
@ -293,6 +295,43 @@ begin
check_data(make_pattern(i));
end loop;

report "Pre-fill a line";
a(11) := '1';
clr_acks;
wb_write(add_off(a, 0), x"1111111100000000", x"ff");
wb_write(add_off(a, 8), x"3333333322222222", x"ff");
wb_write(add_off(a, 16), x"5555555544444444", x"ff");
wb_write(add_off(a, 24), x"7777777766666666", x"ff");
wb_write(add_off(a, 32), x"9999999988888888", x"ff");
wb_write(add_off(a, 40), x"bbbbbbbbaaaaaaaa", x"ff");
wb_write(add_off(a, 48), x"ddddddddcccccccc", x"ff");
wb_write(add_off(a, 56), x"ffffffffeeeeeeee", x"ff");
wb_write(add_off(a, 64), x"1111111100000000", x"ff");
wb_write(add_off(a, 72), x"3333333322222222", x"ff");
wb_write(add_off(a, 80), x"5555555544444444", x"ff");
wb_write(add_off(a, 88), x"7777777766666666", x"ff");
wb_write(add_off(a, 96), x"9999999988888888", x"ff");
wb_write(add_off(a,104), x"bbbbbbbbaaaaaaaa", x"ff");
wb_write(add_off(a,112), x"ddddddddcccccccc", x"ff");
wb_write(add_off(a,120), x"ffffffffeeeeeeee", x"ff");
wait_acks(16);

report "Scattered from middle of line...";
clr_acks;
wb_read(add_off(a,24));
wb_read(add_off(a,32));
wb_read(add_off(a, 0));
wb_read(add_off(a,16));
wait_acks(4);
read_data(d);
assert d = x"7777777766666666" report "bad data (24), got " & to_hstring(d) severity failure;
read_data(d);
assert d = x"9999999988888888" report "bad data (32), got " & to_hstring(d) severity failure;
read_data(d);
assert d = x"1111111100000000" report "bad data (0), got " & to_hstring(d) severity failure;
read_data(d);
assert d = x"5555555544444444" report "bad data (16), got " & to_hstring(d) severity failure;

std.env.finish;
end process;
end architecture;

@ -341,6 +341,8 @@ begin
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 14,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)

@ -258,6 +258,8 @@ begin
generic map(
DRAM_ABITS => 25,
DRAM_ALINES => 15,
DRAM_DLINES => 16,
DRAM_PORT_WIDTH => 128,
PAYLOAD_FILE => RAM_INIT_FILE,
PAYLOAD_SIZE => PAYLOAD_SIZE
)

@ -10,8 +10,10 @@ use work.helpers.all;

entity litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive;
DRAM_ABITS : positive;
DRAM_ALINES : natural;
DRAM_DLINES : natural;
DRAM_PORT_WIDTH : positive;

-- Pseudo-ROM payload
PAYLOAD_SIZE : natural;
@ -63,10 +65,10 @@ entity litedram_wrapper is
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_dm : out std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
@ -87,10 +89,10 @@ architecture behaviour of litedram_wrapper is
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_dm : out std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dq : inout std_ulogic_vector(DRAM_DLINES-1 downto 0);
ddram_dqs_p : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(DRAM_DLINES/8-1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
@ -117,11 +119,11 @@ architecture behaviour of litedram_wrapper is
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_wdata_we : in std_ulogic_vector(DRAM_PORT_WIDTH/8-1 downto 0);
user_port_native_0_wdata_data : in std_ulogic_vector(DRAM_PORT_WIDTH-1 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)
user_port_native_0_rdata_data : out std_ulogic_vector(DRAM_PORT_WIDTH-1 downto 0)
);
end component;
@ -131,11 +133,11 @@ architecture behaviour of litedram_wrapper is
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_wdata_we : std_ulogic_vector(DRAM_PORT_WIDTH/8-1 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(DRAM_PORT_WIDTH-1 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 user_port0_rdata_data : std_ulogic_vector(DRAM_PORT_WIDTH-1 downto 0);

signal wb_ctrl_adr : std_ulogic_vector(29 downto 0);
signal wb_ctrl_dat_w : std_ulogic_vector(31 downto 0);
@ -150,14 +152,24 @@ architecture behaviour of litedram_wrapper is
signal wb_init_out : wb_io_slave_out;

-- DRAM data port width
constant DRAM_DBITS : natural := 128;
constant DRAM_DBITS : natural := DRAM_PORT_WIDTH;
-- DRAM data port sel bits
constant DRAM_SBITS : natural := (DRAM_DBITS / 8);

-- WB geometry (just a few shortcuts)
constant WBL : positive := wb_in.dat'length;
constant WBSL : positive := wb_in.sel'length;

-- Select a WB word inside DRAM port width
constant WB_WORD_COUNT : positive := DRAM_DBITS/WBL;
constant WB_WSEL_BITS : positive := log2(WB_WORD_COUNT);
constant WB_WSEL_RIGHT : positive := log2(WBL/8);

-- BRAM organisation: We never access more than wishbone_data_bits at
-- a time so to save resources we make the array only that wide, and
-- use consecutive indices for to make a cache "line"
--
-- ROW_SIZE is the width in bytes of the BRAM (based on litedram, so 128-bits)
-- ROW_SIZE is the width in bytes of the BRAM, ie, litedram port width
constant ROW_SIZE : natural := DRAM_DBITS / 8;
-- ROW_PER_LINE is the number of row (litedram transactions) in a line
constant ROW_PER_LINE : natural := LINE_SIZE / ROW_SIZE;
@ -184,11 +196,12 @@ architecture behaviour of litedram_wrapper is
-- TAG_BITS is the number of bits of the tag part of the address
constant TAG_BITS : natural := REAL_ADDR_BITS - SET_SIZE_BITS;
-- WAY_BITS is the number of bits to select a way
constant WAY_BITS : natural := log2(NUM_WAYS);
constant WAY_BITS : natural := log2(NUM_WAYS);

subtype row_t is integer range 0 to BRAM_ROWS-1;
subtype index_t is integer range 0 to NUM_LINES-1;
subtype way_t is integer range 0 to NUM_WAYS-1;
subtype row_in_line_t is unsigned(ROW_LINEBITS-1 downto 0);

-- The cache data BRAM organized as described above for each way
subtype cache_row_t is std_ulogic_vector(DRAM_DBITS-1 downto 0);
@ -207,6 +220,9 @@ architecture behaviour of litedram_wrapper is
subtype cache_way_valids_t is std_ulogic_vector(NUM_WAYS-1 downto 0);
type cache_valids_t is array(index_t) of cache_way_valids_t;

-- "Temporary" valid bits for the rows of the currently refilled line
type row_per_line_valid_t is array(0 to ROW_PER_LINE - 1) of std_ulogic;

-- Storage. Hopefully "cache_rows" is a BRAM, the rest is LUTs
signal cache_tags : cache_tags_array_t;
signal cache_valids : cache_valids_t;
@ -217,10 +233,10 @@ architecture behaviour of litedram_wrapper is
--
-- Store queue signals
--
-- We store a single wishbone dword per entry (64-bit) but all
-- 16 sel bits for the DRAM.
-- XXX Investigate storing only AD3 and 8 sel bits if it's better
constant STOREQ_BITS : positive := wishbone_data_bits + DRAM_SBITS;
-- We store a single wishbone dword per entry (64-bit)
-- along with the wishbone sel bits and the necessary address
-- bits to select which part of DRAM port to write to.
constant STOREQ_BITS : positive := WBL + WBSL + WB_WSEL_BITS;

signal storeq_rd_ready : std_ulogic;
signal storeq_rd_valid : std_ulogic;
@ -233,7 +249,7 @@ architecture behaviour of litedram_wrapper is
-- Cache management signals
--

-- Cache state machine
-- Cache state machine
type state_t is (IDLE, -- Normal load hit processing
REFILL_CLR_TAG, -- Cache refill clear tag
REFILL_WAIT_ACK); -- Cache refill wait ack
@ -247,8 +263,8 @@ architecture behaviour of litedram_wrapper is
-- Read pipeline (to handle cache RAM latency)
signal read_ack_0 : std_ulogic := '0';
signal read_ack_1 : std_ulogic := '0';
signal read_ad3_0 : std_ulogic;
signal read_ad3_1 : std_ulogic;
signal read_wsl_0 : std_ulogic_vector(WB_WSEL_BITS-1 downto 0) := (others => '0');
signal read_wsl_1 : std_ulogic_vector(WB_WSEL_BITS-1 downto 0) := (others => '0');
signal read_way_0 : way_t;
signal read_way_1 : way_t;

@ -261,7 +277,8 @@ architecture behaviour of litedram_wrapper is
OP_LOAD_HIT,
OP_LOAD_MISS,
OP_STORE_HIT,
OP_STORE_MISS);
OP_STORE_MISS,
OP_STORE_DELAYED);

signal req_index : index_t;
signal req_row : row_t;
@ -269,10 +286,9 @@ architecture behaviour of litedram_wrapper is
signal req_tag : cache_tag_t;
signal req_op : req_op_t;
signal req_laddr : std_ulogic_vector(REAL_ADDR_BITS-1 downto 0);
signal req_ad3 : std_ulogic;
signal req_wsl : std_ulogic_vector(WB_WSEL_BITS-1 downto 0);
signal req_we : std_ulogic_vector(DRAM_SBITS-1 downto 0);
signal req_wdata : std_ulogic_vector(DRAM_DBITS-1 downto 0);
signal accept_store : std_ulogic;
signal stall : std_ulogic;

-- Line refill command signals and latches
@ -281,6 +297,8 @@ architecture behaviour of litedram_wrapper is
signal refill_way : way_t;
signal refill_index : index_t;
signal refill_row : row_t;
signal refill_end_row : row_in_line_t;
signal refill_rows_vlid : row_per_line_valid_t;

-- Cache RAM interface
type cache_ram_out_t is array(way_t) of cache_row_t;
@ -306,21 +324,25 @@ architecture behaviour of litedram_wrapper is
return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS)));
end;

-- Return the index of a row within a line
function get_row_of_line(row: row_t) return row_in_line_t is
variable row_v : unsigned(ROW_BITS-1 downto 0);
begin
row_v := to_unsigned(row, ROW_BITS);
return row_v(ROW_LINEBITS-1 downto 0);
end;
-- Returns whether this is the last row of a line. It takes a DRAM address
function is_last_row_addr(addr: std_ulogic_vector(REAL_ADDR_BITS-1 downto ROW_OFF_BITS))
function is_last_row_addr(addr: std_ulogic_vector(REAL_ADDR_BITS-1 downto ROW_OFF_BITS);
last: row_in_line_t)
return boolean is
constant ones : std_ulogic_vector(ROW_LINEBITS-1 downto 0) := (others => '1');
begin
return addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS) = ones;
return unsigned(addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS)) = last;
end;

-- Returns whether this is the last row of a line
function is_last_row(row: row_t) return boolean is
variable row_v : std_ulogic_vector(ROW_BITS-1 downto 0);
constant ones : std_ulogic_vector(ROW_LINEBITS-1 downto 0) := (others => '1');
function is_last_row(row: row_t; last: row_in_line_t) return boolean is
begin
row_v := std_ulogic_vector(to_unsigned(row, ROW_BITS));
return row_v(ROW_LINEBITS-1 downto 0) = ones;
return get_row_of_line(row) = last;
end;

-- Return the address of the next row in the current cache line. It takes a
@ -387,8 +409,6 @@ begin
report "geometry bits don't add up" severity FAILURE;
assert (REAL_ADDR_BITS = TAG_BITS + ROW_BITS + ROW_OFF_BITS)
report "geometry bits don't add up" severity FAILURE;
assert (128 = DRAM_DBITS)
report "Can't yet handle a DRAM width that isn't 128-bits" severity FAILURE;

-- alternate core reset address set when DRAM is not initialized.
core_alt_reset <= not init_done;
@ -493,7 +513,7 @@ begin
--
-- Write mux: cache refills from DRAM or writes from Wishbone
--
if state = IDLE then
if req_op = OP_STORE_HIT and req_hit_way = i then
-- Write from wishbone
wr_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS));
wr_data <= req_wdata;
@ -570,7 +590,7 @@ begin
end generate;

--
-- Wishbone interface:
-- Wishbone request interface:
--
-- - Incoming wishbone request latch (to help with timing)
-- - Read response pipeline (to match BRAM output buffer delay)
@ -632,16 +652,15 @@ begin
--
-- Read response pipeline
--
-- XXX Might have to put store acks in there too (see comment in wb_response)
read_pipe: process(system_clk)
begin
if rising_edge(system_clk) then
read_ack_0 <= '1' when req_op = OP_LOAD_HIT else '0';
read_ad3_0 <= req_ad3;
read_wsl_0 <= req_wsl;
read_way_0 <= req_hit_way;

read_ack_1 <= read_ack_0;
read_ad3_1 <= read_ad3_0;
read_wsl_1 <= read_wsl_0;
read_way_1 <= read_way_0;

if TRACE then
@ -670,58 +689,54 @@ begin
end if;
end process;

wb_reponse: process(all)
variable rdata : std_ulogic_vector(DRAM_DBITS-1 downto 0);
variable store_done : std_ulogic;
--
-- Wishbone response generation
--

wb_rseponse: process(all)
variable rdata : std_ulogic_vector(DRAM_DBITS-1 downto 0);
variable store_done : std_ulogic;
variable accept_store : std_ulogic;
variable wsel : natural range 0 to WB_WORD_COUNT-1;
begin
-- Can we accept a store ? This is set when IDLE and the store
-- queue & command queue are not full.
-- Can we accept a store ? This is set when the store queue & command
-- queue are not full.
--
-- Note: This is only used to control the WB request latch, stall
-- and store "early complete". We don't want to use this to control
-- cmd_valid to DRAM as this would create a circular dependency inside
-- LiteDRAM as cmd_ready I think is driven from cmd_valid.
-- This does *not* mean that we will accept the store, there are other
-- reasons to delay them (see OP_STORE_DELAYED).
--
-- The state machine that controls the command queue must thus
-- reproduce this logic at least partially.
-- A store is fully accepted when *both* req_op is not OP_STORE_DELAYED
-- and accept_store is '1'.
--
-- Note also that user_port0_cmd_ready from LiteDRAM is combinational
-- from user_port0_cmd_valid. IE. we won't know that LiteDRAM cannot
-- accept a command until we try to send one.
-- The reason for this split is to avoid a circular dependency inside
-- LiteDRAM, since cmd_ready from litedram is driven from cmd_valid (*)
-- we don't want to generate cmd_valid from cmd_ready. So we generate
-- it instead from all the *other* conditions that make a store valid.
--
if state = IDLE then
accept_store <= user_port0_cmd_ready and storeq_wr_ready;

-- Corner case !!! The read acks pipeline takes two extra cycles
-- which means a store ack can collide with a previous load hit
-- ack. Thus we stall stores if we have a load ack pending.
if read_ack_0 = '1' or read_ack_1 = '1' then
accept_store <= '0';
end if;
-- (*) It's my understanding that user_port0_cmd_ready from LiteDRAM is
-- ombinational from user_port0_cmd_valid along with a bunch of other
-- internal signals. IE. we won't know that LiteDRAM cannot accept a
-- command until we try to send one.
--
accept_store := user_port0_cmd_ready and storeq_wr_ready;

-- Generate stalls. For stores we stall if we can't accept it.
-- For loads, we stall if we are going to take a load miss or
-- are in the middle of a refill and it isn't a partial hit.
if req_op = OP_STORE_MISS or req_op = OP_STORE_HIT then
stall <= not accept_store;
elsif req_op = OP_LOAD_MISS or req_op = OP_STORE_DELAYED then
stall <= '1';
else
accept_store <= '0';
stall <= '0';
end if;

-- Generate stalls. For loads, we stall if we are going to take a load
-- miss or are in the middle of a refill. For stores, if we can't
-- accept it.
case state is
when IDLE =>
case req_op is
when OP_LOAD_MISS =>
stall <= '1';
when OP_STORE_MISS | OP_STORE_HIT =>
stall <= not accept_store;
when others =>
stall <= '0';
end case;
when others =>
stall <= '1';
end case;
-- Data out mux
rdata := cache_out(read_way_1);
wb_out.dat <= rdata(127 downto 64) when read_ad3_1 = '1' else rdata(63 downto 0);

-- Hard wired for 64-bit wishbone
wsel := to_integer(unsigned(read_wsl_1));
wb_out.dat <= rdata((wsel+1)*WBL-1 downto wsel*WBL);

-- Early-complete stores on wishbone.
if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
@ -736,7 +751,8 @@ begin
-- Generate Wishbone ACKs on read hits and store complete
--
-- This can happen on store right behind loads ! This is why
-- we don't accept a new store right behind a load ack above.
-- we delay a store when a load ack is in the pipeline in the
-- request decoder below.
--
wb_out.ack <= read_ack_1 or store_ack_1;
assert read_ack_1 = '0' or store_ack_1 = '0' report
@ -748,60 +764,99 @@ begin
-- Cache request decode
--
request_decode: process(all)
variable valid : std_ulogic;
variable is_hit : std_ulogic;
variable hit_way : way_t;
variable valid : boolean;
variable is_hit : boolean;
variable store_delay : boolean;
variable hit_way : way_t;
begin
-- Extract line, row and tag from request
req_index <= get_index(wb_req.adr);
req_row <= get_row(wb_req.adr(REAL_ADDR_BITS-1 downto 0));
req_tag <= get_tag(wb_req.adr);

-- Calculate address of beginning of cache line, will be
-- Calculate address of beginning of cache row, will be
-- used for cache miss processing if needed
req_laddr <= wb_req.adr(REAL_ADDR_BITS - 1 downto LINE_OFF_BITS) &
(LINE_OFF_BITS-1 downto 0 => '0');
req_laddr <= wb_req.adr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS) &
(ROW_OFF_BITS-1 downto 0 => '0');


-- Do we have a valid request in the WB latch ?
if state = IDLE then
valid := wb_req.cyc and wb_req.stb;
else
valid := '0';
end if;
valid := wb_req.cyc = '1' and wb_req.stb = '1';

-- Store signals
req_ad3 <= wb_req.adr(3);
req_wdata <= wb_req.dat & wb_req.dat;
req_we <= wb_req.sel & "00000000" when req_ad3 = '1' else
"00000000" & wb_req.sel;
-- Store signals (hard wired for 64-bit wishbone at the moment)
req_wsl <= wb_req.adr(WB_WSEL_RIGHT+WB_WSEL_BITS-1 downto WB_WSEL_RIGHT);
for i in 0 to WB_WORD_COUNT-1 loop
if to_integer(unsigned(req_wsl)) = i then
req_we(WBSL*(i+1)-1 downto WBSL*i) <= wb_req.sel;
else
req_we(WBSL*(i+1)-1 downto WBSL*i) <= x"00";
end if;
req_wdata(WBL*(i+1)-1 downto WBL*i) <= wb_req.dat;
end loop;

-- Test if pending request is a hit on any way
hit_way := 0;
is_hit := '0';
is_hit := false;
for i in way_t loop
if valid = '1' and cache_valids(req_index)(i) = '1' then
if valid and
(cache_valids(req_index)(i) = '1' or
(state = REFILL_WAIT_ACK and
req_index = refill_index and i = refill_way and
refill_rows_vlid(req_row mod ROW_PER_LINE) = '1')) then
if read_tag(i, cache_tags(req_index)) = req_tag then
hit_way := i;
is_hit := '1';
is_hit := true;
end if;
end if;
end loop;

-- We need to delay stores under some circumstances to avoid
-- collisions with the refill machine.
--
-- Corner case !!! The read acks pipeline takes two extra cycles
-- which means a store ack can collide with a previous load hit
-- ack. Thus we stall stores if we have a load ack pending.
--
if read_ack_0 = '1' or read_ack_1 = '1' then
-- Clash with pending read acks, delay..
store_delay := true;
elsif state /= IDLE then
-- If the reload machine is active, we cannot accept a store
-- for now.
--
-- We could improve this a bit by allowing stores if we have sent
-- all the requests down to litedram (we are only waiting for the
-- responses) *and* either of those conditions is true:
--
-- * It's a miss (doesn't require a write to BRAM) and isn't
-- for the line being reloaded (otherwise we might reload
-- stale data into the cache).
-- * It's a hit on a different way than the one being reloaded
-- in which case there is no conflict for BRAM access.
--
-- Otherwise we delay it...
--
store_delay := true;
else
store_delay := false;
end if;

-- Generate the req op. We only allow OP_LOAD_* when in the
-- IDLE state as our PLRU and ACK generation rely on this,
-- stores are allowed in IDLE state.
--
req_op <= OP_NONE;
if valid = '1' then
if valid then
if wb_req.we = '1' then
if is_hit = '1' then
if store_delay then
req_op <= OP_STORE_DELAYED;
elsif is_hit then
req_op <= OP_STORE_HIT;
else
req_op <= OP_STORE_MISS;
end if;
else
if is_hit = '1' then
if is_hit then
req_op <= OP_LOAD_HIT;
else
req_op <= OP_LOAD_MISS;
@ -833,21 +888,38 @@ begin

storeq_control : process(all)
variable stq_data : wishbone_data_type;
variable stq_sel : std_ulogic_vector(DRAM_SBITS-1 downto 0);
variable stq_sel : wishbone_sel_type;
variable stq_wsl : std_ulogic_vector(WB_WSEL_BITS-1 downto 0);
begin
storeq_wr_data <= wb_req.dat & req_we;
storeq_wr_data <= wb_req.dat & wb_req.sel &
wb_req.adr(WB_WSEL_RIGHT+WB_WSEL_BITS-1 downto WB_WSEL_RIGHT);

-- Only accept store if we can send a command
-- Only queue stores if we can also send a command
if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
storeq_wr_valid <= user_port0_cmd_ready;
else
storeq_wr_valid <= '0';
end if;

stq_data := storeq_rd_data(storeq_rd_data'left downto DRAM_SBITS);
stq_sel := storeq_rd_data(DRAM_SBITS-1 downto 0);
user_port0_wdata_data <= stq_data & stq_data;
user_port0_wdata_we <= stq_sel;
-- Store signals (hard wired for 64-bit wishbone at the moment)
stq_data := storeq_rd_data(storeq_rd_data'left downto WBSL+WB_WSEL_BITS);
stq_sel := storeq_rd_data(WBSL+WB_WSEL_BITS-1 downto WB_WSEL_BITS);
stq_wsl := storeq_rd_data(WB_WSEL_BITS-1 downto 0);
for i in 0 to WB_WORD_COUNT-1 loop
if to_integer(unsigned(stq_wsl)) = i then
user_port0_wdata_we(WBSL*(i+1)-1 downto WBSL*i) <= stq_sel;
else
user_port0_wdata_we(WBSL*(i+1)-1 downto WBSL*i) <= x"00";
end if;
user_port0_wdata_data(WBL*(i+1)-1 downto WBL*i) <= stq_data;
end loop;

-- Note: Current litedram ignores user_port0_wdata_valid. We
-- must make sure to always have the data available at the
-- output of the store queue when we send the write command.
--
-- Thankfully this is always the case with this design.
--
user_port0_wdata_valid <= storeq_rd_valid;
storeq_rd_ready <= user_port0_wdata_ready;

@ -858,13 +930,13 @@ begin
to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) &
" data:" & to_hstring(req_wdata) &
" we:" & to_hstring(req_we) &
" V:" & std_ulogic'image(accept_store);
" V:" & std_ulogic'image(user_port0_cmd_ready);
else
report "Store miss to:" &
to_hstring(wb_req.adr(DRAM_ABITS+3 downto 0)) &
" data:" & to_hstring(req_wdata) &
" we:" & to_hstring(req_we) &
" V:" & std_ulogic'image(accept_store);
" V:" & std_ulogic'image(user_port0_cmd_ready);
end if;
if storeq_wr_valid = '1' and storeq_wr_ready = '1' then
report "storeq push " & to_hstring(storeq_wr_data);
@ -879,10 +951,10 @@ begin
-- LiteDRAM command mux
dram_commands: process(all)
begin
if state = IDLE and (req_op = OP_STORE_HIT or req_op = OP_STORE_MISS) then
if req_op = OP_STORE_HIT or req_op = OP_STORE_MISS then
-- For stores, forward signals directly. Only send command if
-- the FIFO can accept a store
user_port0_cmd_addr <= wb_req.adr(DRAM_ABITS+3 downto 4);
-- the FIFO can accept a store.
user_port0_cmd_addr <= wb_req.adr(DRAM_ABITS+ROW_OFF_BITS-1 downto ROW_OFF_BITS);
user_port0_cmd_we <= '1';
user_port0_cmd_valid <= storeq_wr_ready;
else
@ -891,6 +963,9 @@ begin
user_port0_cmd_valid <= refill_cmd_valid;
user_port0_cmd_we <= '0';
end if;

-- Note: litedram ignores this signal and assumes we are
-- always ready to accept read data.
user_port0_rdata_ready <= '1'; -- Always 1
end process;

@ -918,6 +993,11 @@ begin
assert refill_cmd_valid = '0' report "refill cmd valid in IDLE state !"
severity failure;

-- Reset per-row valid flags, only used in WAIT_ACK
for i in 0 to ROW_PER_LINE - 1 loop
refill_rows_vlid(i) <= '0';
end loop;

-- If NO_LS_OVERLAP is set, disallow a load miss if the store
-- queue still has data in it.
wait_qdrain := false;
@ -931,8 +1011,9 @@ begin
refill_way <= to_integer(unsigned(plru_victim(req_index)));

-- Keep track of our index and way for subsequent stores
refill_index <= req_index;
refill_row <= get_row(req_laddr);
refill_index <= req_index;
refill_row <= get_row(req_laddr);
refill_end_row <= get_row_of_line(get_row(req_laddr)) - 1;

-- Prep for first DRAM read
--
@ -941,7 +1022,7 @@ begin
-- "dram_commands". In fact, we could make refill_cmd_addr
-- only contain the "counter" bits and wire it with the
-- other bits from req_laddr.
refill_cmd_addr <= req_laddr(DRAM_ABITS+3 downto 4);
refill_cmd_addr <= req_laddr(DRAM_ABITS+ROW_OFF_BITS-1 downto ROW_OFF_BITS);
refill_cmd_valid <= '1';

if TRACE then
@ -982,7 +1063,7 @@ begin
if TRACE then
report "got refill cmd ack !";
end if;
if is_last_row_addr(refill_cmd_addr) then
if is_last_row_addr(refill_cmd_addr, refill_end_row) then
refill_cmd_valid <= '0';
cmds_done := true;
if TRACE then
@ -1003,8 +1084,12 @@ begin
if TRACE then
report "got refill data ack !";
end if;

-- Mark partial line valid
refill_rows_vlid(refill_row mod ROW_PER_LINE) <= '1';

-- Check for completion
if cmds_done and is_last_row(refill_row) then
if cmds_done and is_last_row(refill_row, refill_end_row) then
if TRACE then
report "all refill data done !";
end if;

@ -1,17 +1,18 @@
[*]
[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
[*] Sun May 31 12:53:52 2020
[*] Mon Jun 22 06:32:16 2020
[*]
[dumpfile] "/home/ANT.AMAZON.COM/benh/hackplace/microwatt/foo.ghw"
[dumpfile_mtime] "Sun May 31 12:50:15 2020"
[dumpfile_size] 1134118
[dumpfile_mtime] "Mon Jun 22 06:28:35 2020"
[dumpfile_size] 1680014
[savefile] "/home/ANT.AMAZON.COM/benh/hackplace/microwatt/litedram/extras/wave_tb.gtkw"
[timestart] 1312950000
[timestart] 1920580000
[size] 2509 1371
[pos] -1 -1
*-24.248457 1386890000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
*-24.248457 1935000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] top.
[treeopen] top.dram_tb.
[treeopen] top.dram_tb.dram.
[sst_width] 301
[signals_width] 433
[sst_expanded] 1
@ -26,7 +27,6 @@ top.dram_tb.clk
@22
#{top.dram_tb.wb_in.dat[63:0]} top.dram_tb.wb_in.dat[63] top.dram_tb.wb_in.dat[62] top.dram_tb.wb_in.dat[61] top.dram_tb.wb_in.dat[60] top.dram_tb.wb_in.dat[59] top.dram_tb.wb_in.dat[58] top.dram_tb.wb_in.dat[57] top.dram_tb.wb_in.dat[56] top.dram_tb.wb_in.dat[55] top.dram_tb.wb_in.dat[54] top.dram_tb.wb_in.dat[53] top.dram_tb.wb_in.dat[52] top.dram_tb.wb_in.dat[51] top.dram_tb.wb_in.dat[50] top.dram_tb.wb_in.dat[49] top.dram_tb.wb_in.dat[48] top.dram_tb.wb_in.dat[47] top.dram_tb.wb_in.dat[46] top.dram_tb.wb_in.dat[45] top.dram_tb.wb_in.dat[44] top.dram_tb.wb_in.dat[43] top.dram_tb.wb_in.dat[42] top.dram_tb.wb_in.dat[41] top.dram_tb.wb_in.dat[40] top.dram_tb.wb_in.dat[39] top.dram_tb.wb_in.dat[38] top.dram_tb.wb_in.dat[37] top.dram_tb.wb_in.dat[36] top.dram_tb.wb_in.dat[35] top.dram_tb.wb_in.dat[34] top.dram_tb.wb_in.dat[33] top.dram_tb.wb_in.dat[32] top.dram_tb.wb_in.dat[31] top.dram_tb.wb_in.dat[30] top.dram_tb.wb_in.dat[29] top.dram_tb.wb_in.dat[28] top.dram_tb.wb_in.dat[27] top.dram_tb.wb_in.dat[26] top.dram_tb.wb_in.dat[25] top.dram_tb.wb_in.dat[24] top.dram_tb.wb_in.dat[23] top.dram_tb.wb_in.dat[22] top.dram_tb.wb_in.dat[21] top.dram_tb.wb_in.dat[20] top.dram_tb.wb_in.dat[19] top.dram_tb.wb_in.dat[18] top.dram_tb.wb_in.dat[17] top.dram_tb.wb_in.dat[16] top.dram_tb.wb_in.dat[15] top.dram_tb.wb_in.dat[14] top.dram_tb.wb_in.dat[13] top.dram_tb.wb_in.dat[12] top.dram_tb.wb_in.dat[11] top.dram_tb.wb_in.dat[10] top.dram_tb.wb_in.dat[9] top.dram_tb.wb_in.dat[8] top.dram_tb.wb_in.dat[7] top.dram_tb.wb_in.dat[6] top.dram_tb.wb_in.dat[5] top.dram_tb.wb_in.dat[4] top.dram_tb.wb_in.dat[3] top.dram_tb.wb_in.dat[2] top.dram_tb.wb_in.dat[1] top.dram_tb.wb_in.dat[0]
#{top.dram_tb.wb_in.adr[31:0]} top.dram_tb.wb_in.adr[31] top.dram_tb.wb_in.adr[30] top.dram_tb.wb_in.adr[29] top.dram_tb.wb_in.adr[28] top.dram_tb.wb_in.adr[27] top.dram_tb.wb_in.adr[26] top.dram_tb.wb_in.adr[25] top.dram_tb.wb_in.adr[24] top.dram_tb.wb_in.adr[23] top.dram_tb.wb_in.adr[22] top.dram_tb.wb_in.adr[21] top.dram_tb.wb_in.adr[20] top.dram_tb.wb_in.adr[19] top.dram_tb.wb_in.adr[18] top.dram_tb.wb_in.adr[17] top.dram_tb.wb_in.adr[16] top.dram_tb.wb_in.adr[15] top.dram_tb.wb_in.adr[14] top.dram_tb.wb_in.adr[13] top.dram_tb.wb_in.adr[12] top.dram_tb.wb_in.adr[11] top.dram_tb.wb_in.adr[10] top.dram_tb.wb_in.adr[9] top.dram_tb.wb_in.adr[8] top.dram_tb.wb_in.adr[7] top.dram_tb.wb_in.adr[6] top.dram_tb.wb_in.adr[5] top.dram_tb.wb_in.adr[4] top.dram_tb.wb_in.adr[3] top.dram_tb.wb_in.adr[2] top.dram_tb.wb_in.adr[1] top.dram_tb.wb_in.adr[0]
@23
#{top.dram_tb.wb_in.sel[7:0]} top.dram_tb.wb_in.sel[7] top.dram_tb.wb_in.sel[6] top.dram_tb.wb_in.sel[5] top.dram_tb.wb_in.sel[4] top.dram_tb.wb_in.sel[3] top.dram_tb.wb_in.sel[2] top.dram_tb.wb_in.sel[1] top.dram_tb.wb_in.sel[0]
@28
top.dram_tb.wb_in.cyc
@ -67,6 +67,9 @@ top.dram_tb.dram.user_port0_cmd_valid
top.dram_tb.dram.refill_cmd_valid
@420
top.dram_tb.dram.req_index
@421
top.dram_tb.dram.req_row
@420
top.dram_tb.dram.req_hit_way
@28
top.dram_tb.dram.req_ad3

@ -21,7 +21,7 @@ end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

@ -38,16 +38,14 @@ def build_init_code(build_dir, is_sim):
sw_inc_dir = os.path.join(sw_dir, "include")
gen_inc_dir = os.path.join(sw_inc_dir, "generated")
src_dir = os.path.join(gen_src_dir, "sdram_init")
lxbios_src_dir = os.path.join(soc_directory, "software", "liblitedram")
lxbios_inc_dir = os.path.join(soc_directory, "software", "include")
lxbios_src_dir = os.path.join(soc_directory, "software")
print(" sw dir:", sw_dir)
print("gen_inc_dir:", gen_inc_dir)
print(" src dir:", src_dir)
print(" lx src dir:", lxbios_src_dir)
print(" lx inc dir:", lxbios_inc_dir)

# Generate mem.h
mem_h = "#define MAIN_RAM_BASE 0x40000000"
# Generate mem.h (hard wire size, it's not important)
mem_h = "#define MAIN_RAM_BASE 0x40000000\n#define MAIN_RAM_SIZE 0x10000000"
write_to_file(os.path.join(gen_inc_dir, "mem.h"), mem_h)

# Environment
@ -61,7 +59,6 @@ def build_init_code(build_dir, is_sim):
add_var("SRC_DIR", src_dir)
add_var("GENINC_DIR", sw_inc_dir)
add_var("LXSRC_DIR", lxbios_src_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))
@ -143,7 +140,7 @@ def generate_one(t):

def main():

targets = ['arty','nexys-video', 'sim']
targets = ['arty','nexys-video', 'genesys2', 'sim']
for t in targets:
generate_one(t)

@ -0,0 +1,41 @@
# 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":"standard",
"speedgrade": -2, # FPGA speedgrade
"memtype": "DDR3", # DRAM type

# PHY ----------------------------------------------------------------------
"cmd_latency": 0, # Command additional latency
"sdram_module": "MT41J256M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 4, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": K7DDRPHY, # Type of FPGA PHY

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

# Frequency ----------------------------------------------------------------
"input_clk_freq": 200e6, # 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",
},
},

# CSR Port -----------------------------------------------------------------
"csr_alignment" : 32,
"csr_data_width" : 32,
}

@ -3,8 +3,10 @@
include variables.mak
OBJ = $(BUILD_DIR)/obj

LXINC_DIR=$(LXSRC_DIR)/include

PROGRAM = sdram_init
OBJECTS = $(OBJ)/head.o $(OBJ)/main.o $(OBJ)/sdram.o $(OBJ)/console.o
OBJECTS = $(OBJ)/head.o $(OBJ)/main.o $(OBJ)/sdram.o $(OBJ)/memtest.o $(OBJ)/console.o

#### Compiler

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

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

# These includes must be first ...
CPPFLAGS += -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../../include -I$(SRC_DIR)/libc/include

# .. and these last, otherwise litex overrides some of our stuff
CPPFLAGS += -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(LXINC_DIR)/base -I$(LXSRC_DIR)/liblitedram

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)
@ -48,7 +56,9 @@ endif

all: objdir $(OBJ)/$(PROGRAM).hex

$(OBJ)/sdram.o: $(LXSRC_DIR)/sdram.c
$(OBJ)/sdram.o: $(LXSRC_DIR)/liblitedram/sdram.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)
$(OBJ)/memtest.o: $(LXSRC_DIR)/libbase/memtest.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)
$(OBJ)/console.o: $(SRC_DIR)/../../../lib/console.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)

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

#define STACK_TOP 0xff004000
#define STACK_TOP 0xff006000

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

@ -1,6 +1,8 @@
#ifndef __SYSTEM_H
#define __SYSTEM_H

#include <stdint.h>

#include "microwatt_soc.h"
#include "io.h"

@ -32,6 +34,9 @@ static inline uint64_t timer0_value_read(void)
return val;
}

static inline void init_progression_bar(int max) { }
static inline void show_progress(int now) { }

static inline void csr_write_simple(unsigned long v, unsigned long a)
{
return writel(v, a);

@ -7,10 +7,10 @@

#include <generated/git.h>

#include "console.h"
#include "microwatt_soc.h"
#include "io.h"
#include "sdram.h"
#include "console.h"
#include "elf64.h"

#define FLASH_LOADER_USE_MAP
@ -225,9 +225,9 @@ dump:

static void boot_sdram(void)
{
void *s = (void *)(DRAM_INIT_BASE + 0x4000);
void *s = (void *)(DRAM_INIT_BASE + 0x6000);
void *d = (void *)DRAM_BASE;
int sz = (0x10000 - 0x4000);
int sz = (0x10000 - 0x6000);
printf("Copying payload to DRAM...\n");
memcpy(d, s, sz);
printf("Booting from DRAM...\n");

@ -21,7 +21,7 @@ end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (b1b2b29) & LiteX (20ff2462) on 2020-06-13 00:02:02
// Auto-generated by Migen (4fea1bd) & LiteX (83d24d08) on 2020-07-08 17:33:20
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,

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

library work;
use work.wishbone_types.all;
use work.utils.all;

entity dram_init_mem is
generic (
EXTRA_PAYLOAD_FILE : string := "";
EXTRA_PAYLOAD_SIZE : integer := 0
);
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 := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (TOTAL_RAM_SIZE / 4) - 1) of std_logic_vector(31 downto 0);

-- XXX FIXME: Have a single init function called twice with
-- an offset as argument
procedure init_load_payload(ram: inout ram_t; filename: string) is
file payload_file : text open read_mode is filename;
variable ram_line : line;
variable temp_word : std_logic_vector(63 downto 0);
begin
for i in 0 to RND_PAYLOAD_SIZE-1 loop
exit when endfile(payload_file);
readline(payload_file, ram_line);
hread(ram_line, temp_word);
ram((INIT_RAM_SIZE/4) + i*2) := temp_word(31 downto 0);
ram((INIT_RAM_SIZE/4) + i*2+1) := temp_word(63 downto 32);
end loop;
assert endfile(payload_file) report "Payload too big !" severity failure;
end procedure;

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
report "Payload size:" & integer'image(EXTRA_PAYLOAD_SIZE) &
" rounded to:" & integer'image(RND_PAYLOAD_SIZE);
report "Total RAM size:" & integer'image(TOTAL_RAM_SIZE) &
" bytes using " & integer'image(INIT_RAM_ABITS) &
" address bits";
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;
if RND_PAYLOAD_SIZE /= 0 then
init_load_payload(temp_ram, EXTRA_PAYLOAD_FILE);
end if;
return temp_ram;
end function;

impure function init_zero return ram_t is
variable temp_ram : ram_t := (others => (others => '0'));
begin
return temp_ram;
end function;

impure function initialize_ram(filename: string) return ram_t is
begin
report "Opening file " & filename;
if filename'length = 0 then
return init_zero;
else
return init_load_ram(filename);
end if;
end function;
signal init_ram : ram_t := initialize_ram(INIT_RAM_FILE);

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

signal obuf : std_ulogic_vector(31 downto 0);
signal oack : std_ulogic;
begin

init_ram_0: process(clk)
variable adr : integer;
begin
if rising_edge(clk) then
oack <= '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
obuf <= 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;
oack <= '1';
end if;
wb_out.ack <= oack;
wb_out.dat <= obuf;
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

@ -21,7 +21,7 @@ end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (b1b2b29) & LiteX (20ff2462) on 2020-06-13 00:02:04
// Auto-generated by Migen (4fea1bd) & LiteX (83d24d08) on 2020-07-08 17:33:22
//--------------------------------------------------------------------------------
module litedram_core(
input wire clk,

@ -21,7 +21,7 @@ end entity dram_init_mem;

architecture rtl of dram_init_mem is

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_SIZE : integer := 24576;
constant RND_PAYLOAD_SIZE : integer := round_up(EXTRA_PAYLOAD_SIZE, 8);
constant TOTAL_RAM_SIZE : integer := INIT_RAM_SIZE + RND_PAYLOAD_SIZE;
constant INIT_RAM_ABITS : integer := log2ceil(TOTAL_RAM_SIZE-1);

@ -5,7 +5,7 @@ a64b5a7d14004a39
2402004ca64b7b7d
602100003c200000
6421ff00782107c6
3d80000060213f00
3d80000060215f00
798c07c6618c0000
618c10e0658cff00
4e8004217d8903a6
@ -518,7 +518,7 @@ a64b5a7d14004a39
4e80002060000000
0000000000000000
3c4c000100000000
7c0802a638429cc4
7c0802a638429ec4
fbe1fff8fbc1fff0
f821ff51f8010010
f88100d83be10020
@ -527,67 +527,67 @@ f88100d83be10020
f8e100f038c100d8
f90100f87fe3fb78
f9410108f9210100
6000000048001239
60000000480014a9
7fe3fb787c7e1b78
6000000048000c21
6000000048000e91
7fc3f378382100b0
00000000480017f8
0000000048001a68
0000028001000000
000000004e800020
0000000000000000
4c00012c7c0007ac
000000004e800020
0000000000000000
38429c203c4c0001
38429e203c4c0001
7d8000267c0802a6
9181000848001735
48000c1df821fed1
91810008480019a5
48000e8df821fed1
3c62ffff60000000
4bffff3938637bb8
4bffff3938637c28
548400023880ffff
7c8026ea7c0004ac
3fe0c0003c62ffff
63ff000838637bd8
63ff000838637c48
3c62ffff4bffff15
38637bf87bff0020
38637c687bff0020
7c0004ac4bffff05
73e900017fe0feea
3c62ffff41820010
4bfffee938637c10
4bfffee938637c80
4e00000073e90002
3c62ffff41820010
4bfffed138637c18
4bfffed138637c88
4d80000073e90004
3c62ffff41820010
4bfffeb938637c20
4bfffeb938637c90
4d00000073e90008
3c62ffff41820010
4bfffea138637c28
4bfffea138637c98
4182001073e90010
38637c383c62ffff
38637ca83c62ffff
3f62ffff4bfffe8d
7f63db783b7b7f70
7f63db783b7b7f28
418e00284bfffe7d
608400103c80c000
7c0004ac78840020
3c62ffff7c8026ea
38637c487884b582
38637cb87884b582
4192004c4bfffe55
608400183c80c000
7c0004ac78840020
3c62ffff7c8026ea
38637c6078846022
38637cd078846022
3c80c0004bfffe2d
7884002060840030
7c8026ea7c0004ac
7884b2823c62ffff
4bfffe0938637c78
4bfffe0938637ce8
612900203d20c000
7c0004ac79290020
3c80000f7d204eea
6084424079290600
7c8923923c62ffff
4bfffdd938637c90
4bfffdd938637d00
3fa0c000418a0258
7bbd002063bd0038
7fa0eeea7c0004ac
@ -604,7 +604,7 @@ f9410108f9210100
57ff063e4bfffd29
7fe6fb783c62ffff
7f84e3787fc5f378
4bfffd5138637cb0
4bfffd5138637d20
7d29fb787f89f378
419e01642f890000
7d29f8387f89f038
@ -624,9 +624,9 @@ f9410108f9210100
7f80feaa7c0004ac
579c063e4bfffc81
7f84e3783c62ffff
4bfffcb138637cd0
4bfffcb138637d40
4082009073890002
38637cf03c62ffff
38637d603c62ffff
7c0004ac4bfffc9d
392000067f40f7aa
7d20ffaa7c0004ac
@ -644,7 +644,7 @@ f9410108f9210100
579c063e7f80feaa
738900014bfffbe1
3c62ffff4082ffdc
4bfffc1138637d08
4bfffc1138637d78
614a60083d40c000
7c0004ac794a0020
5529021e7d20562a
@ -652,62 +652,62 @@ f9410108f9210100
7d20572a7c0004ac
4bfffbe17f63db78
3c62ffff7bbd0020
38637d187fa4eb78
38637d887fa4eb78
3be000014bfffbcd
4bfffbc17f63db78
3ca2ffff41920028
3c62ffff3c82ffff
38847d4838a57d38
4bfffba138637d50
6000000048000605
38847db838a57da8
4bfffba138637dc0
6000000048000311
3c62ffff418e0024
4bfffb8938637d80
4bfffb8938637df0
4800014438600000
3ba000003be00000
2fbf00004bffffb0
3c62ffff419e0084
4bfffb6138637d98
4bfffb6138637e08
38a000403c9df000
3861007078840020
6000000048000aa9
6000000048000d19
3d400002e9210070
794a83e4614a464c
614a457f79290600
419e00807fa95000
38637db03c62ffff
38637e203c62ffff
886100774bfffb1d
8921007589410076
88e1007389010074
88a1007188c10072
f861006088810070
38637e303c62ffff
38637ea03c62ffff
3c62ffff4bfffaed
4bfffae138637e60
38a0ffff3c80ff00
54a5042260844000
4bfffae138637ed0
38a000003c80ff00
60a5a00060846000
3c60400078840020
6000000048000a21
38637e803c62ffff
6000000048000c91
38637ef03c62ffff
4bfffb354bfffab5
892100754bffff28
409e00102f890001
2f890015a1210082
3c62ffff419e0010
4bffff6c38637dd0
4bffff6c38637e40
3f02ffffebe10090
3b2100b03bc00000
7fffea143b187de8
7fffea143b187e58
a12100a87bff0020
419d00347f89f040
3c62ffff80810088
4bfffa5138637e10
4bfffa5138637e80
e86100884bfffad1
419eff582fa3ffff
8181000838210130
480012607d838120
480014d07d838120
38a000383c9ff000
7f23cb7878840020
6000000048000979
6000000048000be9
2f890001812100b0
eb4100d0409e004c
eb8100b8eb6100c0
@ -716,14 +716,14 @@ eb8100b8eb6100c0
4bfff9e93f9cf000
7b4500207c9de214
7f63db7878840020
6000000048000931
6000000048000ba1
7fe9fa14a12100a6
3bde00017bff0020
4bffff507bde0020
409efdcc2b9c0020
409efdc42b9e00ba
409efdbc2b9f0018
38637d003c62ffff
38637d703c62ffff
4bfffd784bfff995
0300000000000000
3d20c80000000880
@ -734,134 +734,40 @@ eb8100b8eb6100c0
7d20572a7c0004ac
000000004e800020
0000000000000000
384296003c4c0001
384298003c4c0001
3d40c8007c0802a6
3920000e614a0800
f8010010794a0020
7c0004acf821ffa1
3c62ffff7d20572a
4bfff91138637f90
4bfff91138637f50
3821006060000000
7c0803a6e8010010
000000004e800020
0000008001000000
384295a83c4c0001
384297a83c4c0001
3d40c8007c0802a6
39200001614a0800
f8010010794a0020
7c0004acf821ffa1
3c62ffff7d20572a
4bfff8b938637f50
4bfff8b938637f08
3821006060000000
7c0803a6e8010010
000000004e800020
0000008001000000
384295503c4c0001
390000807c0802a6
3d40aaaa7d0903a6
614aaaaa3d204000
f821ff8148001069
3929000491490000
4bfff8d54200fff8
3940008060000000
7d4903a63d00aaaa
3be000003d204000
814900006108aaaa
419e000c7f8a4000
7fff07b43bff0001
4200ffe839290004
3d40555539000080
3d2040007d0903a6
91490000614a5555
4200fff839290004
600000004bfff879
3d00555539400080
3d2040007d4903a6
8149000061085555
419e000c7f8a4000
7fff07b43bff0001
4200ffe839290004
419e001c2fbf0000
38a001003c62ffff
38637e987fe4fb78
600000004bfff7b5
3ce0802039000100
60e700037d0903a6
392000013d404000
7928f84278e70020
7d2900d0792907e0
7d293838394a0004
912afffc7d294278
4bfff7e54200ffe4
3900010060000000
7d0903a63ce08020
3d40400060e70003
392000013ba00000
7928f84278e70020
7d2900d0792907e0
7d2942787d293838
7f884840810a0000
3bbd0001419e000c
394a00047fbd07b4
2fbd00004200ffd4
3c62ffff419e001c
7fa4eb7838a00100
4bfff70138637ec0
3920002060000000
7d2903a639400000
794800203d2a1000
394a000139290002
9109000079291764
4bfff7454200ffe8
3920002060000000
7d2903a639400000
3d2a10003bc00000
8129000879291764
7f8950005529043e
3bde0001419e000c
394a00017fde07b4
2fbe00004200ffdc
3c62ffff419e001c
7fc4f37838a00020
4bfff67938637ee8
7fffea1460000000
7ffff21438600000
409e00ac2f9f0000
38637f103c62ffff
600000004bfff655
394000807c9602a6
7d4903a678840020
3d49080039200000
f92a0000794a1f24
4200fff039290001
7c9f20507ff602a6
63ff80003fe0000c
4bfff6857fff2396
7bff002060000000
390000807d3602a6
7d0903a679290020
e90a00003d404000
4200fff8394a0008
7d2548507cb602a6
60a580003ca0000c
7ca54b963c62ffff
38637f207fe4fb78
4bfff5c178a50320
3860000160000000
48000df438210080
0100000000000000
3c4c000100000380
7c0802a63842925c
38637f783c62ffff
f821ff7148000d75
384297503c4c0001
3c62ffff7c0802a6
38637f303c804000
f821ff71480012d5
3be000003f60c800
7b7b0020637b1000
600000004bfff575
600000004bfff865
7fe0df2a7c0004ac
635a10043f40c800
7c0004ac7b5a0020
3fa0c8007fe0d72a
63bd080c4bfffc11
63bd080c4bffff01
7c0004ac7bbd0020
3fc0c8007fe0ef2a
7bde002063de0810
@ -876,33 +782,205 @@ f821ff7148000d75
7d20ef2a7c0004ac
7c0004ac39200002
3860000f7d20f72a
7c0004ac4bfffb55
7c0004ac4bfffe45
392000037fe0ef2a
7d20f72a7c0004ac
4bfffb393860000f
4bfffe293860000f
7c0004ac39200006
3b8000017d20ef2a
7f80f72a7c0004ac
4bfffb193860000f
4bfffe093860000f
7c0004ac39200920
7c0004ac7d20ef2a
3860000f7fe0f72a
392004004bfffafd
392004004bfffded
7d20ef2a7c0004ac
7fe0f72a7c0004ac
4bfffae138600003
4bfffbcd4bfffb79
4082001c2c230000
7f80df2a7c0004ac
7f80d72a7c0004ac
48000c7038210090
7f80df2a7c0004ac
4bffffec38600001
4bfffdd138600003
3c8010004bfffe69
480004653c604000
2c23000060000000
7c0004ac4082001c
7c0004ac7f80df2a
382100907f80d72a
7c0004ac480011c4
386000017f80df2a
000000004bffffec
0000068001000000
384295b83c4c0001
7884f0827c0802a6
3d20aaaa39440001
6129aaaa7d4903a6
f821ffc148001141
3be000007c7d1b78
4bfff73d4200006c
395f000160000000
7d4903a63d00aaaa
3bc0000039200000
420000586108aaaa
3d405555391f0001
392000007d0903a6
42000060614a5555
600000004bfff701
3d005555395f0001
392000007d4903a6
4200005061085555
7fc3f37838210040
7bea176448001118
7d3d512e3bff0001
792a17644bffff88
7f8a40007d5d502e
3bde0001419e000c
392900017fde07b4
792817644bffff8c
7d5d412e39290001
792a17644bffff94
7f8a40007d5d502e
3bde0001419e000c
392900017fde07b4
000000004bffff94
0000038001000000
384294b03c4c0001
7884f0827c0802a6
2fa5000039440001
392000017d4903a6
f821ffc148001039
3be000007c7d1b78
420000347cbe2b78
600000004bfff631
2ebe0000395f0001
38e000007d4903a6
3860000039200001
420000447ce607b4
4800104438210040
792af842419e002c
7d2900d0792907e0
7d2952787129d008
792a17647be80020
7d1d512e3bff0001
392900014bffffa4
4bffffe45529043e
7928f8424196003c
7d2900d0792907e0
7d2942787129d008
7d1d402e79281764
7f8830005508043e
39430001419e000c
38e700017d4307b4
392900014bffff80
4bffffd45529043e
0100000000000000
3c4c000100000380
7c0802a6384293bc
390400017884f082
7d0903a63d408020
39200001614a0003
48000f35794a0020
7cbd2b79f821ff71
3be000007c7b1b78
3f82ffff42000060
3b9c7f283bc00000
4bfff4b17f83e378
4bfff51d60000000
391f000160000000
7d0903a63ce08020
2fbd000060e70003
3920000139400000
4200005078e70020
4bfff4797f83e378
3821009060000000
48000f147fc3f378
7928f84241820028
7d2900d0792907e0
7d2942787d295038
3bff00017be81764
4bffff7c7d3b412e
7929002039290001
419e00384bffffe8
792907e07928f842
7d2938387d2900d0
794817647d294278
7e8848407d1b402e
3bde00014196000c
394a00017fde07b4
392900014bffff7c
4bffffd879290020
0100000000000000
3c4c000100000680
60000000384290d4
6000000039228010
8929000039428008
3c4c000100000580
7c0802a63842929c
f821ff8148000e35
7c7d1b787c9e2378
3c62ffff7c641b78
38637f787cbc2b78
4bfff3b17bdfe8c2
2fbc000060000000
409e003438800000
38ff00017d3602a6
7ce903a6792a0020
3900ffff39200000
7d3602a642000074
7d2950501c9e0320
7c844b9279290020
38637f903c62ffff
600000004bfff365
600000004bfff3d1
391f00017d3602a6
792a00207d0903a6
4200004039200000
1c9e03207d3602a6
792900207d295050
7c844b923c62ffff
4bfff32138637fa8
3821008060000000
79271f2448000dc4
7d1d392a39290001
79281f244bffff80
7d1d402a39290001
000000004bffffb4
0000048001000000
384291a03c4c0001
2ba402007c0802a6
f821ff6148000d29
3b8002007c7e1b78
7c9c2378419d0008
7c9d23782ba40080
3ba00080409d0008
7c9f23782ba40400
3be00400409d0008
7fc4f3783c62ffff
4bfff29138637fc0
7f84e37860000000
4bfffb8d7fc3f378
7fa4eb7838a00000
7fc3f3787c791b78
38a000014bfffc81
7c7a1b787fe4fb78
4bfffd617fc3f378
7d291a147d39d214
2f8900007c7b1b78
3c62ffff419e0068
7f24cb787b85f882
4bfff23138637fd8
3c62ffff60000000
7f44d3787ba5f082
4bfff21938637ff0
6000000060000000
7f64db787be5f082
4bfff20138628008
6000000060000000
4bfff1f138628020
3860000060000000
48000c84382100a0
3862803060000000
600000004bfff1d5
38a000007fc3f378
4bfffde97fe4fb78
4bffffd438600001
0100000000000000
3c4c000100000780
6000000038429064
6000000039228098
8929000039428090
419e002c2f890000
39290014e92a0000
7d204eaa7c0004ac
@ -916,7 +994,7 @@ e94a00005469063e
7d2057ea7c0004ac
000000004e800020
0000000000000000
384290503c4c0001
38428fe03c4c0001
fbc1fff07c0802a6
3bc3fffffbe1fff8
f821ffd1f8010010
@ -928,7 +1006,7 @@ f821ffd1f8010010
4bffff397fe3fb78
000000004bffffd0
0000028001000000
38428ff03c4c0001
38428f803c4c0001
612900203d20c000
7c0004ac79290020
3d00c0007d204eea
@ -940,8 +1018,8 @@ f821ffd1f8010010
7c0004ac794a0020
3d00c0007d4056ea
6000000060000000
6108200038e28010
f902800879080020
6108200038e28098
f902809079080020
610820003d00001c
7948f8047d294392
4182008079080fc3
@ -949,15 +1027,15 @@ f902800879080020
994700006108200c
3940ff8079080020
7d4047aa7c0004ac
7c0004ace9428008
e94280087d2057aa
7c0004ace9428090
e94280907d2057aa
394a00047929c202
7d2057aa7c0004ac
39400003e9228008
39400003e9228090
7c0004ac3929000c
e92280087d404faa
e92280907d404faa
7c0004ac39290010
e92280087d404faa
e92280907d404faa
3929000839400007
7d404faa7c0004ac
3d40c0004e800020
@ -1028,7 +1106,7 @@ f924000039290002
7c6307b43863ffe0
000000004e800020
0000000000000000
38428cd03c4c0001
38428c603c4c0001
3d2037367c0802a6
612935347d908026
65293332792907c6
@ -1062,7 +1140,7 @@ fbfd00007fe9fa14
4bfffff07d29f392
0300000000000000
3c4c000100000580
7c0802a638428bc4
7c0802a638428b54
f821ffb1480006e9
7c7f1b78eb630000
7cbd2b787c9c2378
@ -1078,7 +1156,7 @@ f821ffb1480006e9
4bffffb8f93f0000
0100000000000000
3c4c000100000580
7c0802a638428b44
7c0802a638428ad4
f821ffa148000661
7c9b23787c7d1b78
388000007ca32b78
@ -1109,16 +1187,16 @@ e95d00009b270000
f95d0000394a0001
000000004bffffa8
0000078001000000
38428a483c4c0001
384289d83c4c0001
480005397c0802a6
7c741b79f821fed1
38600000f8610060
2fa4000041820068
39210040419e0060
3ac4ffff3e42ffff
3ac4ffff60000000
f92100703b410020
3ae0000060000000
3a527fb839228000
3a42804039228088
f92100783ba10060
ebc1006089250000
419e00102fa90000
@ -1349,9 +1427,9 @@ e8010010ebc1fff0
203a46464f204853
7479622078257830
00000000000a7365
6633623461653832
3830643432643338
0000000000000000
0039326232623162
0064623161656634
4d4152446574694c
6620746c69756220
6567694d206d6f72
@ -1393,42 +1471,45 @@ e8010010ebc1fff0
20676e69746f6f42
415244206d6f7266
0000000a2e2e2e4d
20747365746d654d
6c69616620737562
252f6425203a6465
73726f7272652064
000000000000000a
20747365746d654d
6961662061746164
2f6425203a64656c
726f727265206425
0000000000000a73
20747365746d654d
6961662072646461
2f6425203a64656c
726f727265206425
0000000000000a73
20747365746d654d
00000000000a4b4f
64656570736d654d
3a73657469725720
7370624d646c2520
203a736461655220
0a7370624d646c25
0000000000000000
6f6e204d41524453
207265646e752077
6572617764726168
6c6f72746e6f6320
000000000000000a
696c616974696e49
52445320676e697a
00000a2e2e2e4d41
41524420676e697a
383025783040204d
0000000a2e2e2e78
6f6e204d41524453
207265646e752077
6572617774666f73
6c6f72746e6f6320
000000000000000a
64656570736d654d
7025783020746120
000000000a2e2e2e
203a736574697257
7370624d20646c25
000000000000000a
20203a7364616552
7370624d20646c25
000000000000000a
20747365746d654d
2e70257830207461
00000000000a2e2e
726520737562202d
2520203a73726f72
00000a646c252f64
652072646461202d
25203a73726f7272
00000a646c252f64
652061746164202d
25203a73726f7272
00000a646c252f64
20747365746d654d
00000000000a4f4b
20747365746d654d
00000000000a4b4f
0000000000000000
00000000000000ff
000000000000ffff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save