// To Do: Change way_id_out to an internal register which holds when in between access and finished. // Also add a bit about wheter the "Way ID" is valid / being held or if it is just default // Also make sure all possible output states are transmitted back to the bank correctly `include "../VX_define.v" // `include "VX_cache_data.v" module VX_Cache_Bank #( parameter CACHE_SIZE = 4096, // Bytes parameter CACHE_WAYS = 1, parameter CACHE_BLOCK = 128, // Bytes parameter CACHE_BANKS = 8, parameter LOG_NUM_BANKS = 3, parameter NUM_REQ = 8, parameter LOG_NUM_REQ = 3, parameter NUM_IND = 8, parameter CACHE_WAY_INDEX = 1, parameter NUM_WORDS_PER_BLOCK = 4, parameter OFFSET_SIZE_START = 0, parameter OFFSET_SIZE_END = 1, parameter TAG_SIZE_START = 0, parameter TAG_SIZE_END = 16, parameter IND_SIZE_START = 0, parameter IND_SIZE_END = 7, parameter ADDR_TAG_START = 15, parameter ADDR_TAG_END = 31, parameter ADDR_OFFSET_START = 5, parameter ADDR_OFFSET_END = 6, parameter ADDR_IND_START = 7, parameter ADDR_IND_END = 14 ) ( clk, rst, state, read_or_write, // Read = 0 | Write = 1 i_p_mem_read, i_p_mem_write, valid_in, //write_from_mem, actual_index, o_tag, block_offset, writedata, fetched_writedata, byte_select, readdata, hit, //miss, eviction_wb, // Need to evict eviction_addr, // What's the eviction tag data_evicted, evicted_way ); // localparam NUMBER_BANKS = `CACHE_BANKS; // localparam CACHE_BLOCK_PER_BANK = (`CACHE_BLOCK / `CACHE_BANKS); // localparam NUM_WORDS_PER_BLOCK = `CACHE_BLOCK / (`CACHE_BANKS*4); // localparam NUMBER_INDEXES = `NUM_IND; localparam CACHE_IDLE = 0; // Idle localparam SEND_MEM_REQ = 1; // Write back this block into memory localparam RECIV_MEM_RSP = 2; localparam BLOCK_NUM_BITS = `CLOG2(CACHE_BLOCK); // Inputs input wire rst; input wire clk; input wire [3:0] state; //input wire write_from_mem; // Reading Data input wire[IND_SIZE_END:IND_SIZE_START] actual_index; input wire[TAG_SIZE_END:TAG_SIZE_START] o_tag; // When write_from_mem = 1, o_tag is the new tag input wire[OFFSET_SIZE_END:OFFSET_SIZE_START] block_offset; input wire[31:0] writedata; input wire valid_in; input wire read_or_write; // Specifies if it is a read or write operation input wire[NUM_WORDS_PER_BLOCK-1:0][31:0] fetched_writedata; input wire[2:0] i_p_mem_read; input wire[2:0] i_p_mem_write; input wire[1:0] byte_select; input wire[CACHE_WAY_INDEX-1:0] evicted_way; // Outputs // Normal shit output wire[31:0] readdata; output wire hit; //output wire miss; // Eviction Data (Notice) output wire eviction_wb; // Need to evict output wire[31:0] eviction_addr; // What's the eviction tag // Eviction Data (Extraction) output wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_evicted; wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_use; wire[TAG_SIZE_END:TAG_SIZE_START] tag_use; wire[TAG_SIZE_END:TAG_SIZE_START] eviction_tag; wire valid_use; wire dirty_use; wire access; wire write_from_mem; wire miss; // -10/21 wire[CACHE_WAY_INDEX-1:0] way_to_update; assign miss = (tag_use != o_tag) && valid_use && valid_in; assign data_evicted = data_use; // assign eviction_wb = miss && (dirty_use != 1'b0) && valid_use; assign eviction_wb = (dirty_use != 1'b0); assign eviction_tag = tag_use; assign access = (state == CACHE_IDLE) && valid_in; assign write_from_mem = (state == RECIV_MEM_RSP) && valid_in; // TODO assign hit = (access && (tag_use == o_tag) && valid_use); //assign eviction_addr = {eviction_tag, actual_index, block_offset, 5'b0}; // Fix with actual data assign eviction_addr = {eviction_tag, actual_index, {(BLOCK_NUM_BITS){1'b0}}}; // Fix with actual data wire lw = (i_p_mem_read == `LW_MEM_READ); wire lb = (i_p_mem_read == `LB_MEM_READ); wire lh = (i_p_mem_read == `LH_MEM_READ); wire lhu = (i_p_mem_read == `LHU_MEM_READ); wire lbu = (i_p_mem_read == `LBU_MEM_READ); wire sw = (i_p_mem_write == `SW_MEM_WRITE); wire sb = (i_p_mem_write == `SB_MEM_WRITE); wire sh = (i_p_mem_write == `SH_MEM_WRITE); wire b0 = (byte_select == 0); wire b1 = (byte_select == 1); wire b2 = (byte_select == 2); wire b3 = (byte_select == 3); wire[31:0] data_unQual = (b0 || lw) ? (data_use[block_offset] ) : b1 ? (data_use[block_offset] >> 8) : b2 ? (data_use[block_offset] >> 16) : (data_use[block_offset] >> 24); wire[31:0] lb_data = (data_unQual[7] ) ? (data_unQual | 32'hFFFFFF00) : (data_unQual & 32'hFF); wire[31:0] lh_data = (data_unQual[15]) ? (data_unQual | 32'hFFFF0000) : (data_unQual & 32'hFFFF); wire[31:0] lbu_data = (data_unQual & 32'hFF); wire[31:0] lhu_data = (data_unQual & 32'hFFFF); wire[31:0] lw_data = (data_unQual); wire[31:0] sw_data = writedata; wire[31:0] sb_data = b1 ? {{16{1'b0}}, writedata[7:0], { 8{1'b0}}} : b2 ? {{ 8{1'b0}}, writedata[7:0], {16{1'b0}}} : b3 ? {{ 0{1'b0}}, writedata[7:0], {24{1'b0}}} : writedata; wire[31:0] sh_data = b2 ? {writedata[15:0], {16{1'b0}}} : writedata; wire[31:0] use_write_data = sb ? sb_data : sh ? sh_data : sw_data; wire[31:0] data_Qual = lb ? lb_data : lh ? lh_data : lhu ? lhu_data : lbu ? lbu_data : lw_data; assign readdata = (access) ? data_Qual : 32'b0; // Fix with actual data wire[3:0] sb_mask = (b0 ? 4'b0001 : (b1 ? 4'b0010 : (b2 ? 4'b0100 : 4'b1000))); wire[3:0] sh_mask = (b0 ? 4'b0011 : 4'b1100); wire[NUM_WORDS_PER_BLOCK-1:0][3:0] we; wire[NUM_WORDS_PER_BLOCK-1:0][31:0] data_write; genvar g; for (g = 0; g < NUM_WORDS_PER_BLOCK; g = g + 1) begin wire normal_write = (read_or_write && ((access && (block_offset == g))) && !miss); assign we[g] = (write_from_mem) ? 4'b1111 : (normal_write && sw) ? 4'b1111 : (normal_write && sb) ? sb_mask : (normal_write && sh) ? sh_mask : 4'b0000; // assign we[g] = (normal_write || (write_from_mem)) ? 1'b1 : 1'b0; assign data_write[g] = write_from_mem ? fetched_writedata[g] : use_write_data; assign way_to_update = evicted_way; end VX_cache_data_per_index #( .CACHE_WAYS (CACHE_WAYS), .NUM_IND (NUM_IND), .CACHE_WAY_INDEX (CACHE_WAY_INDEX), .NUM_WORDS_PER_BLOCK(NUM_WORDS_PER_BLOCK), .TAG_SIZE_START (TAG_SIZE_START), .TAG_SIZE_END (TAG_SIZE_END), .IND_SIZE_START (IND_SIZE_START), .IND_SIZE_END (IND_SIZE_END)) data_structures( .clk (clk), .rst (rst), .valid_in (valid_in), .state (state), // Inputs .addr (actual_index), .we (we), .evict (write_from_mem), .data_write (data_write), .tag_write (o_tag), .way_to_update(way_to_update), // Outputs .tag_use (tag_use), .data_use (data_use), .valid_use (valid_use), .dirty_use (dirty_use) ); endmodule