rv32g-core

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

stage_fetch.sv (2467B)


      1 module stage_fetch
      2   (input logic	       clk,
      3    input logic	       rstN,
      4    input logic	       flush_i,	// from fence.i
      5    input logic [31:0]  pc,
      6    input logic [31:0]  imem_data,
      7    input logic	       imem_valid,
      8    output logic [31:0] imem_addr,
      9    output logic [31:0] inst);
     10 
     11 `define USE_ICACHE
     12 `ifdef USE_ICACHE
     13 
     14    localparam					 CACHE_SIZE = 2048;		 // words
     15    localparam					 IDX_WIDTH = $clog2(CACHE_SIZE);
     16    localparam					 TAG_WIDTH = 32 - IDX_WIDTH - 2; // only be byte offset
     17    localparam					 TAG_INVALID = {TAG_WIDTH+1{1'b1}};
     18 
     19    (* ram_style = "block" *) logic [31:0]	 cache [0:CACHE_SIZE-1];
     20    (* ram_style = "block" *) logic [TAG_WIDTH:0] tag_mem [0:CACHE_SIZE-1];
     21    logic [IDX_WIDTH-1:0]			 idx;
     22    logic [TAG_WIDTH-1:0]			 tag_pc;
     23    logic [31:0]					 cache_data;
     24    logic [IDX_WIDTH-1:0]			 resp_idx;
     25    logic [TAG_WIDTH-1:0]			 resp_tag;
     26    logic [TAG_WIDTH:0]				 cache_tagv;			 // {valid,tag} registered read
     27    logic					 resp_valid;
     28    logic					 flush_active;
     29    logic [IDX_WIDTH-1:0]			 flush_cnt;
     30    logic					 hit;
     31 
     32    always_comb begin
     33      imem_addr = pc;
     34      idx = pc[IDX_WIDTH+1:2];
     35      tag_pc = pc[31:IDX_WIDTH+2];
     36 
     37      hit = resp_valid && cache_tagv[TAG_WIDTH] && (cache_tagv[TAG_WIDTH-1:0] == resp_tag);
     38      inst = hit ? cache_data : imem_data;
     39    end
     40 
     41    always_ff @(posedge clk or negedge rstN) begin
     42      if (!rstN) begin // async flush
     43        flush_active <= 1'b1;
     44        flush_cnt <= '0;
     45        cache_data <= '0;
     46        resp_valid <= 0;
     47      end else if (flush_active) begin // sweep invalidation writes
     48        tag_mem[flush_cnt] <= TAG_INVALID;
     49        if (flush_cnt == IDX_WIDTH'(CACHE_SIZE-1)) begin
     50 	 flush_active <= 1'b0;
     51 	 flush_cnt <= '0;
     52        end else begin
     53 	 flush_cnt <= flush_cnt + 1'b1;
     54        end
     55        resp_valid <= 1'b0;
     56      end else if (flush_i) begin // sync flush (fence.i)
     57        flush_active <= 1'b1;
     58        flush_cnt <= '0;
     59        resp_valid <= 1'b0;
     60      end else begin
     61        // fill using the registered backing-memory response
     62        if (resp_valid && imem_valid && !hit) begin
     63          cache[resp_idx] <= imem_data;
     64 	 tag_mem[resp_idx] <= {1'b1, resp_tag};
     65        end
     66 
     67        // registered cache read for the current fetch request
     68        cache_data <= cache[idx];
     69        cache_tagv <= tag_mem[idx];
     70        resp_idx <= idx;
     71        resp_tag <= tag_pc;
     72        resp_valid <= 1;
     73      end
     74    end
     75 
     76 `else
     77 
     78    assign imem_addr = pc;
     79    assign inst = imem_data;
     80 
     81 `endif
     82 
     83 endmodule: stage_fetch