end;
-- Returns whether this is the last row of a line
- function is_last_row_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is
+ function is_last_row_wb_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is
begin
return unsigned(addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last;
end;
end;
-- Return the address of the next row in the current cache line
- function next_row_addr(addr: wishbone_addr_type) return std_ulogic_vector is
+ function next_row_wb_addr(addr: wishbone_addr_type) return std_ulogic_vector is
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
variable result : wishbone_addr_type;
begin
variable addr : real_addr_t;
begin
if rising_edge(clk) then
- addr := (others => '0');
- addr(snoop_in.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS) := snoop_in.adr;
+ addr := addr_to_real(wb_to_addr(snoop_in.adr));
snoop_tag_set <= cache_tags(get_index(addr));
snoop_wrtag <= get_tag(addr);
snoop_index <= get_index(addr);
-- Main state machine
case r1.state is
when IDLE =>
- r1.wb.adr <= req.real_addr(r1.wb.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS);
+ r1.wb.adr <= addr_to_wb(req.real_addr);
r1.wb.sel <= req.byte_sel;
r1.wb.dat <= req.data;
r1.dcbz <= req.dcbz;
-- If we are still sending requests, was one accepted ?
if wishbone_in.stall = '0' and r1.wb.stb = '1' then
-- That was the last word ? We are done sending. Clear stb.
- if is_last_row_addr(r1.wb.adr, r1.end_row_ix) then
+ if is_last_row_wb_addr(r1.wb.adr, r1.end_row_ix) then
r1.wb.stb <= '0';
end if;
-- Calculate the next row address
- r1.wb.adr <= next_row_addr(r1.wb.adr);
+ r1.wb.adr <= next_row_wb_addr(r1.wb.adr);
end if;
-- Incoming acks processing
end;
-- Return the cache row index (data memory) for an address
- function get_row(addr: std_ulogic_vector) return row_t is
+ function get_row(addr: std_ulogic_vector(63 downto 0)) return row_t is
begin
return to_integer(unsigned(addr(SET_SIZE_BITS - 1 downto ROW_OFF_BITS)));
end;
end;
-- Returns whether this is the last row of a line
- function is_last_row_addr(addr: wishbone_addr_type; last: row_in_line_t) return boolean is
+ function is_last_row_wb_addr(wb_addr: wishbone_addr_type; last: row_in_line_t) return boolean is
begin
- return unsigned(addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last;
+ return unsigned(wb_addr(LINE_OFF_BITS - ROW_OFF_BITS - 1 downto 0)) = last;
end;
-- Returns whether this is the last row of a line
end;
-- Return the address of the next row in the current cache line
- function next_row_addr(addr: wishbone_addr_type)
+ function next_row_wb_addr(wb_addr: wishbone_addr_type)
return std_ulogic_vector is
variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0);
variable result : wishbone_addr_type;
begin
-- Is there no simpler way in VHDL to generate that 3 bits adder ?
- row_idx := addr(ROW_LINEBITS - 1 downto 0);
+ row_idx := wb_addr(ROW_LINEBITS - 1 downto 0);
row_idx := std_ulogic_vector(unsigned(row_idx) + 1);
- result := addr;
+ result := wb_addr;
result(ROW_LINEBITS - 1 downto 0) := row_idx;
return result;
end;
end;
-- Get the tag value from the address
- function get_tag(addr: std_ulogic_vector(REAL_ADDR_BITS - 1 downto 0);
- endian: std_ulogic) return cache_tag_t is
+ function get_tag(addr: real_addr_t; endian: std_ulogic) return cache_tag_t is
begin
- return endian & addr(REAL_ADDR_BITS - 1 downto SET_SIZE_BITS);
+ return endian & addr(addr'left downto SET_SIZE_BITS);
end;
-- Read a tag from a tag memory row
-- used for cache miss processing if needed
--
req_laddr <= (63 downto REAL_ADDR_BITS => '0') &
- real_addr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS)&
+ real_addr(REAL_ADDR_BITS - 1 downto ROW_OFF_BITS) &
(ROW_OFF_BITS-1 downto 0 => '0');
-- Test if pending request is a hit on any way
-- Detect snooped writes and decode address into index and tag
-- Since we never write, any write should be snooped
snoop_valid <= wb_snoop_in.cyc and wb_snoop_in.stb and wb_snoop_in.we;
- snoop_addr := (others => '0');
- snoop_addr(wb_snoop_in.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS) := wb_snoop_in.adr;
+ snoop_addr := addr_to_real(wb_to_addr(wb_snoop_in.adr));
snoop_index <= get_index(snoop_addr);
snoop_cache_tags := cache_tags(get_index(snoop_addr));
snoop_tag := get_tag(snoop_addr, '0');
-- Prep for first wishbone read. We calculate the address of
-- the start of the cache line and start the WB cycle.
--
- r.wb.adr <= req_laddr(r.wb.adr'left + ROW_OFF_BITS downto ROW_OFF_BITS);
+ r.wb.adr <= addr_to_wb(req_laddr);
r.wb.cyc <= '1';
r.wb.stb <= '1';
if wishbone_in.stall = '0' and r.wb.stb = '1' then
-- That was the last word ? We are done sending. Clear stb.
--
- if is_last_row_addr(r.wb.adr, r.end_row_ix) then
+ if is_last_row_wb_addr(r.wb.adr, r.end_row_ix) then
r.wb.stb <= '0';
end if;
-- Calculate the next row address
- r.wb.adr <= next_row_addr(r.wb.adr);
+ r.wb.adr <= next_row_wb_addr(r.wb.adr);
end if;
-- Abort reload if we get an invalidation
when STOP_RELOAD =>
-- Wait for all outstanding requests to be satisfied, then
-- go to IDLE state.
- if get_row_of_line(r.store_row) = get_row_of_line(get_row(r.wb.adr)) then
+ if get_row_of_line(r.store_row) = get_row_of_line(get_row(wb_to_addr(r.wb.adr))) then
r.wb.cyc <= '0';
r.state <= IDLE;
end if;
subtype wishbone_data_type is std_ulogic_vector(wishbone_data_bits-1 downto 0);
subtype wishbone_sel_type is std_ulogic_vector(wishbone_sel_bits-1 downto 0);
+ function addr_to_wb(addr: std_ulogic_vector) return wishbone_addr_type;
+ function wb_to_addr(wb_addr: wishbone_addr_type) return std_ulogic_vector;
+
type wishbone_master_out is record
adr : wishbone_addr_type;
dat : wishbone_data_type;
--
-- IO Bus to a device, 30-bit address, 32-bits data
--
+
type wb_io_master_out is record
adr : std_ulogic_vector(29 downto 0);
dat : std_ulogic_vector(31 downto 0);
end record;
constant wb_io_slave_out_init : wb_io_slave_out := (ack => '0', stall => '0', others => (others => '0'));
end package wishbone_types;
+
+package body wishbone_types is
+ function addr_to_wb(addr: std_ulogic_vector) return wishbone_addr_type is
+ begin
+ assert addr'length >= (wishbone_addr_type'length + wishbone_log2_width);
+ assert addr'right = 0;
+ return addr(wishbone_addr_type'left + wishbone_log2_width downto wishbone_log2_width);
+ end;
+ function wb_to_addr(wb_addr: wishbone_addr_type) return std_ulogic_vector is
+ variable ret : std_ulogic_vector(63 downto 0);
+ begin
+ ret := (others => '0');
+ ret(wishbone_addr_type'left + wishbone_log2_width downto wishbone_log2_width) := wb_addr;
+ return ret;
+ end;
+end wishbone_types;