@@ -39,6 +39,8 @@ module ibex_lockstep import ibex_pkg::*; #(
3939 parameter bit DummyInstructions = 1'b0 ,
4040 parameter bit RegFileECC = 1'b0 ,
4141 parameter int unsigned RegFileDataWidth = 32 ,
42+ parameter int unsigned RegFileDataEccWidth = 39 ,
43+ parameter regfile_e RegFile = RegFileFF,
4244 parameter bit MemECC = 1'b0 ,
4345 parameter int unsigned MemDataWidth = MemECC ? 32 + 7 : 32 ,
4446 parameter int unsigned DmBaseAddr = 32'h1A110000 ,
@@ -73,15 +75,8 @@ module ibex_lockstep import ibex_pkg::*; #(
7375 input logic [MemDataWidth- 1 : 0 ] data_rdata_i,
7476 input logic data_err_i,
7577
76- input logic dummy_instr_id_i,
77- input logic dummy_instr_wb_i,
78- input logic [4 : 0 ] rf_raddr_a_i,
79- input logic [4 : 0 ] rf_raddr_b_i,
80- input logic [4 : 0 ] rf_waddr_wb_i,
81- input logic rf_we_wb_i,
82- input logic [RegFileDataWidth- 1 : 0 ] rf_wdata_wb_ecc_i,
83- input logic [RegFileDataWidth- 1 : 0 ] rf_rdata_a_ecc_i,
84- input logic [RegFileDataWidth- 1 : 0 ] rf_rdata_b_ecc_i,
78+ input logic [RegFileDataWidth- 1 : 0 ] rf_rdata_a_i,
79+ input logic [RegFileDataWidth- 1 : 0 ] rf_rdata_b_i,
8580
8681 input logic [IC_NUM_WAYS - 1 : 0 ] ic_tag_req_i,
8782 input logic ic_tag_write_i,
@@ -116,6 +111,8 @@ module ibex_lockstep import ibex_pkg::*; #(
116111 input logic scan_rst_ni
117112);
118113
114+ import prim_secded_pkg :: SecdedInv3932ZeroWord;
115+
119116 localparam int unsigned LockstepOffsetW = prim_util_pkg :: vbits (LockstepOffset);
120117 // Core outputs are delayed for an extra cycle due to shadow output registers
121118 localparam int unsigned OutputsOffset = LockstepOffset + 1 ;
@@ -230,8 +227,8 @@ module ibex_lockstep import ibex_pkg::*; #(
230227 logic data_rvalid;
231228 logic [MemDataWidth- 1 : 0 ] data_rdata;
232229 logic data_err;
233- logic [RegFileDataWidth- 1 : 0 ] rf_rdata_a_ecc ;
234- logic [RegFileDataWidth- 1 : 0 ] rf_rdata_b_ecc ;
230+ logic [RegFileDataWidth- 1 : 0 ] rf_rdata_a ;
231+ logic [RegFileDataWidth- 1 : 0 ] rf_rdata_b ;
235232 logic irq_software;
236233 logic irq_timer;
237234 logic irq_external;
@@ -310,8 +307,8 @@ module ibex_lockstep import ibex_pkg::*; #(
310307 assign shadow_inputs_in.data_rvalid = data_rvalid_i;
311308 assign shadow_inputs_in.data_rdata = data_rdata_i;
312309 assign shadow_inputs_in.data_err = data_err_i;
313- assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i ;
314- assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i ;
310+ assign shadow_inputs_in.rf_rdata_a = rf_rdata_a_i ;
311+ assign shadow_inputs_in.rf_rdata_b = rf_rdata_b_i ;
315312 assign shadow_inputs_in.irq_software = irq_software_i;
316313 assign shadow_inputs_in.irq_timer = irq_timer_i;
317314 assign shadow_inputs_in.irq_external = irq_external_i;
@@ -326,33 +323,26 @@ module ibex_lockstep import ibex_pkg::*; #(
326323 // /////////////////
327324
328325 typedef struct packed {
329- logic instr_req;
330- logic [31 : 0 ] instr_addr;
331- logic data_req;
332- logic data_we;
333- logic [3 : 0 ] data_be;
334- logic [31 : 0 ] data_addr;
335- logic [MemDataWidth- 1 : 0 ] data_wdata;
336- logic dummy_instr_id;
337- logic dummy_instr_wb;
338- logic [4 : 0 ] rf_raddr_a;
339- logic [4 : 0 ] rf_raddr_b;
340- logic [4 : 0 ] rf_waddr_wb;
341- logic rf_we_wb;
342- logic [RegFileDataWidth- 1 : 0 ] rf_wdata_wb_ecc;
343- logic [IC_NUM_WAYS - 1 : 0 ] ic_tag_req;
344- logic ic_tag_write;
345- logic [IC_INDEX_W - 1 : 0 ] ic_tag_addr;
346- logic [TagSizeECC- 1 : 0 ] ic_tag_wdata;
347- logic [IC_NUM_WAYS - 1 : 0 ] ic_data_req;
348- logic ic_data_write;
349- logic [IC_INDEX_W - 1 : 0 ] ic_data_addr;
350- logic [LineSizeECC- 1 : 0 ] ic_data_wdata;
351- logic ic_scr_key_req;
352- logic irq_pending;
353- crash_dump_t crash_dump;
354- logic double_fault_seen;
355- ibex_mubi_t core_busy;
326+ logic instr_req;
327+ logic [31 : 0 ] instr_addr;
328+ logic data_req;
329+ logic data_we;
330+ logic [3 : 0 ] data_be;
331+ logic [31 : 0 ] data_addr;
332+ logic [MemDataWidth- 1 : 0 ] data_wdata;
333+ logic [IC_NUM_WAYS - 1 : 0 ] ic_tag_req;
334+ logic ic_tag_write;
335+ logic [IC_INDEX_W - 1 : 0 ] ic_tag_addr;
336+ logic [TagSizeECC- 1 : 0 ] ic_tag_wdata;
337+ logic [IC_NUM_WAYS - 1 : 0 ] ic_data_req;
338+ logic ic_data_write;
339+ logic [IC_INDEX_W - 1 : 0 ] ic_data_addr;
340+ logic [LineSizeECC- 1 : 0 ] ic_data_wdata;
341+ logic ic_scr_key_req;
342+ logic irq_pending;
343+ crash_dump_t crash_dump;
344+ logic double_fault_seen;
345+ ibex_mubi_t core_busy;
356346 } delayed_outputs_t ;
357347
358348 delayed_outputs_t [OutputsOffset- 1 : 0 ] core_outputs_q;
@@ -367,13 +357,6 @@ module ibex_lockstep import ibex_pkg::*; #(
367357 assign core_outputs_in.data_be = data_be_i;
368358 assign core_outputs_in.data_addr = data_addr_i;
369359 assign core_outputs_in.data_wdata = data_wdata_i;
370- assign core_outputs_in.dummy_instr_id = dummy_instr_id_i;
371- assign core_outputs_in.dummy_instr_wb = dummy_instr_wb_i;
372- assign core_outputs_in.rf_raddr_a = rf_raddr_a_i;
373- assign core_outputs_in.rf_raddr_b = rf_raddr_b_i;
374- assign core_outputs_in.rf_waddr_wb = rf_waddr_wb_i;
375- assign core_outputs_in.rf_we_wb = rf_we_wb_i;
376- assign core_outputs_in.rf_wdata_wb_ecc = rf_wdata_wb_ecc_i;
377360 assign core_outputs_in.ic_tag_req = ic_tag_req_i;
378361 assign core_outputs_in.ic_tag_write = ic_tag_write_i;
379362 assign core_outputs_in.ic_tag_addr = ic_tag_addr_i;
@@ -396,50 +379,65 @@ module ibex_lockstep import ibex_pkg::*; #(
396379 core_outputs_q[OutputsOffset- 1 ] <= core_outputs_in;
397380 end
398381
382+ // The following outputs are generated by the shadow core and directly fed into the shadow core
383+ // register file. There is no need to compare those signals against the signals generated by the
384+ // main core in the lockstep comparison. A fault into one of those signals will cause a mismatch
385+ // in the main core and shadow core register file instances. As the outputs of both register
386+ // files are combined, the ECC checker inside the shadow core will detect the fault.
387+ logic [RegFileDataEccWidth- 1 : 0 ] shadow_rf_wdata_wb_ecc;
388+ logic [4 : 0 ] shadow_rf_raddr_a;
389+ logic [4 : 0 ] shadow_rf_raddr_b;
390+ logic [4 : 0 ] shadow_rf_waddr_wb;
391+ logic shadow_rf_we_wb;
392+ logic shadow_dummy_instr_id;
393+ logic shadow_dummy_instr_wb;
394+
399395 // /////////////////////////////
400396 // Shadow core instantiation //
401397 // /////////////////////////////
402398
403399 logic shadow_alert_minor, shadow_alert_major_internal, shadow_alert_major_bus;
400+ logic [RegFileDataEccWidth - RegFileDataWidth - 1 : 0 ] shadow_rf_rdata_a_intg;
401+ logic [RegFileDataEccWidth - RegFileDataWidth - 1 : 0 ] shadow_rf_rdata_b_intg;
404402
405403 ibex_core # (
406- .PMPEnable ( PMPEnable ),
407- .PMPGranularity ( PMPGranularity ),
408- .PMPNumRegions ( PMPNumRegions ),
409- .PMPRstCfg ( PMPRstCfg ),
410- .PMPRstAddr ( PMPRstAddr ),
411- .PMPRstMsecCfg ( PMPRstMsecCfg ),
412- .MHPMCounterNum ( MHPMCounterNum ),
413- .MHPMCounterWidth ( MHPMCounterWidth ),
414- .RV32E ( RV32E ),
415- .RV32M ( RV32M ),
416- .RV32B ( RV32B ),
417- .RV32ZC ( RV32ZC ),
418- .BranchTargetALU ( BranchTargetALU ),
419- .ICache ( ICache ),
420- .ICacheECC ( ICacheECC ),
421- .BusSizeECC ( BusSizeECC ),
422- .TagSizeECC ( TagSizeECC ),
423- .LineSizeECC ( LineSizeECC ),
424- .BranchPredictor ( BranchPredictor ),
425- .DbgTriggerEn ( DbgTriggerEn ),
426- .DbgHwBreakNum ( DbgHwBreakNum ),
427- .WritebackStage ( WritebackStage ),
428- .ResetAll ( ResetAll ),
429- .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
430- .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
431- .SecureIbex ( SecureIbex ),
432- .DummyInstructions ( DummyInstructions ),
433- .RegFileECC ( RegFileECC ),
434- .RegFileDataWidth ( RegFileDataWidth ),
435- .MemECC ( MemECC ),
436- .MemDataWidth ( MemDataWidth ),
437- .DmBaseAddr ( DmBaseAddr ),
438- .DmAddrMask ( DmAddrMask ),
439- .DmHaltAddr ( DmHaltAddr ),
440- .DmExceptionAddr ( DmExceptionAddr ),
441- .CsrMvendorId ( CsrMvendorId ),
442- .CsrMimpId ( CsrMimpId )
404+ .PMPEnable ( PMPEnable ),
405+ .PMPGranularity ( PMPGranularity ),
406+ .PMPNumRegions ( PMPNumRegions ),
407+ .PMPRstCfg ( PMPRstCfg ),
408+ .PMPRstAddr ( PMPRstAddr ),
409+ .PMPRstMsecCfg ( PMPRstMsecCfg ),
410+ .MHPMCounterNum ( MHPMCounterNum ),
411+ .MHPMCounterWidth ( MHPMCounterWidth ),
412+ .RV32E ( RV32E ),
413+ .RV32M ( RV32M ),
414+ .RV32B ( RV32B ),
415+ .RV32ZC ( RV32ZC ),
416+ .BranchTargetALU ( BranchTargetALU ),
417+ .ICache ( ICache ),
418+ .ICacheECC ( ICacheECC ),
419+ .BusSizeECC ( BusSizeECC ),
420+ .TagSizeECC ( TagSizeECC ),
421+ .LineSizeECC ( LineSizeECC ),
422+ .BranchPredictor ( BranchPredictor ),
423+ .DbgTriggerEn ( DbgTriggerEn ),
424+ .DbgHwBreakNum ( DbgHwBreakNum ),
425+ .WritebackStage ( WritebackStage ),
426+ .ResetAll ( ResetAll ),
427+ .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
428+ .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
429+ .SecureIbex ( SecureIbex ),
430+ .DummyInstructions ( DummyInstructions ),
431+ .RegFileECC ( RegFileECC ),
432+ .RegFileDataWidth ( RegFileDataEccWidth ),
433+ .MemECC ( MemECC ),
434+ .MemDataWidth ( MemDataWidth ),
435+ .DmBaseAddr ( DmBaseAddr ),
436+ .DmAddrMask ( DmAddrMask ),
437+ .DmHaltAddr ( DmHaltAddr ),
438+ .DmExceptionAddr ( DmExceptionAddr ),
439+ .CsrMvendorId ( CsrMvendorId ),
440+ .CsrMimpId ( CsrMimpId )
443441 ) u_shadow_core (
444442 .clk_i (clk_i),
445443 .rst_ni (rst_shadow_n),
@@ -464,15 +462,15 @@ module ibex_lockstep import ibex_pkg::*; #(
464462 .data_rdata_i (shadow_inputs_q[0 ].data_rdata),
465463 .data_err_i (shadow_inputs_q[0 ].data_err),
466464
467- .dummy_instr_id_o (shadow_outputs_d.dummy_instr_id ),
468- .dummy_instr_wb_o (shadow_outputs_d.dummy_instr_wb ),
469- .rf_raddr_a_o (shadow_outputs_d.rf_raddr_a ),
470- .rf_raddr_b_o (shadow_outputs_d.rf_raddr_b ),
471- .rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb ),
472- .rf_we_wb_o (shadow_outputs_d.rf_we_wb ),
473- .rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc ),
474- .rf_rdata_a_ecc_i (shadow_inputs_q[0 ].rf_rdata_a_ecc ),
475- .rf_rdata_b_ecc_i (shadow_inputs_q[0 ].rf_rdata_b_ecc ),
465+ .dummy_instr_id_o (shadow_dummy_instr_id ),
466+ .dummy_instr_wb_o (shadow_dummy_instr_wb ),
467+ .rf_raddr_a_o (shadow_rf_raddr_a ),
468+ .rf_raddr_b_o (shadow_rf_raddr_b ),
469+ .rf_waddr_wb_o (shadow_rf_waddr_wb ),
470+ .rf_we_wb_o (shadow_rf_we_wb ),
471+ .rf_wdata_wb_ecc_o (shadow_rf_wdata_wb_ecc ),
472+ .rf_rdata_a_ecc_i ({ shadow_rf_rdata_a_intg, shadow_inputs_q[0 ].rf_rdata_a } ),
473+ .rf_rdata_b_ecc_i ({ shadow_rf_rdata_b_intg, shadow_inputs_q[0 ].rf_rdata_b } ),
476474
477475 .ic_tag_req_o (shadow_outputs_d.ic_tag_req),
478476 .ic_tag_write_o (shadow_outputs_d.ic_tag_write),
@@ -551,6 +549,83 @@ module ibex_lockstep import ibex_pkg::*; #(
551549 shadow_outputs_q <= shadow_outputs_d;
552550 end
553551
552+ // The lower RegFileDataWidth bits (which are the data bits) are not fed into the shadow
553+ // register file as they are handled by the main register file.
554+ logic [RegFileDataWidth- 1 : 0 ] unused_shadow_rf_wdata_wb_ecc;
555+ assign unused_shadow_rf_wdata_wb_ecc = shadow_rf_wdata_wb_ecc[RegFileDataWidth- 1 : 0 ];
556+
557+ // ////////////////////////
558+ // Shadow register file //
559+ // ////////////////////////
560+ // SEC_CM: DATA_REG_SW.GLITCH_DETECT
561+ if (RegFile == RegFileFF) begin : gen_shadow_regfile_ff
562+ ibex_register_file_ff # (
563+ .RV32E (RV32E ),
564+ .DataWidth (RegFileDataEccWidth - RegFileDataWidth),
565+ .DummyInstructions (DummyInstructions),
566+ .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth- 1 : RegFileDataWidth])
567+ ) register_file_shadow_i (
568+ .clk_i (clk_i),
569+ .rst_ni (rst_shadow_n),
570+
571+ .test_en_i (test_en_i),
572+ .dummy_instr_id_i (shadow_dummy_instr_id),
573+ .dummy_instr_wb_i (shadow_dummy_instr_wb),
574+
575+ .raddr_a_i (shadow_rf_raddr_a),
576+ .rdata_a_o (shadow_rf_rdata_a_intg),
577+ .raddr_b_i (shadow_rf_raddr_b),
578+ .rdata_b_o (shadow_rf_rdata_b_intg),
579+ .waddr_a_i (shadow_rf_waddr_wb),
580+ .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth- 1 : RegFileDataWidth]),
581+ .we_a_i (shadow_rf_we_wb)
582+ );
583+ end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga
584+ ibex_register_file_fpga # (
585+ .RV32E (RV32E ),
586+ .DataWidth (RegFileDataEccWidth - RegFileDataWidth),
587+ .DummyInstructions (DummyInstructions),
588+ .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth- 1 : RegFileDataWidth])
589+ ) register_file_shadow_i (
590+ .clk_i (clk_i),
591+ .rst_ni (rst_shadow_n),
592+
593+ .test_en_i (test_en_i),
594+ .dummy_instr_id_i (shadow_dummy_instr_id),
595+ .dummy_instr_wb_i (shadow_dummy_instr_wb),
596+
597+ .raddr_a_i (shadow_rf_raddr_a),
598+ .rdata_a_o (shadow_rf_rdata_a_intg),
599+ .raddr_b_i (shadow_rf_raddr_b),
600+ .rdata_b_o (shadow_rf_rdata_b_intg),
601+ .waddr_a_i (shadow_rf_waddr_wb),
602+ .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth- 1 : RegFileDataWidth]),
603+ .we_a_i (shadow_rf_we_wb)
604+ );
605+ end else if (RegFile == RegFileLatch) begin : gen_regfile_latch
606+ ibex_register_file_latch # (
607+ .RV32E (RV32E ),
608+ .DataWidth (RegFileDataEccWidth - RegFileDataWidth),
609+ .DummyInstructions (DummyInstructions),
610+ .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth- 1 : RegFileDataWidth])
611+ ) register_file_shadow_i (
612+ .clk_i (clk_i),
613+ .rst_ni (rst_shadow_n),
614+
615+ .test_en_i (test_en_i),
616+ .dummy_instr_id_i (shadow_dummy_instr_id),
617+ .dummy_instr_wb_i (shadow_dummy_instr_wb),
618+
619+ .raddr_a_i (shadow_rf_raddr_a),
620+ .rdata_a_o (shadow_rf_rdata_a_intg),
621+ .raddr_b_i (shadow_rf_raddr_b),
622+ .rdata_b_o (shadow_rf_rdata_b_intg),
623+ .waddr_a_i (shadow_rf_waddr_wb),
624+ .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth- 1 : RegFileDataWidth]),
625+ .we_a_i (shadow_rf_we_wb)
626+ );
627+ end
628+
554629 // ///////////////////////
555630 // Compare the outputs //
556631 // ///////////////////////
0 commit comments