RVSCC/rtl/cache_memory.sv

104 lines
2.8 KiB
Systemverilog
Raw Normal View History

`include "timescale.sv"
2023-01-01 22:28:56 +00:00
2023-02-26 23:26:11 +00:00
module cache_memory #(
2023-01-29 04:55:22 +00:00
parameter int ADDR_SIZE = 32,
parameter int NUM_SETS = 16,
parameter int NUM_WAYS = 4,
parameter int BLOCK_SIZE = 32
) (
input logic clk,
2023-02-28 17:22:02 +00:00
input logic rst,
2023-03-02 19:56:34 +00:00
input logic [$clog2(NUM_WAYS) - 1:0] write_way,
input logic [$clog2(NUM_SETS) - 1:0] set,
input logic [ADDR_SIZE - $clog2(NUM_SETS) - $clog2(BLOCK_SIZE / 4) - 1:0] tag,
2023-01-01 22:28:56 +00:00
input logic write_enable,
2023-01-29 04:55:22 +00:00
input logic [BLOCK_SIZE - 1:0] write_data,
output logic [BLOCK_SIZE - 1:0] read_data,
2023-03-02 19:56:34 +00:00
output logic [$clog2(NUM_WAYS) - 1:0] populate_way,
2023-03-18 23:45:55 +00:00
output logic populated,
2023-03-02 19:56:34 +00:00
output logic hit
2023-01-01 22:28:56 +00:00
);
2023-01-29 04:55:22 +00:00
localparam int NumBlockBytes = BLOCK_SIZE / 4;
localparam int ByteOffsetSize = $clog2(NumBlockBytes);
localparam int WaySize = $clog2(NUM_WAYS);
localparam int SetSize = $clog2(NUM_SETS);
localparam int TagSize = ADDR_SIZE - SetSize - ByteOffsetSize;
2023-03-02 20:20:10 +00:00
2023-03-02 19:56:34 +00:00
logic [NUM_WAYS - 1:0] hits;
logic [WaySize-1:0] way;
logic [WaySize-1:0] read_way;
2023-03-02 20:20:10 +00:00
priority_encoder #(
.N(WaySize)
) read_way_encoder (
2023-03-02 19:56:34 +00:00
.data_in(hits),
.data_out(read_way),
.valid(hit)
);
2023-03-02 20:20:10 +00:00
2023-03-02 19:56:34 +00:00
always_comb begin
2023-03-02 20:20:10 +00:00
if (write_enable) way = write_way;
else way = read_way;
2023-03-02 19:56:34 +00:00
end
2023-01-29 04:55:22 +00:00
typedef struct packed {
logic [BLOCK_SIZE - 1:0] data;
logic [TagSize - 1:0] tag;
logic valid;
} cache_line_t;
2023-02-28 17:22:02 +00:00
typedef cache_line_t [NUM_SETS - 1:0] cache_way;
2023-01-29 04:55:22 +00:00
cache_way [NUM_WAYS - 1:0] ways;
assign read_data = ways[way][set].data;
always_ff @(posedge clk) begin
if (rst) begin
// Reset valid flags
for (int i = 0; i < NUM_WAYS; i++) begin
for (int j = 0; j < NUM_SETS; j++) begin
2023-02-28 17:22:02 +00:00
ways[i][j].data <= BLOCK_SIZE'('dx);
ways[i][j].tag <= TagSize'('dx);
2023-01-29 04:55:22 +00:00
ways[i][j].valid <= 0;
2023-01-01 22:28:56 +00:00
end
2023-01-29 04:55:22 +00:00
end
end else if (write_enable) begin
ways[way][set].data <= write_data;
ways[way][set].tag <= tag;
ways[way][set].valid <= 1;
end
end
2023-03-02 20:20:10 +00:00
2023-03-02 19:56:34 +00:00
logic [NUM_WAYS - 1:0] valid_flags;
2023-01-29 04:55:22 +00:00
always_comb begin
for (int i = 0; i < NUM_WAYS; i++) begin
valid_flags[i] = ways[i][set].valid;
hits[i] = ways[i][set].valid && (tag == ways[i][set].tag);
2023-01-01 22:28:56 +00:00
end
2023-01-29 04:55:22 +00:00
end
2023-03-02 20:20:10 +00:00
2023-03-18 23:45:55 +00:00
logic valid_flags_index_valid;
logic[WaySize-1:0] valid_flags_index;
2023-03-02 20:20:10 +00:00
priority_encoder #(
.N(WaySize)
) populate_way_encoder (
.data_in(valid_flags),
2023-03-18 23:45:55 +00:00
.data_out(valid_flags_index),
.valid(valid_flags_index_valid)
2023-03-02 19:56:34 +00:00
);
2023-03-18 23:45:55 +00:00
/*
generate
if (WaySize > 1)
always_comb populated &= populate_way;
else
assign populated = populate_way;
endgenerate*/
always_comb begin
if(valid_flags_index_valid)
{populated, populate_way} = valid_flags_index + 'd1;
else
{populated, populate_way} = 'd0;
end
2023-01-29 04:55:22 +00:00
endmodule