diff --git a/vunit/vhdl/verification_components/src/axi_read_slave.vhd b/vunit/vhdl/verification_components/src/axi_read_slave.vhd index 975a0a0d9..8c7671823 100644 --- a/vunit/vhdl/verification_components/src/axi_read_slave.vhd +++ b/vunit/vhdl/verification_components/src/axi_read_slave.vhd @@ -11,6 +11,7 @@ use ieee.numeric_std.all; use work.axi_pkg.all; use work.axi_slave_private_pkg.all; use work.queue_pkg.all; +use work.logger_pkg.all; context work.com_context; context work.vc_context; @@ -58,6 +59,7 @@ begin variable response_time : time; variable has_response_time : boolean := false; + variable logger : logger_t := get_logger("axi_process"); begin assert arid'length = rid'length report "arid vs rid data width mismatch"; -- Initialization @@ -92,15 +94,23 @@ begin beats := burst.length; rid <= std_logic_vector(to_unsigned(burst.id, rid'length)); rresp <= axi_resp_okay; - address := burst.address; + address := burst.address - (burst.address mod burst.size); --aligned address end if; end if; if beats > 0 and (rvalid = '0' or rready = '1') and not self.should_stall_data then rvalid <= '1'; + rdata <= (rdata'range => '-'); for j in 0 to burst.size-1 loop idx := (address + j) mod self.data_size; - rdata(8*idx+7 downto 8*idx) <= std_logic_vector(to_unsigned(read_byte(axi_slave.p_memory, address+j), 8)); + + --Don't try to read lower than the burst's base addr; only kicks in when unaligned + if address+j >= burst.address then + debug(logger, "RD addr " & integer'image(address+j) & ", put in byte lane " & integer'image(idx)); + rdata(8*idx+7 downto 8*idx) <= std_logic_vector(to_unsigned(read_byte(axi_slave.p_memory, address+j), 8)); + else + debug(logger, "SKIP RD addr " & integer'image(address+j)); + end if; end loop; if burst.burst_type = axi_burst_type_incr then diff --git a/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd b/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd index 113c6fc37..883c4708e 100644 --- a/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd +++ b/vunit/vhdl/verification_components/src/axi_slave_private_pkg.vhd @@ -432,7 +432,7 @@ package body axi_slave_private_pkg is variable first_page, last_page : integer; begin first_address := burst.address - (burst.address mod data_size); -- Aligned - last_address := burst.address + burst.size*burst.length - 1; + last_address := first_address + burst.size*burst.length - 1; first_page := first_address / 4096; last_page := last_address / 4096; diff --git a/vunit/vhdl/verification_components/test/tb_axi_read_slave.vhd b/vunit/vhdl/verification_components/test/tb_axi_read_slave.vhd index 0073d9f66..87e79b30c 100644 --- a/vunit/vhdl/verification_components/test/tb_axi_read_slave.vhd +++ b/vunit/vhdl/verification_components/test/tb_axi_read_slave.vhd @@ -71,13 +71,19 @@ begin procedure read_data(id : std_logic_vector; address : natural; size : natural; resp : axi_resp_t; last : boolean) is variable idx : integer; + variable addr : integer; + variable logger : logger_t := get_logger("read_data"); begin rready <= '1'; wait until (rvalid and rready) = '1' and rising_edge(clk); rready <= '0'; + addr := address - (address mod size); --align address to transfer size for i in 0 to size-1 loop - idx := (address + i) mod data_size; -- Align data bus - check_equal(rdata(8*idx+7 downto 8*idx), read_byte(memory, address+i)); + idx := ((addr mod data_size) + i); --idx is the byte lane for this value + if addr >= address then + debug(logger, "RD addr " & integer'image(addr+i) & ", got " & integer'image(read_byte(memory, addr+i)) & ", compare to rdata byte lane " & integer'image(idx)); + check_equal(rdata(8*idx+7 downto 8*idx), read_byte(memory, addr+i), result("for rdata in byte lane " & integer'image(idx))); + end if; end loop; check_equal(rid, id, "rid"); check_equal(rresp, resp, "rresp"); @@ -86,7 +92,8 @@ begin procedure transfer(log_size, len : natural; id : std_logic_vector; - burst : std_logic_vector) is + burst : std_logic_vector; + alignment : positive := 4096) is variable buf : buffer_t; variable size : natural; variable data : integer_vector_ptr_t; @@ -94,7 +101,7 @@ begin size := 2**log_size; random_integer_vector_ptr(rnd, data, size * len, 0, 255); - buf := allocate(memory, 8 * len, alignment => 4096); + buf := allocate(memory, length(data), alignment => alignment); for i in 0 to length(data)-1 loop write_byte(memory, base_address(buf)+i, get(data, i)); end loop; @@ -109,7 +116,7 @@ begin variable log_size : natural; variable buf : buffer_t; variable id : std_logic_vector(arid'range); - variable len : natural; + variable len : positive; variable burst : axi_burst_type_t; variable start_time, diff_time : time; begin @@ -131,8 +138,38 @@ begin assert false; end case; - log_size := rnd.RandInt(0, 3); - transfer(log_size, len, id, burst); + log_size := rnd.RandInt(0, log_data_size); + transfer(log_size, len, id, burst, alignment => 4096); + end loop; + + elsif run("Test unaligned read") then + for test_idx in 0 to 32-1 loop + + id := rnd.RandSlv(arid'length); + case rnd.RandInt(1) is + when 0 => + burst := axi_burst_type_fixed; + len := 1; + when 1 => + burst := axi_burst_type_incr; + len := rnd.RandInt(1, 2**arlen'length); + when others => + assert false; + end case; + + log_size := rnd.RandInt(0, log_data_size); + + --If the burst will cross a 4KB boundary, lower the length + --If the min length is reached and still crossing, lower the size + while (2**log_size * len) > (4096 - (num_bytes(memory) mod 4096)) loop + debug("total size = " & integer'image(2**log_size * len) & ", num_bytes = " & integer'image(num_bytes(memory))); + if len = 1 then + log_size := log_size - 1; + else + len := len - 1; + end if; + end loop; + transfer(log_size, len, id, burst, alignment => rnd.RandInt(1, log_data_size)); end loop; elsif run("Test random data stall") then