From 136e5bebb4d28d2eeb5c2971a2bd866c207945a0 Mon Sep 17 00:00:00 2001 From: Easton Man Date: Sat, 21 May 2022 20:06:31 +0800 Subject: [PATCH] feat: half-finished icache --- src/vsrc/icache.sv | 152 +++++++++++++++++++++++++++++++ src/vsrc/{BPU => }/utils/bram.sv | 25 ++--- 2 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 src/vsrc/icache.sv rename src/vsrc/{BPU => }/utils/bram.sv (65%) diff --git a/src/vsrc/icache.sv b/src/vsrc/icache.sv new file mode 100644 index 0000000..f72e406 --- /dev/null +++ b/src/vsrc/icache.sv @@ -0,0 +1,152 @@ + +`include "utils/bram.sv" + +module icache #( + parameter NSET = 256, + parameter NWAY = 2, + parameter CACHELINE_WIDTH = 128, + parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 32 +) ( + input logic clk, + input logic rst, + + // Read port 1 + input logic rreq_1_i, + input logic [ADDR_WIDTH-1:0] raddr_1_i, + output logic rvalid_1_o, + output logic [DATA_WIDTH-1:0] rdata_1_o, + + // Read port 2 + input logic rreq_2_i, + input logic [ADDR_WIDTH-1:0] raddr_2_i, + output logic rvalid_2_o, + output logic [DATA_WIDTH-1:0] rdata_2_o, + + // <-> AXI Controller + output logic [ADDR_WIDTH-1:0] axi_addr_o, + output logic axi_rreq_o, + input logic axi_busy_i, // High effective + input logic [DATA_WIDTH-1:0] axi_data_i +); + + + logic [NWAY-1:0][1:0][CACHELINE_WIDTH-1:0] data_bram_rdata; + logic [NWAY-1:0][1:0][CACHELINE_WIDTH-1:0] data_bram_wdata; + logic [NWAY-1:0][1:0][$clog2(NSET)-1:0] data_bram_addr; + logic [NWAY-1:0][1:0] data_bram_we; + + // Tag bram + // {1bit valid, 20bits tag} + localparam TAG_BRAM_WIDTH = 21; + logic [NWAY-1:0][1:0][TAG_BRAM_WIDTH-1:0] tag_bram_rdata; + logic [NWAY-1:0][1:0][TAG_BRAM_WIDTH-1:0] tag_bram_wdata; + logic [NWAY-1:0][1:0][$clog2(NSET)-1:0] tag_bram_addr; + logic [NWAY-1:0][1:0] tag_bram_we; + + generate + for (genvar i = 0; i < NWAY; i++) begin : tag_bram + bram #( + .DATA_WIDTH (TAG_BRAM_WIDTH), + .DATA_DEPTH_EXP2(10) + ) u_bram ( + .clk (clk), + .wea (tag_bram_we[i][0]), + .web (tag_bram_we[i][1]), + .dina (tag_bram_wdata[i][0]), + .addra(tag_bram_addr[i][0]), + .douta(tag_bram_rdata[i][0]), + .dinb (tag_bram_wdata[i][1]), + .addrb(tag_bram_addr[i][1]), + .doutb(tag_bram_rdata[i][1]) + ); + end + endgenerate + generate + for (genvar i = 0; i < NWAY; i++) begin : data_bram + bram #( + .DATA_WIDTH (128), + .DATA_DEPTH_EXP2(10) + ) u_bram ( + .clk (clk), + .wea (data_bram_we[i][0]), + .web (data_bram_we[i][1]), + .dina (data_bram_wdata[i][0]), + .addra(data_bram_addr[i][0]), + .douta(data_bram_rdata[i][0]), + .dinb (data_bram_wdata[i][1]), + .addrb(data_bram_addr[i][1]), + .doutb(data_bram_rdata[i][1]) + ); + end + endgenerate + + // Cache addr + always_comb begin : cache_addr_gen + for (integer i = 0; i < NWAY; i++) begin + if (rreq_1_i) begin + tag_bram_addr[i][0] = raddr_1_i[11:4]; + data_bram_addr[i][0] = raddr_1_i[11:4]; + end else begin // TODO: write + tag_bram_addr[i][0] = 0; + data_bram_addr[i][0] = 0; + end + end + for (integer i = 0; i < NWAY; i++) begin + if (rreq_2_i) begin + tag_bram_addr[i][1] = raddr_2_i[11:4]; + data_bram_addr[i][1] = raddr_2_i[11:4]; + end else begin + tag_bram_addr[i][1] = 0; + data_bram_addr[i][1] = 0; + end + end + end + + logic [NWAY-1:0][1:0] tag_hit; + always_comb begin + for (integer i = 0; i < NWAY; i++) begin + tag_hit[i][0] = tag_bram_rdata[i][0][19:0] == raddr_1_i[ADDR_WIDTH-1:ADDR_WIDTH-20]; + tag_hit[i][1] = tag_bram_rdata[i][1][19:0] == raddr_2_i[ADDR_WIDTH-1:ADDR_WIDTH-20]; + end + end + + // Generate read output + logic [1:0] offset_1, offset_2; + assign offset_1 = raddr_1_i[3:2]; + assign offset_2 = raddr_2_i[3:2]; + logic [NWAY-1:0][1:0][DATA_WIDTH-1:0] data_inside_cacheline; + always_comb begin + for (integer i = 0; i < NWAY; i++) begin + case (offset_1) + 2'b00: data_inside_cacheline[i][0] = data_bram_rdata[i][0][31:0]; + 2'b01: data_inside_cacheline[i][0] = data_bram_rdata[i][0][63:32]; + 2'b10: data_inside_cacheline[i][0] = data_bram_rdata[i][0][95:64]; + 2'b11: data_inside_cacheline[i][0] = data_bram_rdata[i][0][127:96]; + endcase + case (offset_2) + 2'b00: data_inside_cacheline[i][1] = data_bram_rdata[i][1][31:0]; + 2'b01: data_inside_cacheline[i][1] = data_bram_rdata[i][1][63:32]; + 2'b10: data_inside_cacheline[i][1] = data_bram_rdata[i][1][95:64]; + 2'b11: data_inside_cacheline[i][1] = data_bram_rdata[i][1][127:96]; + endcase + end + end + always_comb begin + rvalid_1_o = 0; + rdata_1_o = 0; + rvalid_2_o = 0; + rdata_2_o = 0; + for (integer i = 0; i < NWAY; i++) begin + if (tag_hit[i][0]) begin + rvalid_1_o = 1; + rdata_1_o = data_inside_cacheline[i][0]; + end + if (tag_hit[i][1]) begin + rvalid_2_o = 1; + rdata_2_o = data_inside_cacheline[i][1]; + end + end + end + +endmodule diff --git a/src/vsrc/BPU/utils/bram.sv b/src/vsrc/utils/bram.sv similarity index 65% rename from src/vsrc/BPU/utils/bram.sv rename to src/vsrc/utils/bram.sv index 7710132..d59eced 100644 --- a/src/vsrc/BPU/utils/bram.sv +++ b/src/vsrc/utils/bram.sv @@ -1,19 +1,20 @@ // simulate BRAM IP in simulation without Vivado // data read latency is 1 cycle module bram #( - parameter DATA_WIDTH = 1, - parameter DATA_DEPTH_EXP2 = 1 + parameter DATA_WIDTH = 128, + parameter ADDR_WIDTH = 8, + parameter DATA_DEPTH_EXP2 = 8 ) ( input logic clk, input logic wea, // Write enable A input logic web, // Write enable B - input logic [DATA_WIDTH-1:0] dina, - input logic [DATA_DEPTH_EXP2-1:0] addra, + input logic [DATA_WIDTH-1:0] dina, + input logic [ADDR_WIDTH-1:0] addra, output logic [DATA_WIDTH-1:0] douta, - input logic [DATA_WIDTH-1:0] dinb, - input logic [DATA_DEPTH_EXP2-1:0] addrb, + input logic [DATA_WIDTH-1:0] dinb, + input logic [ADDR_WIDTH-1:0] addrb, output logic [DATA_WIDTH-1:0] doutb ); @@ -34,13 +35,13 @@ module bram #( // Write logic always_ff @(posedge clk) begin - if (wea) begin - data[addra] <= dina; - end if (web) begin - if (addra != addrb) begin // Write conflict - data[addrb] <= dinb; - end + data[addrb[DATA_DEPTH_EXP2-1:0]] <= dinb; + end + + // A port has priority + if (wea) begin + data[addra[DATA_DEPTH_EXP2-1:0]] <= dina; end end