end;
-- Returns whether this is the last row of a line
- function is_last_row(addr: std_ulogic_vector(63 downto 0)) return boolean is
+ function is_last_row(addr: wishbone_addr_type) 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;
end;
-- Return the address of the next row in the current cache line
- function next_row_addr(addr: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
+ function next_row_addr(addr: wishbone_addr_type) return std_ulogic_vector is
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
- variable result : std_ulogic_vector(63 downto 0);
+ variable result : wishbone_addr_type;
begin
-- Is there no simpler way in VHDL to generate that 3 bits adder ?
row_idx := addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS);
wr_data => wr_data
);
process(all)
+ variable tmp_adr : std_ulogic_vector(63 downto 0);
begin
-- Cache hit reads
do_read <= '1';
-- Otherwise, we might be doing a reload
wr_data <= wishbone_in.dat;
wr_sel <= (others => '1');
- wr_addr <= std_ulogic_vector(to_unsigned(get_row(r1.wb.adr), ROW_BITS));
+ tmp_adr := (r1.wb.adr'left downto 0 => r1.wb.adr, others => '0');
+ wr_addr <= std_ulogic_vector(to_unsigned(get_row(tmp_adr), ROW_BITS));
end if;
-- The two actual write cases here
-- Prep for first wishbone read. We calculate the address of
-- the start of the cache line
--
- r1.wb.adr <= d_in.addr(63 downto LINE_OFF_BITS) &
+ r1.wb.adr <= d_in.addr(r1.wb.adr'left downto LINE_OFF_BITS) &
(LINE_OFF_BITS-1 downto 0 => '0');
r1.wb.sel <= (others => '1');
r1.wb.we <= '0';
when OP_LOAD_NC =>
r1.wb.sel <= bus_sel;
- r1.wb.adr <= d_in.addr(63 downto 3) & "000";
+ r1.wb.adr <= d_in.addr(r1.wb.adr'left downto 3) & "000";
r1.wb.cyc <= '1';
r1.wb.stb <= '1';
r1.wb.we <= '0';
r1.update_valid <= '1';
end if;
r1.wb.sel <= bus_sel;
- r1.wb.adr <= d_in.addr(63 downto 3) & "000";
+ r1.wb.adr <= d_in.addr(r1.wb.adr'left downto 3) & "000";
r1.wb.dat <= store_data;
r1.wb.cyc <= '1';
r1.wb.stb <= '1';
end;
-- Returns whether this is the last row of a line
- function is_last_row(addr: std_ulogic_vector(63 downto 0)) return boolean is
+ function is_last_row(addr: wishbone_addr_type) 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;
end;
-- Return the address of the next row in the current cache line
- function next_row_addr(addr: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
+ function next_row_addr(addr: wishbone_addr_type)
+ return std_ulogic_vector is
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
- variable result : std_ulogic_vector(63 downto 0);
+ variable result : wishbone_addr_type;
begin
-- Is there no simpler way in VHDL to generate that 3 bits adder ?
row_idx := addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS);
wr_data => wishbone_in.dat
);
process(all)
+ variable tmp_adr : std_ulogic_vector(63 downto 0);
begin
do_read <= '1';
do_write <= '0';
end if;
cache_out(i) <= dout;
rd_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS));
- wr_addr <= std_ulogic_vector(to_unsigned(get_row(r.wb.adr), ROW_BITS));
+ tmp_adr := (r.wb.adr'left downto 0 => r.wb.adr, others => '0');
+ wr_addr <= std_ulogic_vector(to_unsigned(get_row(tmp_adr), ROW_BITS));
end process;
end generate;
-- Prep for first wishbone read. We calculate the address of
-- the start of the cache line
--
- r.wb.adr <= i_in.nia(63 downto LINE_OFF_BITS) &
+ r.wb.adr <= i_in.nia(r.wb.adr'left downto LINE_OFF_BITS) &
(LINE_OFF_BITS-1 downto 0 => '0');
r.wb.cyc <= '1';
r.wb.stb <= '1';
begin
wishbone_process: process(clk)
variable ret_dat: std_ulogic_vector(63 downto 0) := (others => '0');
+ variable adr: std_ulogic_vector(63 downto 0);
begin
wishbone_out.ack <= ret_ack and wishbone_in.cyc and wishbone_in.stb;
wishbone_out.dat <= ret_dat;
when IDLE =>
if wishbone_in.stb = '1' then
-- write
+ adr := (wishbone_in.adr'left downto 0 => wishbone_in.adr, others => '0');
if wishbone_in.we = '1' then
assert not(is_x(wishbone_in.dat)) and not(is_x(wishbone_in.adr)) severity failure;
report "RAM writing " & to_hstring(wishbone_in.dat) & " to " & to_hstring(wishbone_in.adr);
- behavioural_write(wishbone_in.dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier);
+ behavioural_write(wishbone_in.dat, adr, to_integer(unsigned(wishbone_in.sel)), identifier);
reload <= reload + 1;
ret_ack <= '1';
state <= ACK;
else
- behavioural_read(ret_dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload);
+ behavioural_read(ret_dat, adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload);
report "RAM reading from " & to_hstring(wishbone_in.adr) & " returns " & to_hstring(ret_dat);
ret_ack <= '1';
state <= ACK;
signal w_in : wishbone_slave_out;
signal w_out : wishbone_master_out;
+
+ impure function to_adr(a: integer) return std_ulogic_vector is
+ begin
+ return std_ulogic_vector(to_unsigned(a, w_out.adr'length));
+ end;
begin
simple_ram_0: entity work.mw_soc_memory
generic map (
-- test various read lengths and alignments
w_out.stb <= '1';
w_out.sel <= "00000001";
- w_out.adr <= x"0000000000000000";
+ w_out.adr <= to_adr(0);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00000001";
- w_out.adr <= x"0000000000000001";
+ w_out.adr <= to_adr(1);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00000001";
- w_out.adr <= x"0000000000000007";
+ w_out.adr <= to_adr(7);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00000011";
- w_out.adr <= x"0000000000000000";
+ w_out.adr <= to_adr(0);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00000011";
- w_out.adr <= x"0000000000000001";
+ w_out.adr <= to_adr(1);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00000011";
- w_out.adr <= x"0000000000000007";
+ w_out.adr <= to_adr(7);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00001111";
- w_out.adr <= x"0000000000000000";
+ w_out.adr <= to_adr(0);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00001111";
- w_out.adr <= x"0000000000000001";
+ w_out.adr <= to_adr(1);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "00001111";
- w_out.adr <= x"0000000000000007";
+ w_out.adr <= to_adr(7);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "11111111";
- w_out.adr <= x"0000000000000000";
+ w_out.adr <= to_adr(0);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "11111111";
- w_out.adr <= x"0000000000000001";
+ w_out.adr <= to_adr(1);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
w_out.stb <= '1';
w_out.sel <= "11111111";
- w_out.adr <= x"0000000000000007";
+ w_out.adr <= to_adr(7);
assert w_in.ack = '0';
wait for clk_period;
assert w_in.ack = '1';
-- test various write lengths and alignments
w_out.stb <= '1';
w_out.sel <= "00000001";
- w_out.adr <= x"0000000000000000";
+ w_out.adr <= to_adr(0);
w_out.we <= '1';
w_out.dat(7 downto 0) <= x"0F";
assert w_in.ack = '0';
w_out.stb <= '1';
w_out.sel <= "00000001";
- w_out.adr <= x"0000000000000000";
+ w_out.adr <= to_adr(0);
w_out.we <= '0';
assert w_in.ack = '0';
wait for clk_period;
w_out.stb <= '1';
w_out.sel <= "11111111";
- w_out.adr <= x"0000000000000007";
+ w_out.adr <= to_adr(7);
w_out.we <= '1';
w_out.dat <= x"BADC0FFEBADC0FFE";
assert w_in.ack = '0';
w_out.stb <= '1';
w_out.sel <= "11111111";
- w_out.adr <= x"0000000000000007";
+ w_out.adr <= to_adr(7);
w_out.we <= '0';
assert w_in.ack = '0';
wait for clk_period;
dmi_ack <= dmi_req when (dmi_addr /= DBG_WB_DATA or state = DMI_WAIT) else '0';
-- Some WB signals are direct wires from registers or DMI
- wb_out.adr <= reg_addr;
+ wb_out.adr <= reg_addr(wb_out.adr'left downto 0);
wb_out.dat <= dmi_din;
wb_out.sel <= reg_ctrl(7 downto 0);
wb_out.we <= dmi_wr;