mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 03:47:15 -04:00
[rtl/icache] Move various parameters into the pkg
No functional change. These parameters are effectively fixed. Moving them to the pkg eases top-level wiring of RAM signals. Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit is contained in:
parent
a799a92e5e
commit
b106001d82
4 changed files with 245 additions and 237 deletions
|
@ -60,7 +60,7 @@ module tb #(parameter bit ICacheECC = 1'b0);
|
|||
// each data ram, binding them into the RAMs themselves. ECC tests can use these to insert errors
|
||||
// into memory lookups.
|
||||
generate if (dut.ICacheECC) begin : gen_ecc
|
||||
for (genvar w = 0; w < dut.NumWays; w++) begin : gen_ecc_ifs
|
||||
for (genvar w = 0; w < ibex_pkg::IC_NUM_WAYS; w++) begin : gen_ecc_ifs
|
||||
bind dut.gen_rams[w].tag_bank.gen_badbit.u_impl_badbit ibex_icache_ecc_if tag_bank_if (.*);
|
||||
bind dut.gen_rams[w].data_bank.gen_badbit.u_impl_badbit ibex_icache_ecc_if data_bank_if (.*);
|
||||
|
||||
|
@ -93,7 +93,7 @@ module tb #(parameter bit ICacheECC = 1'b0);
|
|||
|
||||
// Record the number of (ECC) ways in the config database. The top-level environment's config
|
||||
// will use this to decide how many agents to create.
|
||||
uvm_config_db#(int unsigned)::set(null, "*", "num_ecc_ways", dut.ICacheECC ? dut.NumWays : 0);
|
||||
uvm_config_db#(int unsigned)::set(null, "*", "num_ecc_ways", dut.ICacheECC ? ibex_pkg::IC_NUM_WAYS : 0);
|
||||
|
||||
$timeformat(-12, 0, " ps", 12);
|
||||
run_test();
|
||||
|
|
|
@ -10,6 +10,7 @@ filesets:
|
|||
- lowrisc:prim:secded
|
||||
- lowrisc:prim:ram_1p
|
||||
- lowrisc:prim:assert
|
||||
- lowrisc:ibex:ibex_pkg
|
||||
files:
|
||||
- rtl/ibex_icache.sv
|
||||
file_type: systemVerilogSource
|
||||
|
|
|
@ -12,192 +12,177 @@
|
|||
|
||||
module ibex_icache #(
|
||||
parameter bit BranchPredictor = 1'b0,
|
||||
// Cache arrangement parameters
|
||||
parameter int unsigned BusWidth = 32,
|
||||
parameter int unsigned CacheSizeBytes = 4*1024,
|
||||
parameter bit ICacheECC = 1'b0,
|
||||
parameter int unsigned LineSize = 64,
|
||||
parameter int unsigned NumWays = 2,
|
||||
// Only cache branch targets
|
||||
parameter bit BranchCache = 1'b0
|
||||
) (
|
||||
// Clock and reset
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
// Signal that the core would like instructions
|
||||
input logic req_i,
|
||||
input logic req_i,
|
||||
|
||||
// Set the cache's address counter
|
||||
input logic branch_i,
|
||||
input logic branch_spec_i,
|
||||
input logic predicted_branch_i,
|
||||
input logic branch_mispredict_i,
|
||||
input logic [31:0] addr_i,
|
||||
input logic branch_i,
|
||||
input logic branch_spec_i,
|
||||
input logic predicted_branch_i,
|
||||
input logic branch_mispredict_i,
|
||||
input logic [31:0] addr_i,
|
||||
|
||||
// IF stage interface: Pass fetched instructions to the core
|
||||
input logic ready_i,
|
||||
output logic valid_o,
|
||||
output logic [31:0] rdata_o,
|
||||
output logic [31:0] addr_o,
|
||||
output logic err_o,
|
||||
output logic err_plus2_o,
|
||||
input logic ready_i,
|
||||
output logic valid_o,
|
||||
output logic [31:0] rdata_o,
|
||||
output logic [31:0] addr_o,
|
||||
output logic err_o,
|
||||
output logic err_plus2_o,
|
||||
|
||||
// Instruction memory / interconnect interface: Fetch instruction data from memory
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [BusWidth-1:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
input logic instr_pmp_err_i,
|
||||
input logic instr_rvalid_i,
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [ibex_pkg::BUS_WIDTH-1:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
input logic instr_pmp_err_i,
|
||||
input logic instr_rvalid_i,
|
||||
|
||||
// Cache status
|
||||
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
|
||||
input logic icache_enable_i,
|
||||
input logic icache_inval_i,
|
||||
output logic busy_o
|
||||
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
|
||||
input logic icache_enable_i,
|
||||
input logic icache_inval_i,
|
||||
output logic busy_o
|
||||
);
|
||||
// Local constants
|
||||
localparam int unsigned ADDR_W = 32;
|
||||
|
||||
import ibex_pkg::*;
|
||||
|
||||
// Number of fill buffers (must be >= 2)
|
||||
localparam int unsigned NUM_FB = 4;
|
||||
localparam int unsigned NUM_FB = 4;
|
||||
// Request throttling threshold
|
||||
localparam int unsigned FB_THRESHOLD = NUM_FB - 2;
|
||||
localparam int unsigned FB_THRESHOLD = NUM_FB - 2;
|
||||
// Derived parameters
|
||||
localparam int unsigned LINE_SIZE_BYTES = LineSize/8;
|
||||
localparam int unsigned LINE_W = $clog2(LINE_SIZE_BYTES);
|
||||
localparam int unsigned BUS_SIZE_ECC = ICacheECC ? (BusWidth + 7) : BusWidth;
|
||||
localparam int unsigned BUS_BYTES = BusWidth/8;
|
||||
localparam int unsigned BUS_W = $clog2(BUS_BYTES);
|
||||
localparam int unsigned LINE_BEATS = LINE_SIZE_BYTES / BUS_BYTES;
|
||||
localparam int unsigned LINE_BEATS_W = $clog2(LINE_BEATS);
|
||||
localparam int unsigned NUM_LINES = CacheSizeBytes / NumWays / LINE_SIZE_BYTES;
|
||||
localparam int unsigned LINE_SIZE_ECC = BUS_SIZE_ECC * LINE_BEATS;
|
||||
localparam int unsigned INDEX_W = $clog2(NUM_LINES);
|
||||
localparam int unsigned INDEX_HI = INDEX_W + LINE_W - 1;
|
||||
localparam int unsigned TAG_SIZE = ADDR_W - INDEX_W - LINE_W + 1; // 1 valid bit
|
||||
localparam int unsigned TAG_SIZE_ECC = ICacheECC ? (TAG_SIZE + 6) : TAG_SIZE;
|
||||
localparam int unsigned OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords
|
||||
localparam int unsigned BUS_SIZE_ECC = ICacheECC ? (BUS_WIDTH + 7) : BUS_WIDTH;
|
||||
localparam int unsigned LINE_SIZE_ECC = BUS_SIZE_ECC * IC_LINE_BEATS;
|
||||
localparam int unsigned TAG_SIZE_ECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE;
|
||||
|
||||
// Prefetch signals
|
||||
logic [ADDR_W-1:0] lookup_addr_aligned;
|
||||
logic [ADDR_W-1:0] branch_mispredict_addr;
|
||||
logic [ADDR_W-1:0] prefetch_addr_d, prefetch_addr_q;
|
||||
logic prefetch_addr_en;
|
||||
logic branch_or_mispredict;
|
||||
logic [ADDR_W-1:0] lookup_addr_aligned;
|
||||
logic [ADDR_W-1:0] branch_mispredict_addr;
|
||||
logic [ADDR_W-1:0] prefetch_addr_d, prefetch_addr_q;
|
||||
logic prefetch_addr_en;
|
||||
logic branch_or_mispredict;
|
||||
// Cache pipelipe IC0 signals
|
||||
logic branch_suppress;
|
||||
logic lookup_throttle;
|
||||
logic lookup_req_ic0;
|
||||
logic [ADDR_W-1:0] lookup_addr_ic0;
|
||||
logic [INDEX_W-1:0] lookup_index_ic0;
|
||||
logic fill_req_ic0;
|
||||
logic [INDEX_W-1:0] fill_index_ic0;
|
||||
logic [TAG_SIZE-1:0] fill_tag_ic0;
|
||||
logic [LineSize-1:0] fill_wdata_ic0;
|
||||
logic lookup_grant_ic0;
|
||||
logic lookup_actual_ic0;
|
||||
logic fill_grant_ic0;
|
||||
logic tag_req_ic0;
|
||||
logic [INDEX_W-1:0] tag_index_ic0;
|
||||
logic [NumWays-1:0] tag_banks_ic0;
|
||||
logic tag_write_ic0;
|
||||
logic [TAG_SIZE_ECC-1:0] tag_wdata_ic0;
|
||||
logic data_req_ic0;
|
||||
logic [INDEX_W-1:0] data_index_ic0;
|
||||
logic [NumWays-1:0] data_banks_ic0;
|
||||
logic data_write_ic0;
|
||||
logic [LINE_SIZE_ECC-1:0] data_wdata_ic0;
|
||||
logic branch_suppress;
|
||||
logic lookup_throttle;
|
||||
logic lookup_req_ic0;
|
||||
logic [ADDR_W-1:0] lookup_addr_ic0;
|
||||
logic [IC_INDEX_W-1:0] lookup_index_ic0;
|
||||
logic fill_req_ic0;
|
||||
logic [IC_INDEX_W-1:0] fill_index_ic0;
|
||||
logic [IC_TAG_SIZE-1:0] fill_tag_ic0;
|
||||
logic [IC_LINE_SIZE-1:0] fill_wdata_ic0;
|
||||
logic lookup_grant_ic0;
|
||||
logic lookup_actual_ic0;
|
||||
logic fill_grant_ic0;
|
||||
logic tag_req_ic0;
|
||||
logic [IC_INDEX_W-1:0] tag_index_ic0;
|
||||
logic [IC_NUM_WAYS-1:0] tag_banks_ic0;
|
||||
logic tag_write_ic0;
|
||||
logic [TAG_SIZE_ECC-1:0] tag_wdata_ic0;
|
||||
logic data_req_ic0;
|
||||
logic [IC_INDEX_W-1:0] data_index_ic0;
|
||||
logic [IC_NUM_WAYS-1:0] data_banks_ic0;
|
||||
logic data_write_ic0;
|
||||
logic [LINE_SIZE_ECC-1:0] data_wdata_ic0;
|
||||
// Cache pipelipe IC1 signals
|
||||
logic [TAG_SIZE_ECC-1:0] tag_rdata_ic1 [NumWays];
|
||||
logic [LINE_SIZE_ECC-1:0] data_rdata_ic1 [NumWays];
|
||||
logic [LINE_SIZE_ECC-1:0] hit_data_ecc_ic1;
|
||||
logic [LineSize-1:0] hit_data_ic1;
|
||||
logic lookup_valid_ic1;
|
||||
logic [ADDR_W-1:INDEX_HI+1] lookup_addr_ic1;
|
||||
logic [NumWays-1:0] tag_match_ic1;
|
||||
logic tag_hit_ic1;
|
||||
logic [NumWays-1:0] tag_invalid_ic1;
|
||||
logic [NumWays-1:0] lowest_invalid_way_ic1;
|
||||
logic [NumWays-1:0] round_robin_way_ic1, round_robin_way_q;
|
||||
logic [NumWays-1:0] sel_way_ic1;
|
||||
logic ecc_err_ic1;
|
||||
logic ecc_write_req;
|
||||
logic [NumWays-1:0] ecc_write_ways;
|
||||
logic [INDEX_W-1:0] ecc_write_index;
|
||||
logic [TAG_SIZE_ECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS];
|
||||
logic [LINE_SIZE_ECC-1:0] data_rdata_ic1 [IC_NUM_WAYS];
|
||||
logic [LINE_SIZE_ECC-1:0] hit_data_ecc_ic1;
|
||||
logic [IC_LINE_SIZE-1:0] hit_data_ic1;
|
||||
logic lookup_valid_ic1;
|
||||
logic [ADDR_W-1:IC_INDEX_HI+1] lookup_addr_ic1;
|
||||
logic [IC_NUM_WAYS-1:0] tag_match_ic1;
|
||||
logic tag_hit_ic1;
|
||||
logic [IC_NUM_WAYS-1:0] tag_invalid_ic1;
|
||||
logic [IC_NUM_WAYS-1:0] lowest_invalid_way_ic1;
|
||||
logic [IC_NUM_WAYS-1:0] round_robin_way_ic1, round_robin_way_q;
|
||||
logic [IC_NUM_WAYS-1:0] sel_way_ic1;
|
||||
logic ecc_err_ic1;
|
||||
logic ecc_write_req;
|
||||
logic [IC_NUM_WAYS-1:0] ecc_write_ways;
|
||||
logic [IC_INDEX_W-1:0] ecc_write_index;
|
||||
// Fill buffer signals
|
||||
logic gnt_or_pmp_err, gnt_not_pmp_err;
|
||||
logic [$clog2(NUM_FB)-1:0] fb_fill_level;
|
||||
logic fill_cache_new;
|
||||
logic fill_new_alloc;
|
||||
logic fill_spec_req, fill_spec_done, fill_spec_hold;
|
||||
logic [NUM_FB-1:0][NUM_FB-1:0] fill_older_d, fill_older_q;
|
||||
logic [NUM_FB-1:0] fill_alloc_sel, fill_alloc;
|
||||
logic [NUM_FB-1:0] fill_busy_d, fill_busy_q;
|
||||
logic [NUM_FB-1:0] fill_done;
|
||||
logic [NUM_FB-1:0] fill_in_ic1;
|
||||
logic [NUM_FB-1:0] fill_stale_d, fill_stale_q;
|
||||
logic [NUM_FB-1:0] fill_cache_d, fill_cache_q;
|
||||
logic [NUM_FB-1:0] fill_hit_ic1, fill_hit_d, fill_hit_q;
|
||||
logic [NUM_FB-1:0][LINE_BEATS_W:0] fill_ext_cnt_d, fill_ext_cnt_q;
|
||||
logic [NUM_FB-1:0] fill_ext_hold_d, fill_ext_hold_q;
|
||||
logic [NUM_FB-1:0] fill_ext_done_d, fill_ext_done_q;
|
||||
logic [NUM_FB-1:0][LINE_BEATS_W:0] fill_rvd_cnt_d, fill_rvd_cnt_q;
|
||||
logic [NUM_FB-1:0] fill_rvd_done;
|
||||
logic [NUM_FB-1:0] fill_ram_done_d, fill_ram_done_q;
|
||||
logic [NUM_FB-1:0] fill_out_grant;
|
||||
logic [NUM_FB-1:0][LINE_BEATS_W:0] fill_out_cnt_d, fill_out_cnt_q;
|
||||
logic [NUM_FB-1:0] fill_out_done;
|
||||
logic [NUM_FB-1:0] fill_ext_req, fill_rvd_exp, fill_ram_req, fill_out_req;
|
||||
logic [NUM_FB-1:0] fill_data_sel, fill_data_reg, fill_data_hit, fill_data_rvd;
|
||||
logic [NUM_FB-1:0][LINE_BEATS_W-1:0] fill_ext_off, fill_rvd_off;
|
||||
logic [NUM_FB-1:0][LINE_BEATS_W:0] fill_ext_beat, fill_rvd_beat;
|
||||
logic [NUM_FB-1:0] fill_ext_arb, fill_ram_arb, fill_out_arb;
|
||||
logic [NUM_FB-1:0] fill_rvd_arb;
|
||||
logic [NUM_FB-1:0] fill_entry_en;
|
||||
logic [NUM_FB-1:0] fill_addr_en;
|
||||
logic [NUM_FB-1:0] fill_way_en;
|
||||
logic [NUM_FB-1:0][LINE_BEATS-1:0] fill_data_en;
|
||||
logic [NUM_FB-1:0][LINE_BEATS-1:0] fill_err_d, fill_err_q;
|
||||
logic [ADDR_W-1:0] fill_addr_q [NUM_FB];
|
||||
logic [NumWays-1:0] fill_way_q [NUM_FB];
|
||||
logic [LineSize-1:0] fill_data_d [NUM_FB];
|
||||
logic [LineSize-1:0] fill_data_q [NUM_FB];
|
||||
logic [ADDR_W-1:BUS_W] fill_ext_req_addr;
|
||||
logic [ADDR_W-1:0] fill_ram_req_addr;
|
||||
logic [NumWays-1:0] fill_ram_req_way;
|
||||
logic [LineSize-1:0] fill_ram_req_data;
|
||||
logic [LineSize-1:0] fill_out_data;
|
||||
logic [LINE_BEATS-1:0] fill_out_err;
|
||||
logic gnt_or_pmp_err, gnt_not_pmp_err;
|
||||
logic [$clog2(NUM_FB)-1:0] fb_fill_level;
|
||||
logic fill_cache_new;
|
||||
logic fill_new_alloc;
|
||||
logic fill_spec_req, fill_spec_done, fill_spec_hold;
|
||||
logic [NUM_FB-1:0][NUM_FB-1:0] fill_older_d, fill_older_q;
|
||||
logic [NUM_FB-1:0] fill_alloc_sel, fill_alloc;
|
||||
logic [NUM_FB-1:0] fill_busy_d, fill_busy_q;
|
||||
logic [NUM_FB-1:0] fill_done;
|
||||
logic [NUM_FB-1:0] fill_in_ic1;
|
||||
logic [NUM_FB-1:0] fill_stale_d, fill_stale_q;
|
||||
logic [NUM_FB-1:0] fill_cache_d, fill_cache_q;
|
||||
logic [NUM_FB-1:0] fill_hit_ic1, fill_hit_d, fill_hit_q;
|
||||
logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_cnt_d, fill_ext_cnt_q;
|
||||
logic [NUM_FB-1:0] fill_ext_hold_d, fill_ext_hold_q;
|
||||
logic [NUM_FB-1:0] fill_ext_done_d, fill_ext_done_q;
|
||||
logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_rvd_cnt_d, fill_rvd_cnt_q;
|
||||
logic [NUM_FB-1:0] fill_rvd_done;
|
||||
logic [NUM_FB-1:0] fill_ram_done_d, fill_ram_done_q;
|
||||
logic [NUM_FB-1:0] fill_out_grant;
|
||||
logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_out_cnt_d, fill_out_cnt_q;
|
||||
logic [NUM_FB-1:0] fill_out_done;
|
||||
logic [NUM_FB-1:0] fill_ext_req, fill_rvd_exp, fill_ram_req, fill_out_req;
|
||||
logic [NUM_FB-1:0] fill_data_sel, fill_data_reg, fill_data_hit, fill_data_rvd;
|
||||
logic [NUM_FB-1:0][IC_LINE_BEATS_W-1:0] fill_ext_off, fill_rvd_off;
|
||||
logic [NUM_FB-1:0][IC_LINE_BEATS_W:0] fill_ext_beat, fill_rvd_beat;
|
||||
logic [NUM_FB-1:0] fill_ext_arb, fill_ram_arb, fill_out_arb;
|
||||
logic [NUM_FB-1:0] fill_rvd_arb;
|
||||
logic [NUM_FB-1:0] fill_entry_en;
|
||||
logic [NUM_FB-1:0] fill_addr_en;
|
||||
logic [NUM_FB-1:0] fill_way_en;
|
||||
logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_data_en;
|
||||
logic [NUM_FB-1:0][IC_LINE_BEATS-1:0] fill_err_d, fill_err_q;
|
||||
logic [ADDR_W-1:0] fill_addr_q [NUM_FB];
|
||||
logic [IC_NUM_WAYS-1:0] fill_way_q [NUM_FB];
|
||||
logic [IC_LINE_SIZE-1:0] fill_data_d [NUM_FB];
|
||||
logic [IC_LINE_SIZE-1:0] fill_data_q [NUM_FB];
|
||||
logic [ADDR_W-1:BUS_W] fill_ext_req_addr;
|
||||
logic [ADDR_W-1:0] fill_ram_req_addr;
|
||||
logic [IC_NUM_WAYS-1:0] fill_ram_req_way;
|
||||
logic [IC_LINE_SIZE-1:0] fill_ram_req_data;
|
||||
logic [IC_LINE_SIZE-1:0] fill_out_data;
|
||||
logic [IC_LINE_BEATS-1:0] fill_out_err;
|
||||
// External req signals
|
||||
logic instr_req;
|
||||
logic [ADDR_W-1:BUS_W] instr_addr;
|
||||
logic instr_req;
|
||||
logic [ADDR_W-1:BUS_W] instr_addr;
|
||||
// Data output signals
|
||||
logic skid_complete_instr;
|
||||
logic skid_ready;
|
||||
logic output_compressed;
|
||||
logic skid_valid_d, skid_valid_q, skid_en;
|
||||
logic [15:0] skid_data_d, skid_data_q;
|
||||
logic skid_err_q;
|
||||
logic output_valid;
|
||||
logic addr_incr_two;
|
||||
logic output_addr_en;
|
||||
logic [ADDR_W-1:1] output_addr_incr;
|
||||
logic [ADDR_W-1:1] output_addr_d, output_addr_q;
|
||||
logic [15:0] output_data_lo, output_data_hi;
|
||||
logic data_valid, output_ready;
|
||||
logic [LineSize-1:0] line_data;
|
||||
logic [LINE_BEATS-1:0] line_err;
|
||||
logic [31:0] line_data_muxed;
|
||||
logic line_err_muxed;
|
||||
logic [31:0] output_data;
|
||||
logic output_err;
|
||||
logic skid_complete_instr;
|
||||
logic skid_ready;
|
||||
logic output_compressed;
|
||||
logic skid_valid_d, skid_valid_q, skid_en;
|
||||
logic [15:0] skid_data_d, skid_data_q;
|
||||
logic skid_err_q;
|
||||
logic output_valid;
|
||||
logic addr_incr_two;
|
||||
logic output_addr_en;
|
||||
logic [ADDR_W-1:1] output_addr_incr;
|
||||
logic [ADDR_W-1:1] output_addr_d, output_addr_q;
|
||||
logic [15:0] output_data_lo, output_data_hi;
|
||||
logic data_valid, output_ready;
|
||||
logic [IC_LINE_SIZE-1:0] line_data;
|
||||
logic [IC_LINE_BEATS-1:0] line_err;
|
||||
logic [31:0] line_data_muxed;
|
||||
logic line_err_muxed;
|
||||
logic [31:0] output_data;
|
||||
logic output_err;
|
||||
// Invalidations
|
||||
logic start_inval, inval_done;
|
||||
logic reset_inval_q;
|
||||
logic inval_prog_d, inval_prog_q;
|
||||
logic [INDEX_W-1:0] inval_index_d, inval_index_q;
|
||||
logic start_inval, inval_done;
|
||||
logic reset_inval_q;
|
||||
logic inval_prog_d, inval_prog_q;
|
||||
logic [IC_INDEX_W-1:0] inval_index_d, inval_index_q;
|
||||
|
||||
//////////////////////////
|
||||
// Instruction prefetch //
|
||||
|
@ -230,7 +215,7 @@ module ibex_icache #(
|
|||
|
||||
assign branch_or_mispredict = branch_i | branch_mispredict_i;
|
||||
|
||||
assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:LINE_W],{LINE_W{1'b0}}};
|
||||
assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W-1:IC_LINE_W], {IC_LINE_W{1'b0}}};
|
||||
|
||||
// The prefetch address increments by one cache line for each granted request.
|
||||
// This address is also updated if there is a branch that is not granted, since the target
|
||||
|
@ -239,7 +224,8 @@ module ibex_icache #(
|
|||
// The captured branch target address is not forced to be aligned since the offset in the cache
|
||||
// line must also be recorded for later use by the fill buffers.
|
||||
assign prefetch_addr_d =
|
||||
lookup_grant_ic0 ? (lookup_addr_aligned + {{ADDR_W-LINE_W-1{1'b0}},1'b1,{LINE_W{1'b0}}}) :
|
||||
lookup_grant_ic0 ? (lookup_addr_aligned +
|
||||
{{ADDR_W-IC_LINE_W-1{1'b0}}, 1'b1, {IC_LINE_W{1'b0}}}) :
|
||||
branch_i ? addr_i :
|
||||
branch_mispredict_addr;
|
||||
|
||||
|
@ -263,12 +249,13 @@ module ibex_icache #(
|
|||
assign lookup_addr_ic0 = branch_spec_i ? addr_i :
|
||||
branch_mispredict_i ? branch_mispredict_addr :
|
||||
prefetch_addr_q;
|
||||
assign lookup_index_ic0 = lookup_addr_ic0[INDEX_HI:LINE_W];
|
||||
assign lookup_index_ic0 = lookup_addr_ic0[IC_INDEX_HI:IC_LINE_W];
|
||||
|
||||
// Cache write
|
||||
assign fill_req_ic0 = (|fill_ram_req);
|
||||
assign fill_index_ic0 = fill_ram_req_addr[INDEX_HI:LINE_W];
|
||||
assign fill_tag_ic0 = {(~inval_prog_q & ~ecc_write_req),fill_ram_req_addr[ADDR_W-1:INDEX_HI+1]};
|
||||
assign fill_index_ic0 = fill_ram_req_addr[IC_INDEX_HI:IC_LINE_W];
|
||||
assign fill_tag_ic0 = {(~inval_prog_q & ~ecc_write_req),
|
||||
fill_ram_req_addr[ADDR_W-1:IC_INDEX_HI+1]};
|
||||
assign fill_wdata_ic0 = fill_ram_req_data;
|
||||
|
||||
// Suppress a new lookup on a not-taken branch (as the address will be incorrect)
|
||||
|
@ -289,7 +276,7 @@ module ibex_icache #(
|
|||
lookup_index_ic0;
|
||||
assign tag_banks_ic0 = ecc_write_req ? ecc_write_ways :
|
||||
fill_grant_ic0 ? fill_ram_req_way :
|
||||
{NumWays{1'b1}};
|
||||
{IC_NUM_WAYS{1'b1}};
|
||||
assign tag_write_ic0 = fill_grant_ic0 | inval_prog_q | ecc_write_req;
|
||||
|
||||
// Dataram
|
||||
|
@ -303,24 +290,24 @@ module ibex_icache #(
|
|||
|
||||
// Tagram ECC
|
||||
// Reuse the same ecc encoding module for larger cache sizes by padding with zeros
|
||||
logic [21:0] tag_ecc_input_padded;
|
||||
logic [27:0] tag_ecc_output_padded;
|
||||
logic [22-TAG_SIZE:0] tag_ecc_output_unused;
|
||||
logic [21:0] tag_ecc_input_padded;
|
||||
logic [27:0] tag_ecc_output_padded;
|
||||
logic [22-IC_TAG_SIZE:0] tag_ecc_output_unused;
|
||||
|
||||
assign tag_ecc_input_padded = {{22-TAG_SIZE{1'b0}},fill_tag_ic0};
|
||||
assign tag_ecc_output_unused = tag_ecc_output_padded[21:TAG_SIZE-1];
|
||||
assign tag_ecc_input_padded = {{22-IC_TAG_SIZE{1'b0}},fill_tag_ic0};
|
||||
assign tag_ecc_output_unused = tag_ecc_output_padded[21:IC_TAG_SIZE-1];
|
||||
|
||||
prim_secded_28_22_enc tag_ecc_enc (
|
||||
.in (tag_ecc_input_padded),
|
||||
.out (tag_ecc_output_padded)
|
||||
);
|
||||
|
||||
assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[TAG_SIZE-1:0]};
|
||||
assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22],tag_ecc_output_padded[IC_TAG_SIZE-1:0]};
|
||||
|
||||
// Dataram ECC
|
||||
for (genvar bank = 0; bank < LINE_BEATS; bank ++) begin : gen_ecc_banks
|
||||
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
|
||||
prim_secded_39_32_enc data_ecc_enc (
|
||||
.in (fill_wdata_ic0[bank*BusWidth+:BusWidth]),
|
||||
.in (fill_wdata_ic0[bank*BUS_WIDTH+:BUS_WIDTH]),
|
||||
.out (data_wdata_ic0[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC])
|
||||
);
|
||||
end
|
||||
|
@ -334,11 +321,11 @@ module ibex_icache #(
|
|||
// IC0 -> IC1 //
|
||||
////////////////
|
||||
|
||||
for (genvar way = 0; way < NumWays; way++) begin : gen_rams
|
||||
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams
|
||||
// Tag RAM instantiation
|
||||
prim_ram_1p #(
|
||||
.Width (TAG_SIZE_ECC),
|
||||
.Depth (NUM_LINES),
|
||||
.Depth (IC_NUM_LINES),
|
||||
.DataBitsPerMask (TAG_SIZE_ECC)
|
||||
) tag_bank (
|
||||
.clk_i (clk_i),
|
||||
|
@ -353,7 +340,7 @@ module ibex_icache #(
|
|||
// Data RAM instantiation
|
||||
prim_ram_1p #(
|
||||
.Width (LINE_SIZE_ECC),
|
||||
.Depth (NUM_LINES),
|
||||
.Depth (IC_NUM_LINES),
|
||||
.DataBitsPerMask (LINE_SIZE_ECC)
|
||||
) data_bank (
|
||||
.clk_i (clk_i),
|
||||
|
@ -377,7 +364,7 @@ module ibex_icache #(
|
|||
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (lookup_grant_ic0) begin
|
||||
lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:INDEX_HI+1];
|
||||
lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W-1:IC_INDEX_HI+1];
|
||||
fill_in_ic1 <= fill_alloc_sel;
|
||||
end
|
||||
end
|
||||
|
@ -387,10 +374,10 @@ module ibex_icache #(
|
|||
////////////////////////
|
||||
|
||||
// Tag matching
|
||||
for (genvar way = 0; way < NumWays; way++) begin : gen_tag_match
|
||||
assign tag_match_ic1[way] = (tag_rdata_ic1[way][TAG_SIZE-1:0] ==
|
||||
{1'b1,lookup_addr_ic1[ADDR_W-1:INDEX_HI+1]});
|
||||
assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][TAG_SIZE-1];
|
||||
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_match
|
||||
assign tag_match_ic1[way] = (tag_rdata_ic1[way][IC_TAG_SIZE-1:0] ==
|
||||
{1'b1,lookup_addr_ic1[ADDR_W-1:IC_INDEX_HI+1]});
|
||||
assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][IC_TAG_SIZE-1];
|
||||
end
|
||||
|
||||
assign tag_hit_ic1 = |tag_match_ic1;
|
||||
|
@ -398,7 +385,7 @@ module ibex_icache #(
|
|||
// Hit data mux
|
||||
always_comb begin
|
||||
hit_data_ecc_ic1 = 'b0;
|
||||
for (int way = 0; way < NumWays; way++) begin
|
||||
for (int way = 0; way < IC_NUM_WAYS; way++) begin
|
||||
if (tag_match_ic1[way]) begin
|
||||
hit_data_ecc_ic1 |= data_rdata_ic1[way];
|
||||
end
|
||||
|
@ -409,15 +396,15 @@ module ibex_icache #(
|
|||
// 1 first invalid way
|
||||
// 2 global round-robin (pseudorandom) way
|
||||
assign lowest_invalid_way_ic1[0] = tag_invalid_ic1[0];
|
||||
assign round_robin_way_ic1[0] = round_robin_way_q[NumWays-1];
|
||||
for (genvar way = 1; way < NumWays; way++) begin : gen_lowest_way
|
||||
assign round_robin_way_ic1[0] = round_robin_way_q[IC_NUM_WAYS-1];
|
||||
for (genvar way = 1; way < IC_NUM_WAYS; way++) begin : gen_lowest_way
|
||||
assign lowest_invalid_way_ic1[way] = tag_invalid_ic1[way] & ~|tag_invalid_ic1[way-1:0];
|
||||
assign round_robin_way_ic1[way] = round_robin_way_q[way-1];
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
round_robin_way_q <= {{NumWays-1{1'b0}},1'b1};
|
||||
round_robin_way_q <= {{IC_NUM_WAYS-1{1'b0}}, 1'b1};
|
||||
end else if (lookup_valid_ic1) begin
|
||||
round_robin_way_q <= round_robin_way_ic1;
|
||||
end
|
||||
|
@ -428,21 +415,21 @@ module ibex_icache #(
|
|||
|
||||
// ECC checking logic
|
||||
if (ICacheECC) begin : gen_data_ecc_checking
|
||||
logic [NumWays-1:0] tag_err_ic1;
|
||||
logic [LINE_BEATS*2-1:0] data_err_ic1;
|
||||
logic ecc_correction_write_d, ecc_correction_write_q;
|
||||
logic [NumWays-1:0] ecc_correction_ways_d, ecc_correction_ways_q;
|
||||
logic [INDEX_W-1:0] lookup_index_ic1, ecc_correction_index_q;
|
||||
logic [IC_NUM_WAYS-1:0] tag_err_ic1;
|
||||
logic [IC_LINE_BEATS*2-1:0] data_err_ic1;
|
||||
logic ecc_correction_write_d, ecc_correction_write_q;
|
||||
logic [IC_NUM_WAYS-1:0] ecc_correction_ways_d, ecc_correction_ways_q;
|
||||
logic [IC_INDEX_W-1:0] lookup_index_ic1, ecc_correction_index_q;
|
||||
|
||||
// Tag ECC checking
|
||||
for (genvar way = 0; way < NumWays; way++) begin : gen_tag_ecc
|
||||
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_tag_ecc
|
||||
logic [1:0] tag_err_bank_ic1;
|
||||
logic [27:0] tag_rdata_padded_ic1;
|
||||
|
||||
// Expand the tag rdata with extra padding if the tag size is less than the maximum
|
||||
assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TAG_SIZE_ECC-1-:6],
|
||||
{22-TAG_SIZE{1'b0}},
|
||||
tag_rdata_ic1[way][TAG_SIZE-1:0]};
|
||||
{22-IC_TAG_SIZE{1'b0}},
|
||||
tag_rdata_ic1[way][IC_TAG_SIZE-1:0]};
|
||||
|
||||
prim_secded_28_22_dec data_ecc_dec (
|
||||
.in (tag_rdata_padded_ic1),
|
||||
|
@ -455,7 +442,7 @@ module ibex_icache #(
|
|||
|
||||
// Data ECC checking
|
||||
// Note - could generate for all ways and mux after
|
||||
for (genvar bank = 0; bank < LINE_BEATS; bank++) begin : gen_ecc_banks
|
||||
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
|
||||
prim_secded_39_32_dec data_ecc_dec (
|
||||
.in (hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC]),
|
||||
.d_o (),
|
||||
|
@ -463,7 +450,8 @@ module ibex_icache #(
|
|||
.err_o (data_err_ic1[bank*2+:2])
|
||||
);
|
||||
|
||||
assign hit_data_ic1[bank*BusWidth+:BusWidth] = hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BusWidth];
|
||||
assign hit_data_ic1[bank*BUS_WIDTH+:BUS_WIDTH] =
|
||||
hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BUS_WIDTH];
|
||||
|
||||
end
|
||||
|
||||
|
@ -473,8 +461,8 @@ module ibex_icache #(
|
|||
// All ways will be invalidated on a tag error to prevent X-propagation from data_err_ic1 on
|
||||
// spurious hits. Also prevents the same line being allocated twice when there was a true
|
||||
// hit and a spurious hit.
|
||||
assign ecc_correction_ways_d = {NumWays{|tag_err_ic1}} |
|
||||
(tag_match_ic1 & {NumWays{|data_err_ic1}});
|
||||
assign ecc_correction_ways_d = {IC_NUM_WAYS{|tag_err_ic1}} |
|
||||
(tag_match_ic1 & {IC_NUM_WAYS{|data_err_ic1}});
|
||||
assign ecc_correction_write_d = ecc_err_ic1;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
|
@ -488,7 +476,7 @@ module ibex_icache #(
|
|||
// The index is required in IC1 only when ECC is configured so is registered here
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (lookup_grant_ic0) begin
|
||||
lookup_index_ic1 <= lookup_addr_ic0[INDEX_HI-:INDEX_W];
|
||||
lookup_index_ic1 <= lookup_addr_ic0[IC_INDEX_HI-:IC_INDEX_W];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -620,17 +608,17 @@ module ibex_icache #(
|
|||
// Make an external request
|
||||
assign fill_ext_req[fb] = fill_busy_q[fb] & ~fill_ext_done_d[fb];
|
||||
|
||||
// Count the number of completed external requests (each line requires LINE_BEATS requests)
|
||||
// Count the number of completed external requests (each line requires IC_LINE_BEATS requests)
|
||||
// Don't count fake PMP error grants here since they will never receive an rvalid response
|
||||
assign fill_ext_cnt_d[fb] = fill_alloc[fb] ?
|
||||
{{LINE_BEATS_W{1'b0}},fill_spec_done} :
|
||||
(fill_ext_cnt_q[fb] + {{LINE_BEATS_W{1'b0}},
|
||||
{{IC_LINE_BEATS_W{1'b0}},fill_spec_done} :
|
||||
(fill_ext_cnt_q[fb] + {{IC_LINE_BEATS_W{1'b0}},
|
||||
fill_ext_arb[fb] & gnt_not_pmp_err});
|
||||
// External request must be held until granted
|
||||
assign fill_ext_hold_d[fb] = (fill_alloc[fb] & fill_spec_hold) |
|
||||
(fill_ext_arb[fb] & ~gnt_or_pmp_err);
|
||||
// External requests are completed when the counter is filled or when the request is cancelled
|
||||
assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][LINE_BEATS_W] |
|
||||
assign fill_ext_done_d[fb] = (fill_ext_cnt_q[fb][IC_LINE_BEATS_W] |
|
||||
// external requests are considered complete if the request hit
|
||||
fill_hit_ic1[fb] | fill_hit_q[fb] |
|
||||
// external requests will stop once any PMP error is received
|
||||
|
@ -638,7 +626,7 @@ module ibex_icache #(
|
|||
// cancel if the line won't be cached and, it is stale
|
||||
(~fill_cache_q[fb] & (branch_or_mispredict | fill_stale_q[fb] |
|
||||
// or we're already at the end of the line
|
||||
fill_ext_beat[fb][LINE_BEATS_W]))) &
|
||||
fill_ext_beat[fb][IC_LINE_BEATS_W]))) &
|
||||
// can't cancel while we are waiting for a grant on the bus
|
||||
~fill_ext_hold_q[fb] & fill_busy_q[fb];
|
||||
// Track whether this fill buffer expects to receive beats of data
|
||||
|
@ -646,7 +634,7 @@ module ibex_icache #(
|
|||
// Count the number of rvalid beats received
|
||||
assign fill_rvd_cnt_d[fb] = fill_alloc[fb] ? '0 :
|
||||
(fill_rvd_cnt_q[fb] +
|
||||
{{LINE_BEATS_W{1'b0}},fill_rvd_arb[fb]});
|
||||
{{IC_LINE_BEATS_W{1'b0}},fill_rvd_arb[fb]});
|
||||
// External data is complete when all issued external requests have received their data
|
||||
assign fill_rvd_done[fb] = (fill_ext_done_q[fb] & ~fill_ext_hold_q[fb]) &
|
||||
(fill_rvd_cnt_q[fb] == fill_ext_cnt_q[fb]);
|
||||
|
@ -664,25 +652,25 @@ module ibex_icache #(
|
|||
// - Data is available from the bus this cycle (fill_rvd_arb)
|
||||
assign fill_out_req[fb] = fill_busy_q[fb] & ~fill_stale_q[fb] & ~fill_out_done[fb] &
|
||||
(fill_hit_ic1[fb] | fill_hit_q[fb] |
|
||||
(fill_err_q[fb][fill_out_cnt_q[fb][LINE_BEATS_W-1:0]]) |
|
||||
(fill_err_q[fb][fill_out_cnt_q[fb][IC_LINE_BEATS_W-1:0]]) |
|
||||
(fill_rvd_beat[fb] > fill_out_cnt_q[fb]) | fill_rvd_arb[fb]);
|
||||
|
||||
// Calculate when a beat of data is output. Any ECC error squashes the output that cycle.
|
||||
assign fill_out_grant[fb] = fill_out_arb[fb] & output_ready;
|
||||
|
||||
// Count the beats of data output to the IF stage
|
||||
assign fill_out_cnt_d[fb] = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[LINE_W-1:BUS_W]} :
|
||||
assign fill_out_cnt_d[fb] = fill_alloc[fb] ? {1'b0,lookup_addr_ic0[IC_LINE_W-1:BUS_W]} :
|
||||
(fill_out_cnt_q[fb] +
|
||||
{{LINE_BEATS_W{1'b0}},fill_out_grant[fb]});
|
||||
{{IC_LINE_BEATS_W{1'b0}},fill_out_grant[fb]});
|
||||
// Data output complete when the counter fills
|
||||
assign fill_out_done[fb] = fill_out_cnt_q[fb][LINE_BEATS_W];
|
||||
assign fill_out_done[fb] = fill_out_cnt_q[fb][IC_LINE_BEATS_W];
|
||||
|
||||
//////////////////////////////////////
|
||||
// Fill buffer ram request tracking //
|
||||
//////////////////////////////////////
|
||||
|
||||
// make a fill request once all data beats received
|
||||
assign fill_ram_req[fb] = fill_busy_q[fb] & fill_rvd_cnt_q[fb][LINE_BEATS_W] &
|
||||
assign fill_ram_req[fb] = fill_busy_q[fb] & fill_rvd_cnt_q[fb][IC_LINE_BEATS_W] &
|
||||
// unless the request hit, was non-allocating or got an error
|
||||
~fill_hit_q[fb] & fill_cache_q[fb] & ~|fill_err_q[fb] &
|
||||
// or the request was already completed
|
||||
|
@ -697,12 +685,12 @@ module ibex_icache #(
|
|||
|
||||
// When we branch into the middle of a line, the output count will not start from zero. This
|
||||
// beat count is used to know which incoming rdata beats are relevant.
|
||||
assign fill_ext_beat[fb] = {1'b0,fill_addr_q[fb][LINE_W-1:BUS_W]} +
|
||||
fill_ext_cnt_q[fb][LINE_BEATS_W:0];
|
||||
assign fill_ext_off[fb] = fill_ext_beat[fb][LINE_BEATS_W-1:0];
|
||||
assign fill_rvd_beat[fb] = {1'b0,fill_addr_q[fb][LINE_W-1:BUS_W]} +
|
||||
fill_rvd_cnt_q[fb][LINE_BEATS_W:0];
|
||||
assign fill_rvd_off[fb] = fill_rvd_beat[fb][LINE_BEATS_W-1:0];
|
||||
assign fill_ext_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} +
|
||||
fill_ext_cnt_q[fb][IC_LINE_BEATS_W:0];
|
||||
assign fill_ext_off[fb] = fill_ext_beat[fb][IC_LINE_BEATS_W-1:0];
|
||||
assign fill_rvd_beat[fb] = {1'b0,fill_addr_q[fb][IC_LINE_W-1:BUS_W]} +
|
||||
fill_rvd_cnt_q[fb][IC_LINE_BEATS_W:0];
|
||||
assign fill_rvd_off[fb] = fill_rvd_beat[fb][IC_LINE_BEATS_W-1:0];
|
||||
|
||||
/////////////////////////////
|
||||
// Fill buffer arbitration //
|
||||
|
@ -796,19 +784,20 @@ module ibex_icache #(
|
|||
// Data either comes from the cache or the bus. If there was an ECC error, we must take
|
||||
// the incoming bus data since the cache hit data is corrupted.
|
||||
assign fill_data_d[fb] = fill_hit_ic1[fb] ? hit_data_ic1 :
|
||||
{LINE_BEATS{instr_rdata_i}};
|
||||
{IC_LINE_BEATS{instr_rdata_i}};
|
||||
|
||||
for (genvar b = 0; b < LINE_BEATS; b++) begin : gen_data_buf
|
||||
for (genvar b = 0; b < IC_LINE_BEATS; b++) begin : gen_data_buf
|
||||
// Error tracking (per beat)
|
||||
// Either a PMP error on a speculative request,
|
||||
assign fill_err_d[fb][b] = (instr_pmp_err_i & fill_alloc[fb] & fill_spec_req &
|
||||
(lookup_addr_ic0[LINE_W-1:BUS_W] == b[LINE_BEATS_W-1:0])) |
|
||||
(lookup_addr_ic0[IC_LINE_W-1:BUS_W] ==
|
||||
b[IC_LINE_BEATS_W-1:0])) |
|
||||
// a PMP error on a fill buffer ext req
|
||||
(instr_pmp_err_i & fill_ext_arb[fb] &
|
||||
(fill_ext_off[fb] == b[LINE_BEATS_W-1:0])) |
|
||||
(fill_ext_off[fb] == b[IC_LINE_BEATS_W-1:0])) |
|
||||
// Or a data error with instr_rvalid_i
|
||||
(fill_rvd_arb[fb] & instr_err_i &
|
||||
(fill_rvd_off[fb] == b[LINE_BEATS_W-1:0])) |
|
||||
(fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0])) |
|
||||
// Hold the error once recorded
|
||||
(fill_busy_q[fb] & fill_err_q[fb][b]);
|
||||
|
||||
|
@ -824,11 +813,11 @@ module ibex_icache #(
|
|||
// Ignore incoming rvalid data when we already have cache hit data
|
||||
assign fill_data_en[fb][b] = fill_hit_ic1[fb] |
|
||||
(fill_rvd_arb[fb] & ~fill_hit_q[fb] &
|
||||
(fill_rvd_off[fb] == b[LINE_BEATS_W-1:0]));
|
||||
(fill_rvd_off[fb] == b[IC_LINE_BEATS_W-1:0]));
|
||||
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (fill_data_en[fb][b]) begin
|
||||
fill_data_q[fb][b*BusWidth+:BusWidth] <= fill_data_d[fb][b*BusWidth+:BusWidth];
|
||||
fill_data_q[fb][b*BUS_WIDTH+:BUS_WIDTH] <= fill_data_d[fb][b*BUS_WIDTH+:BUS_WIDTH];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -844,7 +833,7 @@ module ibex_icache #(
|
|||
fill_ext_req_addr = '0;
|
||||
for (int i = 0; i < NUM_FB; i++) begin
|
||||
if (fill_ext_arb[i]) begin
|
||||
fill_ext_req_addr |= {fill_addr_q[i][ADDR_W-1:LINE_W], fill_ext_off[i]};
|
||||
fill_ext_req_addr |= {fill_addr_q[i][ADDR_W-1:IC_LINE_W], fill_ext_off[i]};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -871,7 +860,7 @@ module ibex_icache #(
|
|||
if (fill_data_reg[i]) begin
|
||||
fill_out_data |= fill_data_q[i];
|
||||
// Ignore any speculative errors accumulated on cache hits
|
||||
fill_out_err |= (fill_err_q[i] & ~{LINE_BEATS{fill_hit_q[i]}});
|
||||
fill_out_err |= (fill_err_q[i] & ~{IC_LINE_BEATS{fill_hit_q[i]}});
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -895,16 +884,16 @@ module ibex_icache #(
|
|||
|
||||
// Mux between line-width data sources
|
||||
assign line_data = |fill_data_hit ? hit_data_ic1 : fill_out_data;
|
||||
assign line_err = |fill_data_hit ? {LINE_BEATS{1'b0}} : fill_out_err;
|
||||
assign line_err = |fill_data_hit ? {IC_LINE_BEATS{1'b0}} : fill_out_err;
|
||||
|
||||
// Mux the relevant beat of line data, based on the output address
|
||||
always_comb begin
|
||||
line_data_muxed = '0;
|
||||
line_err_muxed = 1'b0;
|
||||
for (int i = 0; i < LINE_BEATS; i++) begin
|
||||
for (int i = 0; i < IC_LINE_BEATS; i++) begin
|
||||
// When data has been skidded, the output address is behind by one
|
||||
if ((output_addr_q[LINE_W-1:BUS_W] + {{LINE_BEATS_W-1{1'b0}},skid_valid_q}) ==
|
||||
i[LINE_BEATS_W-1:0]) begin
|
||||
if ((output_addr_q[IC_LINE_W-1:BUS_W] + {{IC_LINE_BEATS_W-1{1'b0}},skid_valid_q}) ==
|
||||
i[IC_LINE_BEATS_W-1:0]) begin
|
||||
line_data_muxed |= line_data[i*32+:32];
|
||||
line_err_muxed |= line_err[i];
|
||||
end
|
||||
|
@ -994,14 +983,14 @@ module ibex_icache #(
|
|||
end
|
||||
end
|
||||
|
||||
// Mux the data from BusWidth to halfword
|
||||
// Mux the data from BUS_WIDTH to halfword
|
||||
// This muxing realigns data when instruction words are split across BUS_W e.g.
|
||||
// word 1 |----|*h1*|
|
||||
// word 0 |*h0*|----| --> |*h1*|*h0*|
|
||||
// 31 15 0 31 15 0
|
||||
always_comb begin
|
||||
output_data_lo = '0;
|
||||
for (int i = 0; i < OUTPUT_BEATS; i++) begin
|
||||
for (int i = 0; i < IC_OUTPUT_BEATS; i++) begin
|
||||
if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin
|
||||
output_data_lo |= output_data[i*16+:16];
|
||||
end
|
||||
|
@ -1010,7 +999,7 @@ module ibex_icache #(
|
|||
|
||||
always_comb begin
|
||||
output_data_hi = '0;
|
||||
for (int i = 0; i < OUTPUT_BEATS-1; i++) begin
|
||||
for (int i = 0; i < IC_OUTPUT_BEATS-1; i++) begin
|
||||
if (output_addr_q[BUS_W-1:1] == i[BUS_W-2:0]) begin
|
||||
output_data_hi |= output_data[(i+1)*16+:16];
|
||||
end
|
||||
|
@ -1038,7 +1027,7 @@ module ibex_icache #(
|
|||
assign inval_prog_d = start_inval | (inval_prog_q & ~inval_done);
|
||||
assign inval_done = &inval_index_q;
|
||||
assign inval_index_d = start_inval ? '0 :
|
||||
(inval_index_q + {{INDEX_W-1{1'b0}},1'b1});
|
||||
(inval_index_q + {{IC_INDEX_W-1{1'b0}},1'b1});
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
|
@ -1068,11 +1057,11 @@ module ibex_icache #(
|
|||
// Assertions //
|
||||
////////////////
|
||||
|
||||
`ASSERT_INIT(size_param_legal, (LineSize > 32))
|
||||
`ASSERT_INIT(size_param_legal, (IC_LINE_SIZE > 32))
|
||||
|
||||
// ECC primitives will need to be changed for different sizes
|
||||
`ASSERT_INIT(ecc_tag_param_legal, (TAG_SIZE <= 27))
|
||||
`ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BusWidth == 32))
|
||||
`ASSERT_INIT(ecc_tag_param_legal, (IC_TAG_SIZE <= 27))
|
||||
`ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_WIDTH == 32))
|
||||
|
||||
// Lookups in the tag ram should always give a known result
|
||||
`ASSERT_KNOWN(TagHitKnown, lookup_valid_ic1 & tag_hit_ic1)
|
||||
|
|
|
@ -311,6 +311,24 @@ typedef enum logic [2:0] {
|
|||
DBG_CAUSE_STEP = 3'h4
|
||||
} dbg_cause_e;
|
||||
|
||||
// ICache constants
|
||||
parameter int unsigned ADDR_W = 32;
|
||||
parameter int unsigned BUS_SIZE = 32;
|
||||
parameter int unsigned BUS_BYTES = BUS_SIZE/8;
|
||||
parameter int unsigned BUS_W = $clog2(BUS_BYTES);
|
||||
parameter int unsigned IC_SIZE_BYTES = 4096;
|
||||
parameter int unsigned IC_NUM_WAYS = 2;
|
||||
parameter int unsigned IC_LINE_SIZE = 64;
|
||||
parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8;
|
||||
parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES);
|
||||
parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES;
|
||||
parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES;
|
||||
parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS);
|
||||
parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES);
|
||||
parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1;
|
||||
parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit
|
||||
parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords
|
||||
|
||||
// PMP constants
|
||||
parameter int unsigned PMP_MAX_REGIONS = 16;
|
||||
parameter int unsigned PMP_CFG_W = 8;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue