@@ -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 = $clog2 (LockstepOffset);
120117 // Core outputs are delayed for an extra cycle due to shadow output registers
121118 localparam int unsigned OutputsOffset = LockstepOffset + 1 ;
@@ -210,8 +207,8 @@ module ibex_lockstep import ibex_pkg::*; #(
210207 logic data_rvalid;
211208 logic [MemDataWidth- 1 : 0 ] data_rdata;
212209 logic data_err;
213- logic [RegFileDataWidth- 1 : 0 ] rf_rdata_a_ecc ;
214- logic [RegFileDataWidth- 1 : 0 ] rf_rdata_b_ecc ;
210+ logic [RegFileDataWidth- 1 : 0 ] rf_rdata_a ;
211+ logic [RegFileDataWidth- 1 : 0 ] rf_rdata_b ;
215212 logic irq_software;
216213 logic irq_timer;
217214 logic irq_external;
@@ -237,8 +234,8 @@ module ibex_lockstep import ibex_pkg::*; #(
237234 assign shadow_inputs_in.data_rvalid = data_rvalid_i;
238235 assign shadow_inputs_in.data_rdata = data_rdata_i;
239236 assign shadow_inputs_in.data_err = data_err_i;
240- assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i ;
241- assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i ;
237+ assign shadow_inputs_in.rf_rdata_a = rf_rdata_a_i ;
238+ assign shadow_inputs_in.rf_rdata_b = rf_rdata_b_i ;
242239 assign shadow_inputs_in.irq_software = irq_software_i;
243240 assign shadow_inputs_in.irq_timer = irq_timer_i;
244241 assign shadow_inputs_in.irq_external = irq_external_i;
@@ -273,33 +270,26 @@ module ibex_lockstep import ibex_pkg::*; #(
273270 // /////////////////
274271
275272 typedef struct packed {
276- logic instr_req;
277- logic [31 : 0 ] instr_addr;
278- logic data_req;
279- logic data_we;
280- logic [3 : 0 ] data_be;
281- logic [31 : 0 ] data_addr;
282- logic [MemDataWidth- 1 : 0 ] data_wdata;
283- logic dummy_instr_id;
284- logic dummy_instr_wb;
285- logic [4 : 0 ] rf_raddr_a;
286- logic [4 : 0 ] rf_raddr_b;
287- logic [4 : 0 ] rf_waddr_wb;
288- logic rf_we_wb;
289- logic [RegFileDataWidth- 1 : 0 ] rf_wdata_wb_ecc;
290- logic [IC_NUM_WAYS - 1 : 0 ] ic_tag_req;
291- logic ic_tag_write;
292- logic [IC_INDEX_W - 1 : 0 ] ic_tag_addr;
293- logic [TagSizeECC- 1 : 0 ] ic_tag_wdata;
294- logic [IC_NUM_WAYS - 1 : 0 ] ic_data_req;
295- logic ic_data_write;
296- logic [IC_INDEX_W - 1 : 0 ] ic_data_addr;
297- logic [LineSizeECC- 1 : 0 ] ic_data_wdata;
298- logic ic_scr_key_req;
299- logic irq_pending;
300- crash_dump_t crash_dump;
301- logic double_fault_seen;
302- ibex_mubi_t core_busy;
273+ logic instr_req;
274+ logic [31 : 0 ] instr_addr;
275+ logic data_req;
276+ logic data_we;
277+ logic [3 : 0 ] data_be;
278+ logic [31 : 0 ] data_addr;
279+ logic [MemDataWidth- 1 : 0 ] data_wdata;
280+ logic [IC_NUM_WAYS - 1 : 0 ] ic_tag_req;
281+ logic ic_tag_write;
282+ logic [IC_INDEX_W - 1 : 0 ] ic_tag_addr;
283+ logic [TagSizeECC- 1 : 0 ] ic_tag_wdata;
284+ logic [IC_NUM_WAYS - 1 : 0 ] ic_data_req;
285+ logic ic_data_write;
286+ logic [IC_INDEX_W - 1 : 0 ] ic_data_addr;
287+ logic [LineSizeECC- 1 : 0 ] ic_data_wdata;
288+ logic ic_scr_key_req;
289+ logic irq_pending;
290+ crash_dump_t crash_dump;
291+ logic double_fault_seen;
292+ ibex_mubi_t core_busy;
303293 } delayed_outputs_t ;
304294
305295 delayed_outputs_t [OutputsOffset- 1 : 0 ] core_outputs_q;
@@ -314,13 +304,6 @@ module ibex_lockstep import ibex_pkg::*; #(
314304 assign core_outputs_in.data_be = data_be_i;
315305 assign core_outputs_in.data_addr = data_addr_i;
316306 assign core_outputs_in.data_wdata = data_wdata_i;
317- assign core_outputs_in.dummy_instr_id = dummy_instr_id_i;
318- assign core_outputs_in.dummy_instr_wb = dummy_instr_wb_i;
319- assign core_outputs_in.rf_raddr_a = rf_raddr_a_i;
320- assign core_outputs_in.rf_raddr_b = rf_raddr_b_i;
321- assign core_outputs_in.rf_waddr_wb = rf_waddr_wb_i;
322- assign core_outputs_in.rf_we_wb = rf_we_wb_i;
323- assign core_outputs_in.rf_wdata_wb_ecc = rf_wdata_wb_ecc_i;
324307 assign core_outputs_in.ic_tag_req = ic_tag_req_i;
325308 assign core_outputs_in.ic_tag_write = ic_tag_write_i;
326309 assign core_outputs_in.ic_tag_addr = ic_tag_addr_i;
@@ -343,50 +326,65 @@ module ibex_lockstep import ibex_pkg::*; #(
343326 core_outputs_q[OutputsOffset- 1 ] <= core_outputs_in;
344327 end
345328
329+ // The following outputs are generated by the shadow core and directly fed into the shadow core
330+ // register file. There is no need to compare those signals against the signals generated by the
331+ // main core in the lockstep comparison. A fault into one of those signals will cause a mismatch
332+ // in the main core and shadow core register file instances. As the outputs of both register
333+ // files are combined, the ECC checker inside the shadow core will detect the fault.
334+ logic [RegFileDataEccWidth- 1 : 0 ] shadow_rf_wdata_wb_ecc;
335+ logic [4 : 0 ] shadow_rf_raddr_a;
336+ logic [4 : 0 ] shadow_rf_raddr_b;
337+ logic [4 : 0 ] shadow_rf_waddr_wb;
338+ logic shadow_rf_we_wb;
339+ logic shadow_dummy_instr_id;
340+ logic shadow_dummy_instr_wb;
341+
346342 // /////////////////////////////
347343 // Shadow core instantiation //
348344 // /////////////////////////////
349345
350346 logic shadow_alert_minor, shadow_alert_major_internal, shadow_alert_major_bus;
347+ logic [RegFileDataEccWidth - RegFileDataWidth - 1 : 0 ] shadow_rf_rdata_a_intg;
348+ logic [RegFileDataEccWidth - RegFileDataWidth - 1 : 0 ] shadow_rf_rdata_b_intg;
351349
352350 ibex_core # (
353- .PMPEnable ( PMPEnable ),
354- .PMPGranularity ( PMPGranularity ),
355- .PMPNumRegions ( PMPNumRegions ),
356- .PMPRstCfg ( PMPRstCfg ),
357- .PMPRstAddr ( PMPRstAddr ),
358- .PMPRstMsecCfg ( PMPRstMsecCfg ),
359- .MHPMCounterNum ( MHPMCounterNum ),
360- .MHPMCounterWidth ( MHPMCounterWidth ),
361- .RV32E ( RV32E ),
362- .RV32M ( RV32M ),
363- .RV32B ( RV32B ),
364- .RV32ZC ( RV32ZC ),
365- .BranchTargetALU ( BranchTargetALU ),
366- .ICache ( ICache ),
367- .ICacheECC ( ICacheECC ),
368- .BusSizeECC ( BusSizeECC ),
369- .TagSizeECC ( TagSizeECC ),
370- .LineSizeECC ( LineSizeECC ),
371- .BranchPredictor ( BranchPredictor ),
372- .DbgTriggerEn ( DbgTriggerEn ),
373- .DbgHwBreakNum ( DbgHwBreakNum ),
374- .WritebackStage ( WritebackStage ),
375- .ResetAll ( ResetAll ),
376- .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
377- .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
378- .SecureIbex ( SecureIbex ),
379- .DummyInstructions ( DummyInstructions ),
380- .RegFileECC ( RegFileECC ),
381- .RegFileDataWidth ( RegFileDataWidth ),
382- .MemECC ( MemECC ),
383- .MemDataWidth ( MemDataWidth ),
384- .DmBaseAddr ( DmBaseAddr ),
385- .DmAddrMask ( DmAddrMask ),
386- .DmHaltAddr ( DmHaltAddr ),
387- .DmExceptionAddr ( DmExceptionAddr ),
388- .CsrMvendorId ( CsrMvendorId ),
389- .CsrMimpId ( CsrMimpId )
351+ .PMPEnable ( PMPEnable ),
352+ .PMPGranularity ( PMPGranularity ),
353+ .PMPNumRegions ( PMPNumRegions ),
354+ .PMPRstCfg ( PMPRstCfg ),
355+ .PMPRstAddr ( PMPRstAddr ),
356+ .PMPRstMsecCfg ( PMPRstMsecCfg ),
357+ .MHPMCounterNum ( MHPMCounterNum ),
358+ .MHPMCounterWidth ( MHPMCounterWidth ),
359+ .RV32E ( RV32E ),
360+ .RV32M ( RV32M ),
361+ .RV32B ( RV32B ),
362+ .RV32ZC ( RV32ZC ),
363+ .BranchTargetALU ( BranchTargetALU ),
364+ .ICache ( ICache ),
365+ .ICacheECC ( ICacheECC ),
366+ .BusSizeECC ( BusSizeECC ),
367+ .TagSizeECC ( TagSizeECC ),
368+ .LineSizeECC ( LineSizeECC ),
369+ .BranchPredictor ( BranchPredictor ),
370+ .DbgTriggerEn ( DbgTriggerEn ),
371+ .DbgHwBreakNum ( DbgHwBreakNum ),
372+ .WritebackStage ( WritebackStage ),
373+ .ResetAll ( ResetAll ),
374+ .RndCnstLfsrSeed ( RndCnstLfsrSeed ),
375+ .RndCnstLfsrPerm ( RndCnstLfsrPerm ),
376+ .SecureIbex ( SecureIbex ),
377+ .DummyInstructions ( DummyInstructions ),
378+ .RegFileECC ( RegFileECC ),
379+ .RegFileDataWidth ( RegFileDataEccWidth ),
380+ .MemECC ( MemECC ),
381+ .MemDataWidth ( MemDataWidth ),
382+ .DmBaseAddr ( DmBaseAddr ),
383+ .DmAddrMask ( DmAddrMask ),
384+ .DmHaltAddr ( DmHaltAddr ),
385+ .DmExceptionAddr ( DmExceptionAddr ),
386+ .CsrMvendorId ( CsrMvendorId ),
387+ .CsrMimpId ( CsrMimpId )
390388 ) u_shadow_core (
391389 .clk_i (clk_i),
392390 .rst_ni (rst_shadow_n),
@@ -411,15 +409,15 @@ module ibex_lockstep import ibex_pkg::*; #(
411409 .data_rdata_i (shadow_inputs_q[0 ].data_rdata),
412410 .data_err_i (shadow_inputs_q[0 ].data_err),
413411
414- .dummy_instr_id_o (shadow_outputs_d.dummy_instr_id ),
415- .dummy_instr_wb_o (shadow_outputs_d.dummy_instr_wb ),
416- .rf_raddr_a_o (shadow_outputs_d.rf_raddr_a ),
417- .rf_raddr_b_o (shadow_outputs_d.rf_raddr_b ),
418- .rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb ),
419- .rf_we_wb_o (shadow_outputs_d.rf_we_wb ),
420- .rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc ),
421- .rf_rdata_a_ecc_i (shadow_inputs_q[0 ].rf_rdata_a_ecc ),
422- .rf_rdata_b_ecc_i (shadow_inputs_q[0 ].rf_rdata_b_ecc ),
412+ .dummy_instr_id_o (shadow_dummy_instr_id ),
413+ .dummy_instr_wb_o (shadow_dummy_instr_wb ),
414+ .rf_raddr_a_o (shadow_rf_raddr_a ),
415+ .rf_raddr_b_o (shadow_rf_raddr_b ),
416+ .rf_waddr_wb_o (shadow_rf_waddr_wb ),
417+ .rf_we_wb_o (shadow_rf_we_wb ),
418+ .rf_wdata_wb_ecc_o (shadow_rf_wdata_wb_ecc ),
419+ .rf_rdata_a_ecc_i ({ shadow_rf_rdata_a_intg, shadow_inputs_q[0 ].rf_rdata_a } ),
420+ .rf_rdata_b_ecc_i ({ shadow_rf_rdata_b_intg, shadow_inputs_q[0 ].rf_rdata_b } ),
423421
424422 .ic_tag_req_o (shadow_outputs_d.ic_tag_req),
425423 .ic_tag_write_o (shadow_outputs_d.ic_tag_write),
@@ -498,6 +496,83 @@ module ibex_lockstep import ibex_pkg::*; #(
498496 shadow_outputs_q <= shadow_outputs_d;
499497 end
500498
499+ // The lower RegFileDataWidth bits (which are the data bits) are not fed into the shadow
500+ // register file as they are handled by the main register file.
501+ logic [RegFileDataWidth- 1 : 0 ] unused_shadow_rf_wdata_wb_ecc;
502+ assign unused_shadow_rf_wdata_wb_ecc = shadow_rf_wdata_wb_ecc[RegFileDataWidth- 1 : 0 ];
503+
504+ // ////////////////////////
505+ // Shadow register file //
506+ // ////////////////////////
507+ // SEC_CM: DATA_REG_SW.GLITCH_DETECT
508+ if (RegFile == RegFileFF) begin : gen_shadow_regfile_ff
509+ ibex_register_file_ff # (
510+ .RV32E (RV32E ),
511+ .DataWidth (RegFileDataEccWidth - RegFileDataWidth),
512+ .DummyInstructions (DummyInstructions),
513+ .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth- 1 : RegFileDataWidth])
514+ ) register_file_shadow_i (
515+ .clk_i (clk_i),
516+ .rst_ni (rst_shadow_n),
517+
518+ .test_en_i (test_en_i),
519+ .dummy_instr_id_i (shadow_dummy_instr_id),
520+ .dummy_instr_wb_i (shadow_dummy_instr_wb),
521+
522+ .raddr_a_i (shadow_rf_raddr_a),
523+ .rdata_a_o (shadow_rf_rdata_a_intg),
524+ .raddr_b_i (shadow_rf_raddr_b),
525+ .rdata_b_o (shadow_rf_rdata_b_intg),
526+ .waddr_a_i (shadow_rf_waddr_wb),
527+ .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth- 1 : RegFileDataWidth]),
528+ .we_a_i (shadow_rf_we_wb)
529+ );
530+ end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga
531+ ibex_register_file_fpga # (
532+ .RV32E (RV32E ),
533+ .DataWidth (RegFileDataEccWidth - RegFileDataWidth),
534+ .DummyInstructions (DummyInstructions),
535+ .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth- 1 : RegFileDataWidth])
536+ ) register_file_shadow_i (
537+ .clk_i (clk_i),
538+ .rst_ni (rst_shadow_n),
539+
540+ .test_en_i (test_en_i),
541+ .dummy_instr_id_i (shadow_dummy_instr_id),
542+ .dummy_instr_wb_i (shadow_dummy_instr_wb),
543+
544+ .raddr_a_i (shadow_rf_raddr_a),
545+ .rdata_a_o (shadow_rf_rdata_a_intg),
546+ .raddr_b_i (shadow_rf_raddr_b),
547+ .rdata_b_o (shadow_rf_rdata_b_intg),
548+ .waddr_a_i (shadow_rf_waddr_wb),
549+ .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth- 1 : RegFileDataWidth]),
550+ .we_a_i (shadow_rf_we_wb)
551+ );
552+ end else if (RegFile == RegFileLatch) begin : gen_regfile_latch
553+ ibex_register_file_latch # (
554+ .RV32E (RV32E ),
555+ .DataWidth (RegFileDataEccWidth - RegFileDataWidth),
556+ .DummyInstructions (DummyInstructions),
557+ .WordZeroVal (SecdedInv3932ZeroWord[RegFileDataEccWidth- 1 : RegFileDataWidth])
558+ ) register_file_shadow_i (
559+ .clk_i (clk_i),
560+ .rst_ni (rst_shadow_n),
561+
562+ .test_en_i (test_en_i),
563+ .dummy_instr_id_i (shadow_dummy_instr_id),
564+ .dummy_instr_wb_i (shadow_dummy_instr_wb),
565+
566+ .raddr_a_i (shadow_rf_raddr_a),
567+ .rdata_a_o (shadow_rf_rdata_a_intg),
568+ .raddr_b_i (shadow_rf_raddr_b),
569+ .rdata_b_o (shadow_rf_rdata_b_intg),
570+ .waddr_a_i (shadow_rf_waddr_wb),
571+ .wdata_a_i (shadow_rf_wdata_wb_ecc[RegFileDataEccWidth- 1 : RegFileDataWidth]),
572+ .we_a_i (shadow_rf_we_wb)
573+ );
574+ end
575+
501576 // ///////////////////////
502577 // Compare the outputs //
503578 // ///////////////////////
0 commit comments