rv32g-core

Pipelined, synthesizable, and fabricable RISC-V core in SystemVerilog+Yosys+OpenROAD
Log | Files | Refs | LICENSE

commit bc45a18510474069f97c55481f64f2397ba69444
parent 6a78ab80cc3de152aca15c5dcf416ba2c3cb3c6a
Author: Vineet Kumar <git@vineetk.net>
Date:   Fri,  7 Aug 2026 14:40:04 +0530

fold i-cache tag+valid into BSRAM to cut critical path

Recovery-Origin: a139678b4ed4a1ad5293bc95b89fa6527b24b669
Recovery-Status: reconstructed history

Recovered final stage_fetch.sv supplies combined tag/valid block-RAM storage and sweep invalidation. Assigning this surviving file to this commit follows its reflog message; the original commit object is missing.

Diffstat:
Mrtl/stage_fetch.sv | 61++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 34 insertions(+), 27 deletions(-)

diff --git a/rtl/stage_fetch.sv b/rtl/stage_fetch.sv @@ -11,55 +11,62 @@ module stage_fetch `define USE_ICACHE `ifdef USE_ICACHE - localparam CACHE_SIZE = 2048; // words - localparam IDX_WIDTH = $clog2(CACHE_SIZE); - localparam TAG_WIDTH = 32 - IDX_WIDTH - 2; // only be byte offset + localparam CACHE_SIZE = 2048; // words + localparam IDX_WIDTH = $clog2(CACHE_SIZE); + localparam TAG_WIDTH = 32 - IDX_WIDTH - 2; // only be byte offset + localparam TAG_INVALID = {TAG_WIDTH+1{1'b1}}; - (* keep *) logic [31:0] cache [0:CACHE_SIZE-1]; - (* keep *) logic valid [0:CACHE_SIZE-1]; - logic [IDX_WIDTH-1:0] idx; - (* keep *) logic [TAG_WIDTH-1:0] tag_mem [0:CACHE_SIZE-1]; - logic [TAG_WIDTH-1:0] tag_pc; - logic [31:0] cache_data; - logic [IDX_WIDTH-1:0] resp_idx; - logic [TAG_WIDTH-1:0] cache_tag, resp_tag; - logic cache_valid, resp_valid; - logic hit; + (* ram_style = "block" *) logic [31:0] cache [0:CACHE_SIZE-1]; + (* ram_style = "block" *) logic [TAG_WIDTH:0] tag_mem [0:CACHE_SIZE-1]; + logic [IDX_WIDTH-1:0] idx; + logic [TAG_WIDTH-1:0] tag_pc; + logic [31:0] cache_data; + logic [IDX_WIDTH-1:0] resp_idx; + logic [TAG_WIDTH-1:0] resp_tag; + logic [TAG_WIDTH:0] cache_tagv; // {valid,tag} registered read + logic resp_valid; + logic flush_active; + logic [IDX_WIDTH-1:0] flush_cnt; + logic hit; always_comb begin imem_addr = pc; idx = pc[IDX_WIDTH+1:2]; tag_pc = pc[31:IDX_WIDTH+2]; - hit = resp_valid && cache_valid && (cache_tag == resp_tag); + hit = resp_valid && cache_tagv[TAG_WIDTH] && (cache_tagv[TAG_WIDTH-1:0] == resp_tag); inst = hit ? cache_data : imem_data; end always_ff @(posedge clk or negedge rstN) begin if (!rstN) begin // async flush - for (int i = 0; i < CACHE_SIZE; i++) valid[i] <= 0; + flush_active <= 1'b1; + flush_cnt <= '0; cache_data <= '0; - cache_tag <= '0; - cache_valid <= 0; - resp_idx <= '0; - resp_tag <= '0; - resp_valid <= 0; - end else if (flush_i) begin // sync flush - for (int i = 0; i < CACHE_SIZE; i++) valid[i] <= 0; - cache_valid <= 0; resp_valid <= 0; + end else if (flush_active) begin // sweep invalidation writes + tag_mem[flush_cnt] <= TAG_INVALID; + if (flush_cnt == IDX_WIDTH'(CACHE_SIZE-1)) begin + flush_active <= 1'b0; + flush_cnt <= '0; + end else begin + flush_cnt <= flush_cnt + 1'b1; + end + resp_valid <= 1'b0; + end else if (flush_i) begin // sync flush (fence.i) + flush_active <= 1'b1; + flush_cnt <= '0; + resp_valid <= 1'b0; end else begin // fill using the registered backing-memory response if (resp_valid && imem_valid && !hit) begin cache[resp_idx] <= imem_data; - tag_mem[resp_idx] <= resp_tag; - valid[resp_idx] <= 1; + tag_mem[resp_idx] <= {1'b1, resp_tag}; end // registered cache read for the current fetch request cache_data <= cache[idx]; - cache_tag <= tag_mem[idx]; - cache_valid <= valid[idx]; + cache_tagv <= tag_mem[idx]; resp_idx <= idx; resp_tag <= tag_pc; resp_valid <= 1;