diff --git a/doc/03_reference/load_store_unit.rst b/doc/03_reference/load_store_unit.rst index a169298e..0898fc11 100644 --- a/doc/03_reference/load_store_unit.rst +++ b/doc/03_reference/load_store_unit.rst @@ -58,7 +58,7 @@ Bus Integrity Checking ---------------------- The core can optionally generate and verify check bits sent alongside the data for memory accesses. -Checkbits are generated and checked using a 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_enc.sv`). +Checkbits are generated and checked using an inverted 39/32 Hsaio code (see :file:`vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv`). When this feature is used, any mismatch in checkbits will generate a major alert. This feature is only used if the core is configured with the SecureIbex parameter set. diff --git a/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_response_seq_lib.sv b/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_response_seq_lib.sv index 91463238..fbf0c380 100644 --- a/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_response_seq_lib.sv +++ b/dv/uvm/core_ibex/common/ibex_mem_intf_agent/ibex_mem_intf_response_seq_lib.sv @@ -72,7 +72,7 @@ class ibex_mem_intf_response_seq extends uvm_sequence #(ibex_mem_intf_seq_item); end end // Add correct integrity bits - {req.intg, req.data} = prim_secded_pkg::prim_secded_39_32_enc(req.data); + {req.intg, req.data} = prim_secded_pkg::prim_secded_inv_39_32_enc(req.data); `uvm_info(get_full_name(), $sformatf("Response transfer:\n%0s", req.sprint()), UVM_HIGH) start_item(req); finish_item(req); diff --git a/dv/uvm/core_ibex/ibex_dv.f b/dv/uvm/core_ibex/ibex_dv.f index c3dc7aa7..31ed8519 100644 --- a/dv/uvm/core_ibex/ibex_dv.f +++ b/dv/uvm/core_ibex/ibex_dv.f @@ -18,12 +18,12 @@ ${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_assert.sv ${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_cipher_pkg.sv ${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_lfsr.sv -${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_28_22_enc.sv -${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_28_22_dec.sv -${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_enc.sv -${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_dec.sv -${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_72_64_enc.sv -${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_72_64_dec.sv +${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_28_22_enc.sv +${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_28_22_dec.sv +${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv +${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_dec.sv +${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_72_64_enc.sv +${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_72_64_dec.sv // Until this list is generated by FuseSoC, we have to use manually generated // wrappers around the prim_* modules to instantiate the prim_generic_* ones, diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index 13dc144e..aae6dad6 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -779,19 +779,19 @@ module ibex_core import ibex_pkg::*; #( logic rf_ecc_err_a_id, rf_ecc_err_b_id; // ECC checkbit generation for regiter file wdata - prim_secded_39_32_enc regfile_ecc_enc ( + prim_secded_inv_39_32_enc regfile_ecc_enc ( .data_i(rf_wdata_wb), .data_o(rf_wdata_wb_ecc_o) ); // ECC checking on register file rdata - prim_secded_39_32_dec regfile_ecc_dec_a ( + prim_secded_inv_39_32_dec regfile_ecc_dec_a ( .data_i (rf_rdata_a_ecc_i), .data_o (), .syndrome_o(), .err_o (rf_ecc_err_a) ); - prim_secded_39_32_dec regfile_ecc_dec_b ( + prim_secded_inv_39_32_dec regfile_ecc_dec_b ( .data_i (rf_rdata_b_ecc_i), .data_o (), .syndrome_o(), diff --git a/rtl/ibex_icache.sv b/rtl/ibex_icache.sv index bb3716c7..b1c20c7f 100644 --- a/rtl/ibex_icache.sv +++ b/rtl/ibex_icache.sv @@ -290,7 +290,7 @@ module ibex_icache import ibex_pkg::*; #( 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 ( + prim_secded_inv_28_22_enc tag_ecc_enc ( .data_i (tag_ecc_input_padded), .data_o (tag_ecc_output_padded) ); @@ -299,7 +299,7 @@ module ibex_icache import ibex_pkg::*; #( // Dataram ECC for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_39_32_enc data_ecc_enc ( + prim_secded_inv_39_32_enc data_ecc_enc ( .data_i (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]), .data_o (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC]) ); @@ -421,7 +421,7 @@ module ibex_icache import ibex_pkg::*; #( {22-IC_TAG_SIZE{1'b0}}, tag_rdata_ic1[way][IC_TAG_SIZE-1:0]}; - prim_secded_28_22_dec data_ecc_dec ( + prim_secded_inv_28_22_dec data_ecc_dec ( .data_i (tag_rdata_padded_ic1), .data_o (), .syndrome_o (), @@ -433,7 +433,7 @@ module ibex_icache import ibex_pkg::*; #( // Data ECC checking // Note - could generate for all ways and mux after for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks - prim_secded_39_32_dec data_ecc_dec ( + prim_secded_inv_39_32_dec data_ecc_dec ( .data_i (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]), .data_o (), .syndrome_o (), diff --git a/rtl/ibex_lockstep.sv b/rtl/ibex_lockstep.sv index c42ef7c8..3d1e20f0 100644 --- a/rtl/ibex_lockstep.sv +++ b/rtl/ibex_lockstep.sv @@ -216,14 +216,14 @@ module ibex_lockstep import ibex_pkg::*; #( logic [31:0] unused_wdata; // Checks on incoming data - prim_secded_39_32_dec u_instr_intg_dec ( + prim_secded_inv_39_32_dec u_instr_intg_dec ( .data_i ({instr_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].instr_rdata}), .data_o (), .syndrome_o (), .err_o (instr_intg_err) ); - prim_secded_39_32_dec u_data_intg_dec ( + prim_secded_inv_39_32_dec u_data_intg_dec ( .data_i ({data_rdata_intg_q, shadow_inputs_q[LockstepOffset-1].data_rdata}), .data_o (), .syndrome_o (), @@ -234,7 +234,7 @@ module ibex_lockstep import ibex_pkg::*; #( (shadow_inputs_q[LockstepOffset-1].data_rvalid & |data_intg_err); // Generate integrity bits - prim_secded_39_32_enc u_data_gen ( + prim_secded_inv_39_32_enc u_data_gen ( .data_i (data_wdata_i), .data_o ({data_wdata_intg_o, unused_wdata}) ); diff --git a/rtl/ibex_register_file_ff.sv b/rtl/ibex_register_file_ff.sv index a2c03bea..0cd5e6f0 100644 --- a/rtl/ibex_register_file_ff.sv +++ b/rtl/ibex_register_file_ff.sv @@ -11,9 +11,10 @@ * targeting FPGA synthesis or Verilator simulation. */ module ibex_register_file_ff #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0 + parameter bit RV32E = 0, + parameter int unsigned DataWidth = 32, + parameter bit DummyInstructions = 0, + parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset input logic clk_i, @@ -55,7 +56,7 @@ module ibex_register_file_ff #( for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin - rf_reg_q[i] <= '0; + rf_reg_q[i] <= WordZeroVal; end else if (we_a_dec[i]) begin rf_reg_q[i] <= wdata_a_i; end @@ -73,21 +74,21 @@ module ibex_register_file_ff #( always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin - rf_r0_q <= '0; + rf_r0_q <= WordZeroVal; end else if (we_r0_dummy) begin rf_r0_q <= wdata_a_i; end end // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : '0; + assign rf_reg[0] = dummy_instr_id_i ? rf_r0_q : WordZeroVal; end else begin : g_normal_r0 logic unused_dummy_instr_id; assign unused_dummy_instr_id = dummy_instr_id_i; // R0 is nil - assign rf_reg[0] = '0; + assign rf_reg[0] = WordZeroVal; end assign rf_reg[NUM_WORDS-1:1] = rf_reg_q[NUM_WORDS-1:1]; diff --git a/rtl/ibex_register_file_fpga.sv b/rtl/ibex_register_file_fpga.sv index 5e7df342..3a5d425a 100644 --- a/rtl/ibex_register_file_fpga.sv +++ b/rtl/ibex_register_file_fpga.sv @@ -12,9 +12,10 @@ * FPGA architectures, it will produce RAM32M primitives. Other vendors have not yet been tested. */ module ibex_register_file_fpga #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0 + parameter bit RV32E = 0, + parameter int unsigned DataWidth = 32, + parameter bit DummyInstructions = 0, + parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset input logic clk_i, @@ -56,6 +57,13 @@ module ibex_register_file_fpga #( end end : sync_write + // Make sure we initialize the BRAM with the correct register reset value. + initial begin + for (int k = 0; k < NUM_WORDS; k++) begin + mem[k] = WordZeroVal; + end + end + // Reset not used in this register file version logic unused_rst_ni; assign unused_rst_ni = rst_ni; diff --git a/rtl/ibex_register_file_latch.sv b/rtl/ibex_register_file_latch.sv index c69e469c..717bcaf6 100644 --- a/rtl/ibex_register_file_latch.sv +++ b/rtl/ibex_register_file_latch.sv @@ -12,9 +12,10 @@ * register file when targeting ASIC synthesis or event-based simulators. */ module ibex_register_file_latch #( - parameter bit RV32E = 0, - parameter int unsigned DataWidth = 32, - parameter bit DummyInstructions = 0 + parameter bit RV32E = 0, + parameter int unsigned DataWidth = 32, + parameter bit DummyInstructions = 0, + parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset input logic clk_i, @@ -78,7 +79,7 @@ module ibex_register_file_latch #( // Use clk_int here, since otherwise we don't want to write anything anyway. always_ff @(posedge clk_int or negedge rst_ni) begin : sample_wdata if (!rst_ni) begin - wdata_a_q <= '0; + wdata_a_q <= WordZeroVal; end else begin if (we_a_i) begin wdata_a_q <= wdata_a_i; @@ -143,13 +144,13 @@ module ibex_register_file_latch #( end // Output the dummy data for dummy instructions, otherwise R0 reads as zero - assign mem[0] = dummy_instr_id_i ? mem_r0 : '0; + assign mem[0] = dummy_instr_id_i ? mem_r0 : WordZeroVal; end else begin : g_normal_r0 logic unused_dummy_instr_id; assign unused_dummy_instr_id = dummy_instr_id_i; - assign mem[0] = '0; + assign mem[0] = WordZeroVal; end `ifdef VERILATOR diff --git a/rtl/ibex_top.sv b/rtl/ibex_top.sv index 90bc2357..7aec5401 100644 --- a/rtl/ibex_top.sv +++ b/rtl/ibex_top.sv @@ -308,11 +308,16 @@ module ibex_top import ibex_pkg::*; #( // Register file Instantiation // ///////////////////////////////// + // We're using an inverted Hsiao code, hence we need to reset + // the regfile ECC bits to 1. + localparam logic [RegFileDataWidth-1:0] WordZeroVal = RegFileDataWidth'({7'h7f, 32'h0}); + if (RegFile == RegFileFF) begin : gen_regfile_ff ibex_register_file_ff #( .RV32E (RV32E), .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions) + .DummyInstructions(DummyInstructions), + .WordZeroVal (WordZeroVal) ) register_file_i ( .clk_i (clk), .rst_ni(rst_ni), @@ -332,7 +337,8 @@ module ibex_top import ibex_pkg::*; #( ibex_register_file_fpga #( .RV32E (RV32E), .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions) + .DummyInstructions(DummyInstructions), + .WordZeroVal (WordZeroVal) ) register_file_i ( .clk_i (clk), .rst_ni(rst_ni), @@ -352,7 +358,8 @@ module ibex_top import ibex_pkg::*; #( ibex_register_file_latch #( .RV32E (RV32E), .DataWidth (RegFileDataWidth), - .DummyInstructions(DummyInstructions) + .DummyInstructions(DummyInstructions), + .WordZeroVal (WordZeroVal) ) register_file_i ( .clk_i (clk), .rst_ni(rst_ni),