diff --git a/doc/02_user/integration.rst b/doc/02_user/integration.rst index 6d835c9ce3..a01d35ae79 100644 --- a/doc/02_user/integration.rst +++ b/doc/02_user/integration.rst @@ -53,8 +53,6 @@ The configuration dependent primitives are: Required where ``ICache == 1`` and ``SecureIbex == 1``. * ``prim_lfsr`` - Linear feedback shift register, used for pseudo random number generation for dummy instruction insertion. Required where ``SecureIbex == 1``. - * ``prim_onehot_check`` - Checks a onehot signal is correct, for detecting fault injection attacks. - Required where ``SecureIbex == 1``. * ``prim_secded_X`` - Various primitives to encode and decode SECDED (Single Error Correct, Double Error Detect) error detection and correction codes. Required where ``SecureIbex == 1``. diff --git a/doc/03_reference/coverage_plan.rst b/doc/03_reference/coverage_plan.rst index 551aadea0a..296d4d7c27 100644 --- a/doc/03_reference/coverage_plan.rst +++ b/doc/03_reference/coverage_plan.rst @@ -338,7 +338,7 @@ For more detail about each security countermeasure in Ibex see :ref:`security` * ``cp_lockstep_err`` - Lockstep glitch fault seen. -* ``cp_rf_we_glitch_err`` - Register file write enable glitch fault seen. +* ``cp_rf_glitch_err`` - Register file fault seen. * ``cp_pc_mismatch_err`` - PC mismatch error seen. @@ -360,7 +360,7 @@ The mapping between security countermeasures and coverpoints that demonstrate it +--------------------------------+-------------------------------------------------------+ | DATA_REG_SW.INTEGRITY | ``cp_rf_a_ecc_err`` ``cp_rf_b_ecc_err`` | +--------------------------------+-------------------------------------------------------+ -| DATA_REG_SW.GLITCH_DETECT | ``cp_rf_we_glitch_err`` | +| DATA_REG_SW.GLITCH_DETECT | ``cp_rf_glitch_err`` | +--------------------------------+-------------------------------------------------------+ | LOGIC.SHADOW | ``cp_lockstep_err`` | +--------------------------------+-------------------------------------------------------+ diff --git a/dv/uvm/core_ibex/fcov/core_ibex_fcov_if.sv b/dv/uvm/core_ibex/fcov/core_ibex_fcov_if.sv index e3e2fcf2f1..5a4a4582a8 100644 --- a/dv/uvm/core_ibex/fcov/core_ibex_fcov_if.sv +++ b/dv/uvm/core_ibex/fcov/core_ibex_fcov_if.sv @@ -395,7 +395,7 @@ interface core_ibex_fcov_if import ibex_pkg::*; ( id_stall_type_last_valid; // V2S Related Probes for Top-Level - logic rf_we_glitch_err; + logic rf_glitch_err; logic lockstep_glitch_err; logic imem_single_cycle_response, dmem_single_cycle_response; @@ -493,7 +493,7 @@ interface core_ibex_fcov_if import ibex_pkg::*; ( `DV_FCOV_EXPR_SEEN(mem_store_ecc_err, load_store_unit_i.store_resp_intg_err_o) `DV_FCOV_EXPR_SEEN(lockstep_err, lockstep_glitch_err) - `DV_FCOV_EXPR_SEEN(rf_we_glitch_err, rf_we_glitch_err) + `DV_FCOV_EXPR_SEEN(rf_glitch_err, rf_glitch_err) `DV_FCOV_EXPR_SEEN(pc_mismatch_err, if_stage_i.pc_mismatch_alert_o) cp_fetch_enable: coverpoint fetch_enable_i { diff --git a/dv/uvm/core_ibex/ibex_dv.f b/dv/uvm/core_ibex/ibex_dv.f index 8b2cd34cac..877870069d 100644 --- a/dv/uvm/core_ibex/ibex_dv.f +++ b/dv/uvm/core_ibex/ibex_dv.f @@ -50,9 +50,6 @@ ${LOWRISC_IP_DIR}/ip/prim/rtl/prim_secded_39_32_dec.sv ${LOWRISC_IP_DIR}/ip/prim/rtl/prim_secded_72_64_enc.sv ${LOWRISC_IP_DIR}/ip/prim/rtl/prim_secded_72_64_dec.sv -${LOWRISC_IP_DIR}/ip/prim/rtl/prim_onehot_check.sv -${LOWRISC_IP_DIR}/ip/prim/rtl/prim_onehot_enc.sv -${LOWRISC_IP_DIR}/ip/prim/rtl/prim_onehot_mux.sv // ibex CORE RTL files +incdir+${PRJ_DIR}/rtl diff --git a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml index 8c6516650f..3c2a447480 100644 --- a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml +++ b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml @@ -709,9 +709,9 @@ rtl_params: SecureIbex: 1 -- test: riscv_rf_ctrl_intg_test +- test: riscv_rf_addr_intg_test description: > - Randomly corrupt one of the register file write and read enables signals in the middle of program execution + Randomly corrupt one of the register file addresses in the middle of program execution iterations: 15 gen_test: riscv_rand_instr_test gen_opts: > @@ -720,7 +720,7 @@ +gen_all_csrs_by_default=1 +add_csr_write=MSTATUS,MEPC,MCAUSE,MTVAL,0x7c0,0x7c1 +no_csr_instr=0 - rtl_test: core_ibex_rf_ctrl_intg_test + rtl_test: core_ibex_rf_addr_intg_test rtl_params: SecureIbex: 1 diff --git a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv index b4107f41ac..61fc0aa247 100644 --- a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv +++ b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv @@ -196,9 +196,8 @@ module core_ibex_tb_top; end `ifndef DV_FCOV_DISABLE - assign dut.u_ibex_top.u_ibex_core.u_fcov_bind.rf_we_glitch_err = - dut.u_ibex_top.rf_alert_major_internal; - + assign dut.u_ibex_top.u_ibex_core.u_fcov_bind.rf_glitch_err = + dut.u_ibex_top.alert_major_internal_o; assign dut.u_ibex_top.u_ibex_core.u_fcov_bind.lockstep_glitch_err = dut.u_ibex_top.lockstep_alert_major_internal; `endif @@ -383,20 +382,6 @@ module core_ibex_tb_top; unused_assert_connected = 1; end - // Disable the assertion for onehot check in case WrenCheck (set by SecureIbex) is enabled. - if (SecureIbex) begin : gen_disable_onehot_check - assign dut.u_ibex_top.gen_regfile_ff.register_file_i.gen_wren_check.u_prim_onehot_check. - unused_assert_connected = 1; - end - - // Disable the assertion for onehot check in case RdataMuxCheck (set by SecureIbex) is enabled. - if (SecureIbex) begin : gen_disable_rdata_mux_check - assign dut.u_ibex_top.gen_regfile_ff.register_file_i.gen_rdata_mux_check. - u_prim_onehot_check_raddr_a.unused_assert_connected = 1; - assign dut.u_ibex_top.gen_regfile_ff.register_file_i.gen_rdata_mux_check. - u_prim_onehot_check_raddr_b.unused_assert_connected = 1; - end - ibex_pkg::ctrl_fsm_e controller_state; logic controller_handle_irq; ibex_pkg::irqs_t ibex_irqs, last_ibex_irqs; diff --git a/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv b/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv index 7d52bb0684..5794dde7ce 100644 --- a/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv +++ b/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv @@ -132,12 +132,15 @@ class core_ibex_rf_intg_test extends core_ibex_base_test; int rnd_delay; bit port_idx; string port_name; + int unsigned lockstep_delay; vseq.start(env.vseqr); // Pick port to corrupt. port_idx = $urandom_range(1); - port_name = port_idx ? "rf_rdata_b_ecc" : "rf_rdata_a_ecc"; + port_name = port_idx ? "rf_rdata_b" : "rf_rdata_a"; + + lockstep_delay = read_data("gen_lockstep.u_ibex_lockstep.LockstepOffset"); `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(rnd_delay, rnd_delay > 1000; rnd_delay < 10_000;) clk_vif.wait_n_clks(rnd_delay); @@ -182,8 +185,8 @@ class core_ibex_rf_intg_test extends core_ibex_base_test; // Determine whether an alert is expected: if the instruction is valid. exp_alert = read_data("u_ibex_core.instr_valid_id"); - // Schedule a simulation step so the DUT can react. - #1step; + // Wait LockstepOffset cycles before reading the error. + clk_vif.wait_n_clks(lockstep_delay); // Check if the major alert matches our expectation. alert_major_internal = read_data("alert_major_internal_o"); @@ -205,8 +208,8 @@ class core_ibex_rf_intg_test extends core_ibex_base_test; endclass -class core_ibex_rf_ctrl_intg_test extends core_ibex_base_test; - `uvm_component_utils(core_ibex_rf_ctrl_intg_test) +class core_ibex_rf_addr_intg_test extends core_ibex_base_test; + `uvm_component_utils(core_ibex_rf_addr_intg_test) `uvm_component_new uvm_report_server rs; @@ -215,23 +218,47 @@ class core_ibex_rf_ctrl_intg_test extends core_ibex_base_test; int rnd_delay; int unsigned bit_idx; logic [31:0] orig_val, glitch_val; - logic alert_major_internal; - string glitch_path, alert_major_internal_path; + logic [1:0] ecc_err; + string glitch_path, ecc_alert_path, lockstep_delay_path; + string trgt_core_path[]; string ctrl_signals[]; + string err_signals[]; int unsigned ctrl_signal_idx; + int unsigned trgt_core_idx; string top_path = "core_ibex_tb_top.dut.u_ibex_top"; + // Main core signals. string ibex_rf_path = {top_path, ".gen_regfile_ff.register_file_i"}; + // Shadow core signals. + string lockstep_path = {top_path, ".gen_lockstep.u_ibex_lockstep"}; + string shdw_ecc_path = {lockstep_path, ".u_shadow_core.gen_regfile_ecc"}; + string shdw_rf_path = {lockstep_path, ".gen_shadow_regfile_ff.register_file_shadow_i"}; + // The lockstep delay. + int unsigned lockstep_delay; + + trgt_core_path = { + ibex_rf_path, + shdw_rf_path + }; ctrl_signals = { - "we_a_dec", - "gen_rdata_mux_check.raddr_onehot_a", - "gen_rdata_mux_check.raddr_onehot_b" + "raddr_a_i", + "raddr_b_i" + }; + + err_signals = { + "rf_ecc_err_a", + "rf_ecc_err_b" }; + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(trgt_core_idx, trgt_core_idx < trgt_core_path.size();) `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(ctrl_signal_idx, ctrl_signal_idx < ctrl_signals.size();) `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(rnd_delay, rnd_delay > 1000; rnd_delay < 10_000;) - glitch_path = $sformatf("%s.%s", ibex_rf_path, ctrl_signals[ctrl_signal_idx]); + glitch_path = $sformatf("%s.%s", trgt_core_path[trgt_core_idx], ctrl_signals[ctrl_signal_idx]); + + // Read the lockstep delay. + lockstep_delay_path = $sformatf("%s.%s", lockstep_path, "LockstepOffset"); + `DV_CHECK_FATAL(uvm_hdl_read(lockstep_delay_path, lockstep_delay)); vseq.start(env.vseqr); clk_vif.wait_n_clks(rnd_delay); @@ -240,27 +267,31 @@ class core_ibex_rf_ctrl_intg_test extends core_ibex_base_test; `DV_CHECK_FATAL(uvm_hdl_read(glitch_path, orig_val)); `uvm_info(`gfn, $sformatf("Read %x", orig_val), UVM_LOW) - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(bit_idx, bit_idx < 32;) + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(bit_idx, bit_idx < 5;) glitch_val = orig_val; glitch_val[bit_idx] = ~glitch_val[bit_idx]; // Disable TB assertion for alerts. `DV_ASSERT_CTRL_REQ("tb_no_alerts_triggered", 1'b0) - // Disable one-hot check assertions for RF muxes - `DV_ASSERT_CTRL_REQ("tb_rf_rd_mux_a_onehot", 1'b0) - `DV_ASSERT_CTRL_REQ("tb_rf_rd_mux_b_onehot", 1'b0) `uvm_info(`gfn, $sformatf("Forcing %s to value 'h%0x", glitch_path, glitch_val), UVM_LOW) `DV_CHECK_FATAL(uvm_hdl_force(glitch_path, glitch_val)); - // Leave glitch applied for one clock cycle. - clk_vif.wait_n_clks(1); + // Determine how long it takes until the error gets noticed. + if (trgt_core_idx == 0) begin + // When we are faulting the main core RF, it takes lockstep_delay until we detect the fault. + // This is because the shadow core ECC checker is responsible for detecting the fault. + clk_vif.wait_n_clks(lockstep_delay); + end else begin + // When we are faulting the shadow core RF, the fault is immediately detected. + #1step; + end // Check that the alert matches our expectation. - alert_major_internal_path = $sformatf("%s.alert_major_internal_o", top_path); - `DV_CHECK_FATAL(uvm_hdl_read(alert_major_internal_path, alert_major_internal)) - `DV_CHECK_FATAL(alert_major_internal, "Major alert did not fire!") + ecc_alert_path = $sformatf("%s.%s", shdw_ecc_path, err_signals[ctrl_signal_idx]); + `DV_CHECK_FATAL(uvm_hdl_read(ecc_alert_path, ecc_err)) + `DV_CHECK_FATAL(|ecc_err, "ECC alert did not fire!") // Release glitch. `DV_CHECK_FATAL(uvm_hdl_release(glitch_path)) diff --git a/rtl/ibex_lockstep.sv b/rtl/ibex_lockstep.sv index 61dc450d6d..71b841f0bf 100644 --- a/rtl/ibex_lockstep.sv +++ b/rtl/ibex_lockstep.sv @@ -39,6 +39,8 @@ module ibex_lockstep import ibex_pkg::*; #( parameter bit DummyInstructions = 1'b0, parameter bit RegFileECC = 1'b0, parameter int unsigned RegFileDataWidth = 32, + parameter int unsigned RegFileDataEccWidth = 39, + parameter regfile_e RegFile = RegFileFF, parameter bit MemECC = 1'b0, parameter int unsigned MemDataWidth = MemECC ? 32 + 7 : 32, parameter int unsigned DmBaseAddr = 32'h1A110000, @@ -73,15 +75,8 @@ module ibex_lockstep import ibex_pkg::*; #( input logic [MemDataWidth-1:0] data_rdata_i, input logic data_err_i, - input logic dummy_instr_id_i, - input logic dummy_instr_wb_i, - input logic [4:0] rf_raddr_a_i, - input logic [4:0] rf_raddr_b_i, - input logic [4:0] rf_waddr_wb_i, - input logic rf_we_wb_i, - input logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i, - input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i, + input logic [RegFileDataWidth-1:0] rf_rdata_a_i, + input logic [RegFileDataWidth-1:0] rf_rdata_b_i, input logic [IC_NUM_WAYS-1:0] ic_tag_req_i, input logic ic_tag_write_i, @@ -116,6 +111,8 @@ module ibex_lockstep import ibex_pkg::*; #( input logic scan_rst_ni ); + import prim_secded_pkg::SecdedInv3932ZeroWord; + localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset); // Core outputs are delayed for an extra cycle due to shadow output registers localparam int unsigned OutputsOffset = LockstepOffset + 1; @@ -210,8 +207,8 @@ module ibex_lockstep import ibex_pkg::*; #( logic data_rvalid; logic [MemDataWidth-1:0] data_rdata; logic data_err; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc; + logic [RegFileDataWidth-1:0] rf_rdata_a; + logic [RegFileDataWidth-1:0] rf_rdata_b; logic irq_software; logic irq_timer; logic irq_external; @@ -237,8 +234,8 @@ module ibex_lockstep import ibex_pkg::*; #( assign shadow_inputs_in.data_rvalid = data_rvalid_i; assign shadow_inputs_in.data_rdata = data_rdata_i; assign shadow_inputs_in.data_err = data_err_i; - assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i; - assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i; + assign shadow_inputs_in.rf_rdata_a = rf_rdata_a_i; + assign shadow_inputs_in.rf_rdata_b = rf_rdata_b_i; assign shadow_inputs_in.irq_software = irq_software_i; assign shadow_inputs_in.irq_timer = irq_timer_i; assign shadow_inputs_in.irq_external = irq_external_i; @@ -273,33 +270,26 @@ module ibex_lockstep import ibex_pkg::*; #( /////////////////// typedef struct packed { - logic instr_req; - logic [31:0] instr_addr; - logic data_req; - logic data_we; - logic [3:0] data_be; - logic [31:0] data_addr; - logic [MemDataWidth-1:0] data_wdata; - logic dummy_instr_id; - logic dummy_instr_wb; - logic [4:0] rf_raddr_a; - logic [4:0] rf_raddr_b; - logic [4:0] rf_waddr_wb; - logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [IC_NUM_WAYS-1:0] ic_tag_req; - logic ic_tag_write; - logic [IC_INDEX_W-1:0] ic_tag_addr; - logic [TagSizeECC-1:0] ic_tag_wdata; - logic [IC_NUM_WAYS-1:0] ic_data_req; - logic ic_data_write; - logic [IC_INDEX_W-1:0] ic_data_addr; - logic [LineSizeECC-1:0] ic_data_wdata; - logic ic_scr_key_req; - logic irq_pending; - crash_dump_t crash_dump; - logic double_fault_seen; - ibex_mubi_t core_busy; + logic instr_req; + logic [31:0] instr_addr; + logic data_req; + logic data_we; + logic [3:0] data_be; + logic [31:0] data_addr; + logic [MemDataWidth-1:0] data_wdata; + logic [IC_NUM_WAYS-1:0] ic_tag_req; + logic ic_tag_write; + logic [IC_INDEX_W-1:0] ic_tag_addr; + logic [TagSizeECC-1:0] ic_tag_wdata; + logic [IC_NUM_WAYS-1:0] ic_data_req; + logic ic_data_write; + logic [IC_INDEX_W-1:0] ic_data_addr; + logic [LineSizeECC-1:0] ic_data_wdata; + logic ic_scr_key_req; + logic irq_pending; + crash_dump_t crash_dump; + logic double_fault_seen; + ibex_mubi_t core_busy; } delayed_outputs_t; delayed_outputs_t [OutputsOffset-1:0] core_outputs_q; @@ -314,13 +304,6 @@ module ibex_lockstep import ibex_pkg::*; #( assign core_outputs_in.data_be = data_be_i; assign core_outputs_in.data_addr = data_addr_i; assign core_outputs_in.data_wdata = data_wdata_i; - assign core_outputs_in.dummy_instr_id = dummy_instr_id_i; - assign core_outputs_in.dummy_instr_wb = dummy_instr_wb_i; - assign core_outputs_in.rf_raddr_a = rf_raddr_a_i; - assign core_outputs_in.rf_raddr_b = rf_raddr_b_i; - assign core_outputs_in.rf_waddr_wb = rf_waddr_wb_i; - assign core_outputs_in.rf_we_wb = rf_we_wb_i; - assign core_outputs_in.rf_wdata_wb_ecc = rf_wdata_wb_ecc_i; assign core_outputs_in.ic_tag_req = ic_tag_req_i; assign core_outputs_in.ic_tag_write = ic_tag_write_i; assign core_outputs_in.ic_tag_addr = ic_tag_addr_i; @@ -343,50 +326,65 @@ module ibex_lockstep import ibex_pkg::*; #( core_outputs_q[OutputsOffset-1] <= core_outputs_in; end + // The following outputs are generated by the shadow core and directly fed into the shadow core + // register file. There is no need to compare those signals against the signals generated by the + // main core in the lockstep comparison. A fault into one of those signals will cause a mismatch + // in the main core and shadow core register file instances. As the outputs of both register + // files are combined, the ECC checker inside the shadow core will detect the fault. + logic [RegFileDataEccWidth-1:0] shadow_rf_wdata_wb_ecc; + logic [4:0] shadow_rf_raddr_a; + logic [4:0] shadow_rf_raddr_b; + logic [4:0] shadow_rf_waddr_wb; + logic shadow_rf_we_wb; + logic shadow_dummy_instr_id; + logic shadow_dummy_instr_wb; + /////////////////////////////// // Shadow core instantiation // /////////////////////////////// logic shadow_alert_minor, shadow_alert_major_internal, shadow_alert_major_bus; + logic [RegFileDataEccWidth - RegFileDataWidth - 1:0] shadow_rf_rdata_a_intg; + logic [RegFileDataEccWidth - RegFileDataWidth - 1:0] shadow_rf_rdata_b_intg; ibex_core #( - .PMPEnable ( PMPEnable ), - .PMPGranularity ( PMPGranularity ), - .PMPNumRegions ( PMPNumRegions ), - .PMPRstCfg ( PMPRstCfg ), - .PMPRstAddr ( PMPRstAddr ), - .PMPRstMsecCfg ( PMPRstMsecCfg ), - .MHPMCounterNum ( MHPMCounterNum ), - .MHPMCounterWidth ( MHPMCounterWidth ), - .RV32E ( RV32E ), - .RV32M ( RV32M ), - .RV32B ( RV32B ), - .RV32ZC ( RV32ZC ), - .BranchTargetALU ( BranchTargetALU ), - .ICache ( ICache ), - .ICacheECC ( ICacheECC ), - .BusSizeECC ( BusSizeECC ), - .TagSizeECC ( TagSizeECC ), - .LineSizeECC ( LineSizeECC ), - .BranchPredictor ( BranchPredictor ), - .DbgTriggerEn ( DbgTriggerEn ), - .DbgHwBreakNum ( DbgHwBreakNum ), - .WritebackStage ( WritebackStage ), - .ResetAll ( ResetAll ), - .RndCnstLfsrSeed ( RndCnstLfsrSeed ), - .RndCnstLfsrPerm ( RndCnstLfsrPerm ), - .SecureIbex ( SecureIbex ), - .DummyInstructions ( DummyInstructions ), - .RegFileECC ( RegFileECC ), - .RegFileDataWidth ( RegFileDataWidth ), - .MemECC ( MemECC ), - .MemDataWidth ( MemDataWidth ), - .DmBaseAddr ( DmBaseAddr ), - .DmAddrMask ( DmAddrMask ), - .DmHaltAddr ( DmHaltAddr ), - .DmExceptionAddr ( DmExceptionAddr ), - .CsrMvendorId ( CsrMvendorId ), - .CsrMimpId ( CsrMimpId ) + .PMPEnable ( PMPEnable ), + .PMPGranularity ( PMPGranularity ), + .PMPNumRegions ( PMPNumRegions ), + .PMPRstCfg ( PMPRstCfg ), + .PMPRstAddr ( PMPRstAddr ), + .PMPRstMsecCfg ( PMPRstMsecCfg ), + .MHPMCounterNum ( MHPMCounterNum ), + .MHPMCounterWidth ( MHPMCounterWidth ), + .RV32E ( RV32E ), + .RV32M ( RV32M ), + .RV32B ( RV32B ), + .RV32ZC ( RV32ZC ), + .BranchTargetALU ( BranchTargetALU ), + .ICache ( ICache ), + .ICacheECC ( ICacheECC ), + .BusSizeECC ( BusSizeECC ), + .TagSizeECC ( TagSizeECC ), + .LineSizeECC ( LineSizeECC ), + .BranchPredictor ( BranchPredictor ), + .DbgTriggerEn ( DbgTriggerEn ), + .DbgHwBreakNum ( DbgHwBreakNum ), + .WritebackStage ( WritebackStage ), + .ResetAll ( ResetAll ), + .RndCnstLfsrSeed ( RndCnstLfsrSeed ), + .RndCnstLfsrPerm ( RndCnstLfsrPerm ), + .SecureIbex ( SecureIbex ), + .DummyInstructions ( DummyInstructions ), + .RegFileECC ( RegFileECC ), + .RegFileDataWidth ( RegFileDataEccWidth ), + .MemECC ( MemECC ), + .MemDataWidth ( MemDataWidth ), + .DmBaseAddr ( DmBaseAddr ), + .DmAddrMask ( DmAddrMask ), + .DmHaltAddr ( DmHaltAddr ), + .DmExceptionAddr ( DmExceptionAddr ), + .CsrMvendorId ( CsrMvendorId ), + .CsrMimpId ( CsrMimpId ) ) u_shadow_core ( .clk_i (clk_i), .rst_ni (rst_shadow_n), @@ -411,15 +409,15 @@ module ibex_lockstep import ibex_pkg::*; #( .data_rdata_i (shadow_inputs_q[0].data_rdata), .data_err_i (shadow_inputs_q[0].data_err), - .dummy_instr_id_o (shadow_outputs_d.dummy_instr_id), - .dummy_instr_wb_o (shadow_outputs_d.dummy_instr_wb), - .rf_raddr_a_o (shadow_outputs_d.rf_raddr_a), - .rf_raddr_b_o (shadow_outputs_d.rf_raddr_b), - .rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb), - .rf_we_wb_o (shadow_outputs_d.rf_we_wb), - .rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (shadow_inputs_q[0].rf_rdata_a_ecc), - .rf_rdata_b_ecc_i (shadow_inputs_q[0].rf_rdata_b_ecc), + .dummy_instr_id_o (shadow_dummy_instr_id), + .dummy_instr_wb_o (shadow_dummy_instr_wb), + .rf_raddr_a_o (shadow_rf_raddr_a), + .rf_raddr_b_o (shadow_rf_raddr_b), + .rf_waddr_wb_o (shadow_rf_waddr_wb), + .rf_we_wb_o (shadow_rf_we_wb), + .rf_wdata_wb_ecc_o (shadow_rf_wdata_wb_ecc), + .rf_rdata_a_ecc_i ({shadow_rf_rdata_a_intg, shadow_inputs_q[0].rf_rdata_a}), + .rf_rdata_b_ecc_i ({shadow_rf_rdata_b_intg, shadow_inputs_q[0].rf_rdata_b}), .ic_tag_req_o (shadow_outputs_d.ic_tag_req), .ic_tag_write_o (shadow_outputs_d.ic_tag_write), @@ -498,6 +496,83 @@ module ibex_lockstep import ibex_pkg::*; #( shadow_outputs_q <= shadow_outputs_d; end + // The lower RegFileDataWidth bits (which are the data bits) are not fed into the shadow + // register file as they are handled by the main register file. + logic [RegFileDataWidth-1:0] unused_shadow_rf_wdata_wb_ecc; + assign unused_shadow_rf_wdata_wb_ecc = shadow_rf_wdata_wb_ecc[RegFileDataWidth-1:0]; + + ////////////////////////// + // Shadow register file // + ////////////////////////// + // SEC_CM: DATA_REG_SW.GLITCH_DETECT + if (RegFile == RegFileFF) begin : gen_shadow_regfile_ff + ibex_register_file_ff #( + .RV32E (RV32E), + .DataWidth (RegFileDataEccWidth - RegFileDataWidth), + .DummyInstructions(DummyInstructions), + .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth-1:RegFileDataWidth]) + ) register_file_shadow_i ( + .clk_i (clk_i), + .rst_ni (rst_shadow_n), + + .test_en_i (test_en_i), + .dummy_instr_id_i (shadow_dummy_instr_id), + .dummy_instr_wb_i (shadow_dummy_instr_wb), + + .raddr_a_i (shadow_rf_raddr_a), + .rdata_a_o (shadow_rf_rdata_a_intg), + .raddr_b_i (shadow_rf_raddr_b), + .rdata_b_o (shadow_rf_rdata_b_intg), + .waddr_a_i (shadow_rf_waddr_wb), + .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth-1:RegFileDataWidth]), + .we_a_i (shadow_rf_we_wb) + ); + end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga + ibex_register_file_fpga #( + .RV32E (RV32E), + .DataWidth (RegFileDataEccWidth - RegFileDataWidth), + .DummyInstructions(DummyInstructions), + .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth-1:RegFileDataWidth]) + ) register_file_shadow_i ( + .clk_i (clk_i), + .rst_ni (rst_shadow_n), + + .test_en_i (test_en_i), + .dummy_instr_id_i (shadow_dummy_instr_id), + .dummy_instr_wb_i (shadow_dummy_instr_wb), + + .raddr_a_i (shadow_rf_raddr_a), + .rdata_a_o (shadow_rf_rdata_a_intg), + .raddr_b_i (shadow_rf_raddr_b), + .rdata_b_o (shadow_rf_rdata_b_intg), + .waddr_a_i (shadow_rf_waddr_wb), + .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth-1:RegFileDataWidth]), + .we_a_i (shadow_rf_we_wb) + ); + end else if (RegFile == RegFileLatch) begin : gen_regfile_latch + ibex_register_file_latch #( + .RV32E (RV32E), + .DataWidth (RegFileDataEccWidth - RegFileDataWidth), + .DummyInstructions(DummyInstructions), + .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth-1:RegFileDataWidth]) + ) register_file_shadow_i ( + .clk_i (clk_i), + .rst_ni (rst_shadow_n), + + .test_en_i (test_en_i), + .dummy_instr_id_i (shadow_dummy_instr_id), + .dummy_instr_wb_i (shadow_dummy_instr_wb), + + .raddr_a_i (shadow_rf_raddr_a), + .rdata_a_o (shadow_rf_rdata_a_intg), + .raddr_b_i (shadow_rf_raddr_b), + .rdata_b_o (shadow_rf_rdata_b_intg), + .waddr_a_i (shadow_rf_waddr_wb), + .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth-1:RegFileDataWidth]), + .we_a_i (shadow_rf_we_wb) + ); + end + ///////////////////////// // Compare the outputs // ///////////////////////// diff --git a/rtl/ibex_register_file_ff.sv b/rtl/ibex_register_file_ff.sv index 53c89e2d34..f94f9550ad 100644 --- a/rtl/ibex_register_file_ff.sv +++ b/rtl/ibex_register_file_ff.sv @@ -14,8 +14,6 @@ module ibex_register_file_ff #( parameter bit RV32E = 0, parameter int unsigned DataWidth = 32, parameter bit DummyInstructions = 0, - parameter bit WrenCheck = 0, - parameter bit RdataMuxCheck = 0, parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset @@ -38,10 +36,7 @@ module ibex_register_file_ff #( // Write port W1 input logic [4:0] waddr_a_i, input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i, - - // This indicates whether spurious WE or non-one-hot encoded raddr are detected. - output logic err_o + input logic we_a_i ); localparam int unsigned ADDR_WIDTH = RV32E ? 4 : 5; @@ -50,44 +45,14 @@ module ibex_register_file_ff #( logic [DataWidth-1:0] rf_reg [NUM_WORDS]; logic [NUM_WORDS-1:0] we_a_dec; - logic oh_raddr_a_err, oh_raddr_b_err, oh_we_err; - always_comb begin : we_a_decoder for (int unsigned i = 0; i < NUM_WORDS; i++) begin we_a_dec[i] = (waddr_a_i == 5'(i)) ? we_a_i : 1'b0; end end - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - // This checks for spurious WE strobes on the regfile. - if (WrenCheck) begin : gen_wren_check - // Buffer the decoded write enable bits so that the checker - // is not optimized into the address decoding logic. - logic [NUM_WORDS-1:0] we_a_dec_buf; - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf ( - .in_i(we_a_dec), - .out_o(we_a_dec_buf) - ); - - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .AddrCheck(1), - .EnableCheck(1) - ) u_prim_onehot_check ( - .clk_i, - .rst_ni, - .oh_i(we_a_dec_buf), - .addr_i(waddr_a_i), - .en_i(we_a_i), - .err_o(oh_we_err) - ); - end else begin : gen_no_wren_check - logic unused_strobe; - assign unused_strobe = we_a_dec[0]; // this is never read from in this case - assign oh_we_err = 1'b0; - end + logic unused_strobe; + assign unused_strobe = we_a_dec[0]; // this is never read from in this case // No flops for R0 as it's hard-wired to 0 for (genvar i = 1; i < NUM_WORDS; i++) begin : g_rf_flops @@ -133,106 +98,8 @@ module ibex_register_file_ff #( assign rf_reg[0] = WordZeroVal; end - if (RdataMuxCheck) begin : gen_rdata_mux_check - // Encode raddr_a/b into one-hot encoded signals. - logic [NUM_WORDS-1:0] raddr_onehot_a, raddr_onehot_b; - logic [NUM_WORDS-1:0] raddr_onehot_a_buf, raddr_onehot_b_buf; - prim_onehot_enc #( - .OneHotWidth(NUM_WORDS) - ) u_prim_onehot_enc_raddr_a ( - .in_i (raddr_a_i), - .en_i (1'b1), - .out_o (raddr_onehot_a) - ); - - prim_onehot_enc #( - .OneHotWidth(NUM_WORDS) - ) u_prim_onehot_enc_raddr_b ( - .in_i (raddr_b_i), - .en_i (1'b1), - .out_o (raddr_onehot_b) - ); - - // Buffer the one-hot encoded signals so that the checkers - // are not optimized. - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf_raddr_a ( - .in_i (raddr_onehot_a), - .out_o(raddr_onehot_a_buf) - ); - - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf_raddr_b ( - .in_i (raddr_onehot_b), - .out_o(raddr_onehot_b_buf) - ); - - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - // Check the one-hot encoded signals for glitches. - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .OneHotWidth(NUM_WORDS), - .AddrCheck(1), - // When AddrCheck=1 also EnableCheck needs to be 1. - .EnableCheck(1) - ) u_prim_onehot_check_raddr_a ( - .clk_i, - .rst_ni, - .oh_i (raddr_onehot_a_buf), - .addr_i (raddr_a_i), - // Set enable=1 as address is always valid. - .en_i (1'b1), - .err_o (oh_raddr_a_err) - ); - - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .OneHotWidth(NUM_WORDS), - .AddrCheck(1), - // When AddrCheck=1 also EnableCheck needs to be 1. - .EnableCheck(1) - ) u_prim_onehot_check_raddr_b ( - .clk_i, - .rst_ni, - .oh_i (raddr_onehot_b_buf), - .addr_i (raddr_b_i), - // Set enable=1 as address is always valid. - .en_i (1'b1), - .err_o (oh_raddr_b_err) - ); - - // MUX register to rdata_a/b_o according to raddr_a/b_onehot. - prim_onehot_mux #( - .Width(DataWidth), - .Inputs(NUM_WORDS) - ) u_rdata_a_mux ( - .clk_i, - .rst_ni, - .in_i (rf_reg), - .sel_i (raddr_onehot_a), - .out_o (rdata_a_o) - ); - - prim_onehot_mux #( - .Width(DataWidth), - .Inputs(NUM_WORDS) - ) u_rdata_b_mux ( - .clk_i, - .rst_ni, - .in_i (rf_reg), - .sel_i (raddr_onehot_b), - .out_o (rdata_b_o) - ); - end else begin : gen_no_rdata_mux_check - assign rdata_a_o = rf_reg[raddr_a_i]; - assign rdata_b_o = rf_reg[raddr_b_i]; - assign oh_raddr_a_err = 1'b0; - assign oh_raddr_b_err = 1'b0; - end - - assign err_o = oh_raddr_a_err || oh_raddr_b_err || oh_we_err; + assign rdata_a_o = rf_reg[raddr_a_i]; + assign rdata_b_o = rf_reg[raddr_b_i]; // Signal not used in FF register file logic unused_test_en; diff --git a/rtl/ibex_register_file_fpga.sv b/rtl/ibex_register_file_fpga.sv index 65698d1c51..fcabad15c0 100644 --- a/rtl/ibex_register_file_fpga.sv +++ b/rtl/ibex_register_file_fpga.sv @@ -15,8 +15,6 @@ module ibex_register_file_fpga #( parameter bit RV32E = 0, parameter int unsigned DataWidth = 32, parameter bit DummyInstructions = 0, - parameter bit WrenCheck = 0, - parameter bit RdataMuxCheck = 0, parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset @@ -36,10 +34,7 @@ module ibex_register_file_fpga #( // Write port W1 input logic [ 4:0] waddr_a_i, input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i, - - // This indicates whether spurious WE or non-one-hot encoded raddr are detected. - output logic err_o + input logic we_a_i ); localparam int ADDR_WIDTH = RV32E ? 4 : 5; @@ -50,125 +45,12 @@ module ibex_register_file_fpga #( logic [DataWidth-1:0] mem_o_a, mem_o_b; - // WE strobe and one-hot encoded raddr alert. - logic oh_raddr_a_err, oh_raddr_b_err, oh_we_err; - assign err_o = oh_raddr_a_err || oh_raddr_b_err || oh_we_err; - - if (RdataMuxCheck) begin : gen_rdata_mux_check - // Encode raddr_a/b into one-hot encoded signals. - logic [NUM_WORDS-1:0] raddr_onehot_a, raddr_onehot_b; - logic [NUM_WORDS-1:0] raddr_onehot_a_buf, raddr_onehot_b_buf; - prim_onehot_enc #( - .OneHotWidth(NUM_WORDS) - ) u_prim_onehot_enc_raddr_a ( - .in_i (raddr_a_i), - .en_i (1'b1), - .out_o (raddr_onehot_a) - ); - - prim_onehot_enc #( - .OneHotWidth(NUM_WORDS) - ) u_prim_onehot_enc_raddr_b ( - .in_i (raddr_b_i), - .en_i (1'b1), - .out_o (raddr_onehot_b) - ); - - // Buffer the one-hot encoded signals so that the checkers - // are not optimized. - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf_raddr_a ( - .in_i (raddr_onehot_a), - .out_o(raddr_onehot_a_buf) - ); - - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf_raddr_b ( - .in_i (raddr_onehot_b), - .out_o(raddr_onehot_b_buf) - ); - - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - // Check the one-hot encoded signals for glitches. - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .OneHotWidth(NUM_WORDS), - .AddrCheck(1), - // When AddrCheck=1 also EnableCheck needs to be 1. - .EnableCheck(1) - ) u_prim_onehot_check_raddr_a ( - .clk_i, - .rst_ni, - .oh_i (raddr_onehot_a_buf), - .addr_i (raddr_a_i), - // Set enable=1 as address is always valid. - .en_i (1'b1), - .err_o (oh_raddr_a_err) - ); - - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .OneHotWidth(NUM_WORDS), - .AddrCheck(1), - // When AddrCheck=1 also EnableCheck needs to be 1. - .EnableCheck(1) - ) u_prim_onehot_check_raddr_b ( - .clk_i, - .rst_ni, - .oh_i (raddr_onehot_b_buf), - .addr_i (raddr_b_i), - // Set enable=1 as address is always valid. - .en_i (1'b1), - .err_o (oh_raddr_b_err) - ); - - // MUX register to rdata_a/b_o according to raddr_a/b_onehot. - prim_onehot_mux #( - .Width(DataWidth), - .Inputs(NUM_WORDS) - ) u_rdata_a_mux ( - .clk_i, - .rst_ni, - .in_i (mem), - .sel_i (raddr_onehot_a), - .out_o (mem_o_a) - ); - - prim_onehot_mux #( - .Width(DataWidth), - .Inputs(NUM_WORDS) - ) u_rdata_b_mux ( - .clk_i, - .rst_ni, - .in_i (mem), - .sel_i (raddr_onehot_b), - .out_o (mem_o_b) - ); - - assign rdata_a_o = (raddr_a_i == '0) ? WordZeroVal : mem_o_a; - assign rdata_b_o = (raddr_b_i == '0) ? WordZeroVal : mem_o_b; - end else begin : gen_no_rdata_mux_check - assign rdata_a_o = (raddr_a_i == '0) ? WordZeroVal : mem[raddr_a_i]; - assign rdata_b_o = (raddr_b_i == '0) ? WordZeroVal : mem[raddr_b_i]; - - assign oh_raddr_a_err = 1'b0; - assign oh_raddr_b_err = 1'b0; - end + assign rdata_a_o = (raddr_a_i == '0) ? WordZeroVal : mem[raddr_a_i]; + assign rdata_b_o = (raddr_b_i == '0) ? WordZeroVal : mem[raddr_b_i]; // we select assign we = (waddr_a_i == '0) ? 1'b0 : we_a_i; - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - // This checks for spurious WE strobes on the regfile. - if (WrenCheck) begin : gen_wren_check - // Since the FPGA uses a memory macro, there is only one write-enable strobe to check. - assign oh_we_err = we && !we_a_i; - end else begin : gen_no_wren_check - assign oh_we_err = 1'b0; - end - // Note that the SystemVerilog LRM requires variables on the LHS of assignments within // "always_ff" to not be written to by any other process. However, to enable the initialization // of the inferred RAM32M primitives with non-zero values, below "initial" procedure is needed. diff --git a/rtl/ibex_register_file_latch.sv b/rtl/ibex_register_file_latch.sv index 375da414b4..1526b09861 100644 --- a/rtl/ibex_register_file_latch.sv +++ b/rtl/ibex_register_file_latch.sv @@ -15,8 +15,6 @@ module ibex_register_file_latch #( parameter bit RV32E = 0, parameter int unsigned DataWidth = 32, parameter bit DummyInstructions = 0, - parameter bit WrenCheck = 0, - parameter bit RdataMuxCheck = 0, parameter logic [DataWidth-1:0] WordZeroVal = '0 ) ( // Clock and Reset @@ -38,10 +36,7 @@ module ibex_register_file_latch #( // Write port W1 input logic [4:0] waddr_a_i, input logic [DataWidth-1:0] wdata_a_i, - input logic we_a_i, - - // This indicates whether spurious WE or non-one-hot encoded raddr are detected. - output logic err_o + input logic we_a_i ); localparam int unsigned ADDR_WIDTH = RV32E ? 4 : 5; @@ -51,8 +46,6 @@ module ibex_register_file_latch #( logic [NUM_WORDS-1:0] waddr_onehot_a; - logic oh_raddr_a_err, oh_raddr_b_err, oh_we_err; - logic [NUM_WORDS-1:1] mem_clocks; logic [DataWidth-1:0] wdata_a_q; @@ -65,109 +58,11 @@ module ibex_register_file_latch #( logic clk_int; - assign err_o = oh_raddr_a_err || oh_raddr_b_err || oh_we_err; - ////////// // READ // ////////// - if (RdataMuxCheck) begin : gen_rdata_mux_check - // Encode raddr_a/b into one-hot encoded signals. - logic [NUM_WORDS-1:0] raddr_onehot_a, raddr_onehot_b; - logic [NUM_WORDS-1:0] raddr_onehot_a_buf, raddr_onehot_b_buf; - prim_onehot_enc #( - .OneHotWidth(NUM_WORDS) - ) u_prim_onehot_enc_raddr_a ( - .in_i (raddr_a_int), - .en_i (1'b1), - .out_o (raddr_onehot_a) - ); - - prim_onehot_enc #( - .OneHotWidth(NUM_WORDS) - ) u_prim_onehot_enc_raddr_b ( - .in_i (raddr_b_int), - .en_i (1'b1), - .out_o (raddr_onehot_b) - ); - - // Buffer the one-hot encoded signals so that the checkers - // are not optimized. - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf_raddr_a ( - .in_i(raddr_onehot_a), - .out_o(raddr_onehot_a_buf) - ); - - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf_raddr_b ( - .in_i(raddr_onehot_b), - .out_o(raddr_onehot_b_buf) - ); - - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - // Check the one-hot encoded signals for glitches. - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .OneHotWidth(NUM_WORDS), - .AddrCheck(1), - // When AddrCheck=1 also EnableCheck needs to be 1. - .EnableCheck(1) - ) u_prim_onehot_check_raddr_a ( - .clk_i, - .rst_ni, - .oh_i (raddr_onehot_a_buf), - .addr_i (raddr_a_int), - // Set enable=1 as address is always valid. - .en_i (1'b1), - .err_o (oh_raddr_a_err) - ); - - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .OneHotWidth(NUM_WORDS), - .AddrCheck(1), - // When AddrCheck=1 also EnableCheck needs to be 1. - .EnableCheck(1) - ) u_prim_onehot_check_raddr_b ( - .clk_i, - .rst_ni, - .oh_i (raddr_onehot_b_buf), - .addr_i (raddr_b_int), - // Set enable=1 as address is always valid. - .en_i (1'b1), - .err_o (oh_raddr_b_err) - ); - - // MUX register to rdata_a/b_o according to raddr_a/b_onehot. - prim_onehot_mux #( - .Width(DataWidth), - .Inputs(NUM_WORDS) - ) u_rdata_a_mux ( - .clk_i, - .rst_ni, - .in_i (mem), - .sel_i (raddr_onehot_a), - .out_o (rdata_a_o) - ); - - prim_onehot_mux #( - .Width(DataWidth), - .Inputs(NUM_WORDS) - ) u_rdata_b_mux ( - .clk_i, - .rst_ni, - .in_i (mem), - .sel_i (raddr_onehot_b), - .out_o (rdata_b_o) - ); - end else begin : gen_no_rdata_mux_check - assign rdata_a_o = mem[raddr_a_int]; - assign rdata_b_o = mem[raddr_b_int]; - assign oh_raddr_a_err = 1'b0; - assign oh_raddr_b_err = 1'b0; - end + assign rdata_a_o = mem[raddr_a_int]; + assign rdata_b_o = mem[raddr_b_int]; /////////// // WRITE // @@ -203,36 +98,9 @@ module ibex_register_file_latch #( end end - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - // This checks for spurious WE strobes on the regfile. - if (WrenCheck) begin : gen_wren_check - // Buffer the decoded write enable bits so that the checker - // is not optimized into the address decoding logic. - logic [NUM_WORDS-1:0] waddr_onehot_a_buf; - prim_buf #( - .Width(NUM_WORDS) - ) u_prim_buf ( - .in_i(waddr_onehot_a), - .out_o(waddr_onehot_a_buf) - ); - prim_onehot_check #( - .AddrWidth(ADDR_WIDTH), - .AddrCheck(1), - .EnableCheck(1) - ) u_prim_onehot_check ( - .clk_i, - .rst_ni, - .oh_i(waddr_onehot_a_buf), - .addr_i(waddr_a_i), - .en_i(we_a_i), - .err_o(oh_we_err) - ); - end else begin : gen_no_wren_check - logic unused_strobe; - assign unused_strobe = waddr_onehot_a[0]; // this is never read from in this case - assign oh_we_err = 1'b0; - end + logic unused_strobe; + assign unused_strobe = waddr_onehot_a[0]; // this is never read from in this case // Individual clock gating (if integrated clock-gating cells are available) for (genvar x = 1; x < NUM_WORDS; x++) begin : gen_cg_word_iter diff --git a/rtl/ibex_top.sv b/rtl/ibex_top.sv index 20a8822d00..3bf55a8c69 100644 --- a/rtl/ibex_top.sv +++ b/rtl/ibex_top.sv @@ -168,10 +168,10 @@ module ibex_top import ibex_pkg::*; #( localparam bit Lockstep = SecureIbex; localparam bit ResetAll = Lockstep; localparam bit DummyInstructions = SecureIbex; - localparam bit RegFileECC = SecureIbex; - localparam bit RegFileWrenCheck = SecureIbex; - localparam bit RegFileRdataMuxCheck = SecureIbex; - localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32; + localparam bit RegFileECC = 0; + localparam bit RegFileLockstepECC = Lockstep; + localparam int unsigned RegFileDataWidth = 32; + localparam int unsigned RegFileDataEccWidth = 32 + 7; localparam bit MemECC = SecureIbex; localparam int unsigned MemDataWidth = MemECC ? 32 + 7 : 32; // Icache parameters @@ -193,9 +193,9 @@ module ibex_top import ibex_pkg::*; #( logic [4:0] rf_raddr_b; logic [4:0] rf_waddr_wb; logic rf_we_wb; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc, rf_rdata_a_ecc_buf; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc, rf_rdata_b_ecc_buf; + logic [RegFileDataWidth-1:0] rf_wdata_wb; + logic [RegFileDataWidth-1:0] rf_rdata_a; + logic [RegFileDataWidth-1:0] rf_rdata_b; // Combined data and integrity for data and instruction busses logic [MemDataWidth-1:0] data_wdata_core; @@ -277,17 +277,6 @@ module ibex_top import ibex_pkg::*; #( .out_o(fetch_enable_buf) ); - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_a_ecc_buf ( - .in_i (rf_rdata_a_ecc), - .out_o(rf_rdata_a_ecc_buf) - ); - - prim_buf #(.Width(RegFileDataWidth)) u_rf_rdata_b_ecc_buf ( - .in_i (rf_rdata_b_ecc), - .out_o(rf_rdata_b_ecc_buf) - ); - - // ibex_core takes integrity and data bits together. Combine the separate integrity and data // inputs here. assign data_rdata_core[31:0] = data_rdata_i; @@ -370,9 +359,9 @@ module ibex_top import ibex_pkg::*; #( .rf_raddr_b_o (rf_raddr_b), .rf_waddr_wb_o (rf_waddr_wb), .rf_we_wb_o (rf_we_wb), - .rf_wdata_wb_ecc_o(rf_wdata_wb_ecc), - .rf_rdata_a_ecc_i (rf_rdata_a_ecc_buf), - .rf_rdata_b_ecc_i (rf_rdata_b_ecc_buf), + .rf_wdata_wb_ecc_o(rf_wdata_wb), + .rf_rdata_a_ecc_i (rf_rdata_a), + .rf_rdata_b_ecc_i (rf_rdata_b), .ic_tag_req_o (ic_tag_req), .ic_tag_write_o (ic_tag_write), @@ -450,15 +439,11 @@ module ibex_top import ibex_pkg::*; #( // Register file Instantiation // ///////////////////////////////// - logic rf_alert_major_internal; if (RegFile == RegFileFF) begin : gen_regfile_ff ibex_register_file_ff #( .RV32E (RV32E), .DataWidth (RegFileDataWidth), .DummyInstructions(DummyInstructions), - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - .WrenCheck (RegFileWrenCheck), - .RdataMuxCheck (RegFileRdataMuxCheck), .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) ) register_file_i ( .clk_i (clk), @@ -469,22 +454,18 @@ module ibex_top import ibex_pkg::*; #( .dummy_instr_wb_i(dummy_instr_wb), .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), + .rdata_a_o(rf_rdata_a), .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), + .rdata_b_o(rf_rdata_b), .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb), - .err_o (rf_alert_major_internal) + .wdata_a_i(rf_wdata_wb), + .we_a_i (rf_we_wb) ); end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga ibex_register_file_fpga #( .RV32E (RV32E), .DataWidth (RegFileDataWidth), .DummyInstructions(DummyInstructions), - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - .WrenCheck (RegFileWrenCheck), - .RdataMuxCheck (RegFileRdataMuxCheck), .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) ) register_file_i ( .clk_i (clk), @@ -495,22 +476,18 @@ module ibex_top import ibex_pkg::*; #( .dummy_instr_wb_i(dummy_instr_wb), .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), + .rdata_a_o(rf_rdata_a), .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), + .rdata_b_o(rf_rdata_b), .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb), - .err_o (rf_alert_major_internal) + .wdata_a_i(rf_wdata_wb), + .we_a_i (rf_we_wb) ); end else if (RegFile == RegFileLatch) begin : gen_regfile_latch ibex_register_file_latch #( .RV32E (RV32E), .DataWidth (RegFileDataWidth), .DummyInstructions(DummyInstructions), - // SEC_CM: DATA_REG_SW.GLITCH_DETECT - .WrenCheck (RegFileWrenCheck), - .RdataMuxCheck (RegFileRdataMuxCheck), .WordZeroVal (RegFileDataWidth'(prim_secded_pkg::SecdedInv3932ZeroWord)) ) register_file_i ( .clk_i (clk), @@ -521,13 +498,12 @@ module ibex_top import ibex_pkg::*; #( .dummy_instr_wb_i(dummy_instr_wb), .raddr_a_i(rf_raddr_a), - .rdata_a_o(rf_rdata_a_ecc), + .rdata_a_o(rf_rdata_a), .raddr_b_i(rf_raddr_b), - .rdata_b_o(rf_rdata_b_ecc), + .rdata_b_o(rf_rdata_b), .waddr_a_i(rf_waddr_wb), - .wdata_a_i(rf_wdata_wb_ecc), - .we_a_i (rf_we_wb), - .err_o (rf_alert_major_internal) + .wdata_a_i(rf_wdata_wb), + .we_a_i (rf_we_wb) ); end @@ -811,15 +787,8 @@ module ibex_top import ibex_pkg::*; #( data_wdata_core, data_rdata_core, data_err_i, - dummy_instr_id, - dummy_instr_wb, - rf_raddr_a, - rf_raddr_b, - rf_waddr_wb, - rf_we_wb, - rf_wdata_wb_ecc, - rf_rdata_a_ecc, - rf_rdata_b_ecc, + rf_rdata_a, + rf_rdata_b, ic_tag_req, ic_tag_write, ic_tag_addr, @@ -865,15 +834,8 @@ module ibex_top import ibex_pkg::*; #( logic [MemDataWidth-1:0] data_rdata_local; logic data_err_local; - logic dummy_instr_id_local; - logic dummy_instr_wb_local; - logic [4:0] rf_raddr_a_local; - logic [4:0] rf_raddr_b_local; - logic [4:0] rf_waddr_wb_local; - logic rf_we_wb_local; - logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_local; - logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_local; - logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_local; + logic [RegFileDataWidth-1:0] rf_rdata_a_local; + logic [RegFileDataWidth-1:0] rf_rdata_b_local; logic [IC_NUM_WAYS-1:0] ic_tag_req_local; logic ic_tag_write_local; @@ -918,15 +880,8 @@ module ibex_top import ibex_pkg::*; #( data_wdata_core, data_rdata_core, data_err_i, - dummy_instr_id, - dummy_instr_wb, - rf_raddr_a, - rf_raddr_b, - rf_waddr_wb, - rf_we_wb, - rf_wdata_wb_ecc, - rf_rdata_a_ecc, - rf_rdata_b_ecc, + rf_rdata_a, + rf_rdata_b, ic_tag_req, ic_tag_write, ic_tag_addr, @@ -968,15 +923,8 @@ module ibex_top import ibex_pkg::*; #( data_wdata_local, data_rdata_local, data_err_local, - dummy_instr_id_local, - dummy_instr_wb_local, - rf_raddr_a_local, - rf_raddr_b_local, - rf_waddr_wb_local, - rf_we_wb_local, - rf_wdata_wb_ecc_local, - rf_rdata_a_ecc_local, - rf_rdata_b_ecc_local, + rf_rdata_a_local, + rf_rdata_b_local, ic_tag_req_local, ic_tag_write_local, ic_tag_addr_local, @@ -1023,42 +971,44 @@ module ibex_top import ibex_pkg::*; #( logic lockstep_alert_major_bus_local; ibex_lockstep #( - .PMPEnable (PMPEnable), - .PMPGranularity (PMPGranularity), - .PMPNumRegions (PMPNumRegions), - .PMPRstCfg (PMPRstCfg), - .PMPRstAddr (PMPRstAddr), - .PMPRstMsecCfg (PMPRstMsecCfg), - .MHPMCounterNum (MHPMCounterNum), - .MHPMCounterWidth (MHPMCounterWidth), - .RV32E (RV32E), - .RV32M (RV32M), - .RV32B (RV32B), - .RV32ZC (RV32ZC), - .BranchTargetALU (BranchTargetALU), - .ICache (ICache), - .ICacheECC (ICacheECC), - .BusSizeECC (BusSizeECC), - .TagSizeECC (TagSizeECC), - .LineSizeECC (LineSizeECC), - .BranchPredictor (BranchPredictor), - .DbgTriggerEn (DbgTriggerEn), - .DbgHwBreakNum (DbgHwBreakNum), - .WritebackStage (WritebackStage), - .ResetAll (ResetAll), - .RndCnstLfsrSeed (RndCnstLfsrSeed), - .RndCnstLfsrPerm (RndCnstLfsrPerm), - .SecureIbex (SecureIbex), - .DummyInstructions(DummyInstructions), - .RegFileECC (RegFileECC), - .RegFileDataWidth (RegFileDataWidth), - .MemECC (MemECC), - .DmBaseAddr (DmBaseAddr), - .DmAddrMask (DmAddrMask), - .DmHaltAddr (DmHaltAddr), - .DmExceptionAddr (DmExceptionAddr), - .CsrMvendorId (CsrMvendorId), - .CsrMimpId (CsrMimpId) + .PMPEnable (PMPEnable), + .PMPGranularity (PMPGranularity), + .PMPNumRegions (PMPNumRegions), + .PMPRstCfg (PMPRstCfg), + .PMPRstAddr (PMPRstAddr), + .PMPRstMsecCfg (PMPRstMsecCfg), + .MHPMCounterNum (MHPMCounterNum), + .MHPMCounterWidth (MHPMCounterWidth), + .RV32E (RV32E), + .RV32M (RV32M), + .RV32B (RV32B), + .RV32ZC (RV32ZC), + .BranchTargetALU (BranchTargetALU), + .ICache (ICache), + .ICacheECC (ICacheECC), + .BusSizeECC (BusSizeECC), + .TagSizeECC (TagSizeECC), + .LineSizeECC (LineSizeECC), + .BranchPredictor (BranchPredictor), + .DbgTriggerEn (DbgTriggerEn), + .DbgHwBreakNum (DbgHwBreakNum), + .WritebackStage (WritebackStage), + .ResetAll (ResetAll), + .RndCnstLfsrSeed (RndCnstLfsrSeed), + .RndCnstLfsrPerm (RndCnstLfsrPerm), + .SecureIbex (SecureIbex), + .DummyInstructions (DummyInstructions), + .RegFileECC (RegFileLockstepECC), + .RegFileDataWidth (RegFileDataWidth), + .RegFileDataEccWidth (RegFileDataEccWidth), + .RegFile (RegFile), + .MemECC (MemECC), + .DmBaseAddr (DmBaseAddr), + .DmAddrMask (DmAddrMask), + .DmHaltAddr (DmHaltAddr), + .DmExceptionAddr (DmExceptionAddr), + .CsrMvendorId (CsrMvendorId), + .CsrMimpId (CsrMimpId) ) u_ibex_lockstep ( .clk_i (clk), .rst_ni (rst_ni), @@ -1083,15 +1033,8 @@ module ibex_top import ibex_pkg::*; #( .data_rdata_i (data_rdata_local), .data_err_i (data_err_local), - .dummy_instr_id_i (dummy_instr_id_local), - .dummy_instr_wb_i (dummy_instr_wb_local), - .rf_raddr_a_i (rf_raddr_a_local), - .rf_raddr_b_i (rf_raddr_b_local), - .rf_waddr_wb_i (rf_waddr_wb_local), - .rf_we_wb_i (rf_we_wb_local), - .rf_wdata_wb_ecc_i (rf_wdata_wb_ecc_local), - .rf_rdata_a_ecc_i (rf_rdata_a_ecc_local), - .rf_rdata_b_ecc_i (rf_rdata_b_ecc_local), + .rf_rdata_a_i (rf_rdata_a_local), + .rf_rdata_b_i (rf_rdata_b_local), .ic_tag_req_i (ic_tag_req_local), .ic_tag_write_i (ic_tag_write_local), @@ -1156,7 +1099,6 @@ module ibex_top import ibex_pkg::*; #( assign alert_major_internal_o = core_alert_major_internal | lockstep_alert_major_internal | - rf_alert_major_internal | icache_alert_major_internal; assign alert_major_bus_o = core_alert_major_bus | lockstep_alert_major_bus; assign alert_minor_o = core_alert_minor | lockstep_alert_minor; diff --git a/syn/syn_yosys.sh b/syn/syn_yosys.sh index cca9e7644f..6281dde62b 100755 --- a/syn/syn_yosys.sh +++ b/syn/syn_yosys.sh @@ -34,9 +34,6 @@ source syn_setup.sh LR_DEP_SOURCES=( "../vendor/lowrisc_ip/ip/prim/rtl/prim_count.sv" - "../vendor/lowrisc_ip/ip/prim/rtl/prim_onehot_check.sv" - "../vendor/lowrisc_ip/ip/prim/rtl/prim_onehot_enc.sv" - "../vendor/lowrisc_ip/ip/prim/rtl/prim_onehot_mux.sv" "../vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_dec.sv" "../vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv" "../vendor/lowrisc_ip/ip/prim/rtl/prim_lfsr.sv"