mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-20 12:08:05 -04:00
[rtl] Add dual core lockstep option
Note that the alert output is tied off for now until an option is added to reset all registers (otherwise there will be X propagation). Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit is contained in:
parent
6a3200929b
commit
a88f5eb912
7 changed files with 499 additions and 6 deletions
|
@ -4,6 +4,9 @@ Core Integration
|
|||
================
|
||||
|
||||
The main module is named ``ibex_top`` and can be found in ``ibex_top.sv``.
|
||||
Note that the core logic is split-out from the register file and RAMs under ``ibex_top``.
|
||||
This is to facilitate a dual-core lockstep implementation (see :ref:`security`).
|
||||
|
||||
Below, the instantiation template is given and the parameters and interfaces are described.
|
||||
|
||||
Instantiation Template
|
||||
|
|
|
@ -77,3 +77,13 @@ Shadow CSRs
|
|||
Certain critical CSRs (`mstatus`, `mtvec`, `cpuctrl`, `pmpcfg` and `pmpaddr`) have extra glitch detection enabled.
|
||||
This creates a second copy of the register which stores a complemented version of the main CSR data.
|
||||
A constant check is made that the two copies are consistent, and a major alert is signalled if not.
|
||||
|
||||
Dual core lockstep
|
||||
------------------
|
||||
|
||||
This configuration option instantiates a second copy of the core logic, referred to as the shadow core.
|
||||
The shadow core executes using a delayed version of all inputs supplied to the main core.
|
||||
All outputs of the shadow core are compared against a delayed version of the outputs of the main core.
|
||||
Any mismatch between the two sets of outputs will trigger a major alert.
|
||||
|
||||
Note that the register file and icache RAMs are not duplicated since these units are covered by ECC protection.
|
||||
|
|
|
@ -54,6 +54,7 @@ ${PRJ_DIR}/rtl/ibex_id_stage.sv
|
|||
${PRJ_DIR}/rtl/ibex_icache.sv
|
||||
${PRJ_DIR}/rtl/ibex_if_stage.sv
|
||||
${PRJ_DIR}/rtl/ibex_load_store_unit.sv
|
||||
${PRJ_DIR}/rtl/ibex_lockstep.sv
|
||||
${PRJ_DIR}/rtl/ibex_multdiv_slow.sv
|
||||
${PRJ_DIR}/rtl/ibex_multdiv_fast.sv
|
||||
${PRJ_DIR}/rtl/ibex_prefetch_buffer.sv
|
||||
|
|
|
@ -14,6 +14,7 @@ filesets:
|
|||
- rtl/ibex_register_file_ff.sv # generic FF-based
|
||||
- rtl/ibex_register_file_fpga.sv # FPGA
|
||||
- rtl/ibex_register_file_latch.sv # ASIC
|
||||
- rtl/ibex_lockstep.sv
|
||||
- rtl/ibex_top.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ module ibex_core import ibex_pkg::*; #(
|
|||
localparam int unsigned PMP_NUM_CHAN = 2;
|
||||
localparam bit DataIndTiming = SecureIbex;
|
||||
localparam bit PCIncrCheck = SecureIbex;
|
||||
localparam bit ShadowCSR = SecureIbex;
|
||||
localparam bit ShadowCSR = 1'b0;
|
||||
// Speculative branch option, trades-off performance against timing.
|
||||
// Setting this to 1 eases branch target critical paths significantly but reduces performance
|
||||
// by ~3% (based on CoreMark/MHz score).
|
||||
|
@ -855,9 +855,6 @@ module ibex_core import ibex_pkg::*; #(
|
|||
// Major alert - core is unrecoverable
|
||||
assign alert_major_o = rf_ecc_err_comb | pc_mismatch_alert | csr_shadow_err;
|
||||
|
||||
`ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o)
|
||||
`ASSERT_KNOWN(IbexAlertMajorX, alert_major_o)
|
||||
|
||||
// Explict INC_ASSERT block to avoid unused signal lint warnings were asserts are not included
|
||||
`ifdef INC_ASSERT
|
||||
// Signals used for assertions only
|
||||
|
|
377
rtl/ibex_lockstep.sv
Normal file
377
rtl/ibex_lockstep.sv
Normal file
|
@ -0,0 +1,377 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Ibex lockstep module
|
||||
// This module instantiates a second copy of the core logic, and compares it's outputs against
|
||||
// those from the main core. The second core runs synchronously with the main core, delayed by
|
||||
// LockstepOffset cycles.
|
||||
module ibex_lockstep import ibex_pkg::*; #(
|
||||
parameter int unsigned LockstepOffset = 2,
|
||||
parameter bit PMPEnable = 1'b0,
|
||||
parameter int unsigned PMPGranularity = 0,
|
||||
parameter int unsigned PMPNumRegions = 4,
|
||||
parameter int unsigned MHPMCounterNum = 0,
|
||||
parameter int unsigned MHPMCounterWidth = 40,
|
||||
parameter bit RV32E = 1'b0,
|
||||
parameter rv32m_e RV32M = RV32MFast,
|
||||
parameter rv32b_e RV32B = RV32BNone,
|
||||
parameter bit BranchTargetALU = 1'b0,
|
||||
parameter bit WritebackStage = 1'b0,
|
||||
parameter bit ICache = 1'b0,
|
||||
parameter bit ICacheECC = 1'b0,
|
||||
parameter int unsigned BusSizeECC = BUS_SIZE,
|
||||
parameter int unsigned TagSizeECC = IC_TAG_SIZE,
|
||||
parameter int unsigned LineSizeECC = IC_LINE_SIZE,
|
||||
parameter bit BranchPredictor = 1'b0,
|
||||
parameter bit DbgTriggerEn = 1'b0,
|
||||
parameter int unsigned DbgHwBreakNum = 1,
|
||||
parameter bit SecureIbex = 1'b0,
|
||||
parameter bit DummyInstructions = 1'b0,
|
||||
parameter bit RegFileECC = 1'b0,
|
||||
parameter int unsigned RegFileDataWidth = 32,
|
||||
parameter int unsigned DmHaltAddr = 32'h1A110800,
|
||||
parameter int unsigned DmExceptionAddr = 32'h1A110808
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic [31:0] hart_id_i,
|
||||
input logic [31:0] boot_addr_i,
|
||||
|
||||
input logic instr_req_i,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_rvalid_i,
|
||||
input logic [31:0] instr_addr_i,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_err_i,
|
||||
|
||||
input logic data_req_i,
|
||||
input logic data_gnt_i,
|
||||
input logic data_rvalid_i,
|
||||
input logic data_we_i,
|
||||
input logic [3:0] data_be_i,
|
||||
input logic [31:0] data_addr_i,
|
||||
input logic [31:0] data_wdata_i,
|
||||
input logic [31:0] data_rdata_i,
|
||||
input logic data_err_i,
|
||||
|
||||
input logic dummy_instr_id_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 [IC_NUM_WAYS-1:0] ic_tag_req_i,
|
||||
input logic ic_tag_write_i,
|
||||
input logic [IC_INDEX_W-1:0] ic_tag_addr_i,
|
||||
input logic [TagSizeECC-1:0] ic_tag_wdata_i,
|
||||
input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
|
||||
input logic [IC_NUM_WAYS-1:0] ic_data_req_i,
|
||||
input logic ic_data_write_i,
|
||||
input logic [IC_INDEX_W-1:0] ic_data_addr_i,
|
||||
input logic [LineSizeECC-1:0] ic_data_wdata_i,
|
||||
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
|
||||
|
||||
input logic irq_software_i,
|
||||
input logic irq_timer_i,
|
||||
input logic irq_external_i,
|
||||
input logic [14:0] irq_fast_i,
|
||||
input logic irq_nm_i,
|
||||
input logic irq_pending_i,
|
||||
|
||||
input logic debug_req_i,
|
||||
input crash_dump_t crash_dump_i,
|
||||
|
||||
output logic alert_minor_o,
|
||||
output logic alert_major_o,
|
||||
input logic core_busy_i
|
||||
);
|
||||
|
||||
localparam int unsigned LockstepOffsetW = $clog2(LockstepOffset);
|
||||
|
||||
//////////////////////
|
||||
// Reset generation //
|
||||
//////////////////////
|
||||
|
||||
logic [LockstepOffsetW-1:0] rst_shadow_cnt_d, rst_shadow_cnt_q;
|
||||
logic rst_shadow_set_d, rst_shadow_set_q;
|
||||
// Internally generated resets cause IMPERFECTSCH warnings
|
||||
/* verilator lint_off IMPERFECTSCH */
|
||||
logic rst_shadow_n;
|
||||
/* verilator lint_on IMPERFECTSCH */
|
||||
|
||||
assign rst_shadow_set_d = (rst_shadow_cnt_q == LockstepOffsetW'(LockstepOffset - 1));
|
||||
assign rst_shadow_cnt_d = rst_shadow_set_d ? rst_shadow_cnt_q :
|
||||
(rst_shadow_cnt_q + LockstepOffsetW'(1));
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rst_shadow_cnt_q <= '0;
|
||||
rst_shadow_set_q <= '0;
|
||||
end else begin
|
||||
rst_shadow_cnt_q <= rst_shadow_cnt_d;
|
||||
rst_shadow_set_q <= rst_shadow_set_d;
|
||||
end
|
||||
end
|
||||
|
||||
assign rst_shadow_n = rst_shadow_set_q;
|
||||
|
||||
//////////////////
|
||||
// Input delays //
|
||||
//////////////////
|
||||
|
||||
typedef struct packed {
|
||||
logic instr_gnt;
|
||||
logic instr_rvalid;
|
||||
logic [31:0] instr_rdata;
|
||||
logic instr_err;
|
||||
logic data_gnt;
|
||||
logic data_rvalid;
|
||||
logic [31:0] data_rdata;
|
||||
logic data_err;
|
||||
logic [RegFileDataWidth-1:0] rf_rdata_a_ecc;
|
||||
logic [RegFileDataWidth-1:0] rf_rdata_b_ecc;
|
||||
logic irq_software;
|
||||
logic irq_timer;
|
||||
logic irq_external;
|
||||
logic [14:0] irq_fast;
|
||||
logic irq_nm;
|
||||
logic debug_req;
|
||||
} delayed_inputs_t;
|
||||
|
||||
delayed_inputs_t [LockstepOffset-1:0] shadow_inputs_q;
|
||||
delayed_inputs_t shadow_inputs_in;
|
||||
// Packed arrays must be dealt with separately
|
||||
logic [TagSizeECC-1:0] shadow_tag_rdata_q [IC_NUM_WAYS][LockstepOffset];
|
||||
logic [LineSizeECC-1:0] shadow_data_rdata_q [IC_NUM_WAYS][LockstepOffset];
|
||||
|
||||
// Assign the inputs to the delay structure
|
||||
assign shadow_inputs_in.instr_gnt = instr_gnt_i;
|
||||
assign shadow_inputs_in.instr_rvalid = instr_rvalid_i;
|
||||
assign shadow_inputs_in.instr_rdata = instr_rdata_i;
|
||||
assign shadow_inputs_in.instr_err = instr_err_i;
|
||||
assign shadow_inputs_in.data_gnt = data_gnt_i;
|
||||
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.irq_software = irq_software_i;
|
||||
assign shadow_inputs_in.irq_timer = irq_timer_i;
|
||||
assign shadow_inputs_in.irq_external = irq_external_i;
|
||||
assign shadow_inputs_in.irq_fast = irq_fast_i;
|
||||
assign shadow_inputs_in.irq_nm = irq_nm_i;
|
||||
assign shadow_inputs_in.debug_req = debug_req_i;
|
||||
|
||||
// Delay the inputs
|
||||
always_ff @(posedge clk_i) begin
|
||||
for (int unsigned i = 0; i < LockstepOffset-1; i++) begin
|
||||
shadow_inputs_q[i] <= shadow_inputs_q[i+1];
|
||||
shadow_tag_rdata_q[i] <= shadow_tag_rdata_q[i+1];
|
||||
shadow_data_rdata_q[i] <= shadow_data_rdata_q[i+1];
|
||||
end
|
||||
shadow_inputs_q[LockstepOffset-1] <= shadow_inputs_in;
|
||||
shadow_tag_rdata_q[LockstepOffset-1] <= ic_tag_rdata_i;
|
||||
shadow_data_rdata_q[LockstepOffset-1] <= ic_data_rdata_i;
|
||||
end
|
||||
|
||||
///////////////////
|
||||
// Output delays //
|
||||
///////////////////
|
||||
|
||||
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 [31:0] data_wdata;
|
||||
logic dummy_instr_id;
|
||||
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 irq_pending;
|
||||
crash_dump_t crash_dump;
|
||||
logic core_busy;
|
||||
} delayed_outputs_t;
|
||||
|
||||
delayed_outputs_t [LockstepOffset-1:0] core_outputs_q;
|
||||
delayed_outputs_t core_outputs_in, shadow_outputs;
|
||||
|
||||
// Assign core outputs to the structure
|
||||
assign core_outputs_in.instr_req = instr_req_i;
|
||||
assign core_outputs_in.instr_addr = instr_addr_i;
|
||||
assign core_outputs_in.data_req = data_req_i;
|
||||
assign core_outputs_in.data_we = data_we_i;
|
||||
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.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;
|
||||
assign core_outputs_in.ic_tag_wdata = ic_tag_wdata_i;
|
||||
assign core_outputs_in.ic_data_req = ic_data_req_i;
|
||||
assign core_outputs_in.ic_data_write = ic_data_write_i;
|
||||
assign core_outputs_in.ic_data_addr = ic_data_addr_i;
|
||||
assign core_outputs_in.ic_data_wdata = ic_data_wdata_i;
|
||||
assign core_outputs_in.irq_pending = irq_pending_i;
|
||||
assign core_outputs_in.crash_dump = crash_dump_i;
|
||||
assign core_outputs_in.core_busy = core_busy_i;
|
||||
|
||||
// Delay the outputs
|
||||
always_ff @(posedge clk_i) begin
|
||||
for (int unsigned i = 0; i < LockstepOffset-1; i++) begin
|
||||
core_outputs_q[i] <= core_outputs_q[i+1];
|
||||
end
|
||||
core_outputs_q[LockstepOffset-1] <= core_outputs_in;
|
||||
end
|
||||
|
||||
///////////////////////////////
|
||||
// Shadow core instantiation //
|
||||
///////////////////////////////
|
||||
|
||||
logic shadow_alert_minor, shadow_alert_major;
|
||||
|
||||
ibex_core #(
|
||||
.PMPEnable ( PMPEnable ),
|
||||
.PMPGranularity ( PMPGranularity ),
|
||||
.PMPNumRegions ( PMPNumRegions ),
|
||||
.MHPMCounterNum ( MHPMCounterNum ),
|
||||
.MHPMCounterWidth ( MHPMCounterWidth ),
|
||||
.RV32E ( RV32E ),
|
||||
.RV32M ( RV32M ),
|
||||
.RV32B ( RV32B ),
|
||||
.BranchTargetALU ( BranchTargetALU ),
|
||||
.ICache ( ICache ),
|
||||
.ICacheECC ( ICacheECC ),
|
||||
.BusSizeECC ( BusSizeECC ),
|
||||
.TagSizeECC ( TagSizeECC ),
|
||||
.LineSizeECC ( LineSizeECC ),
|
||||
.BranchPredictor ( BranchPredictor ),
|
||||
.DbgTriggerEn ( DbgTriggerEn ),
|
||||
.DbgHwBreakNum ( DbgHwBreakNum ),
|
||||
.WritebackStage ( WritebackStage ),
|
||||
.SecureIbex ( SecureIbex ),
|
||||
.DummyInstructions ( DummyInstructions ),
|
||||
.RegFileECC ( RegFileECC ),
|
||||
.RegFileDataWidth ( RegFileDataWidth ),
|
||||
.DmHaltAddr ( DmHaltAddr ),
|
||||
.DmExceptionAddr ( DmExceptionAddr )
|
||||
) u_shadow_core (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_shadow_n),
|
||||
|
||||
.hart_id_i (hart_id_i),
|
||||
.boot_addr_i (boot_addr_i),
|
||||
|
||||
.instr_req_o (shadow_outputs.instr_req),
|
||||
.instr_gnt_i (shadow_inputs_q[0].instr_gnt),
|
||||
.instr_rvalid_i (shadow_inputs_q[0].instr_rvalid),
|
||||
.instr_addr_o (shadow_outputs.instr_addr),
|
||||
.instr_rdata_i (shadow_inputs_q[0].instr_rdata),
|
||||
.instr_err_i (shadow_inputs_q[0].instr_err),
|
||||
|
||||
.data_req_o (shadow_outputs.data_req),
|
||||
.data_gnt_i (shadow_inputs_q[0].data_gnt),
|
||||
.data_rvalid_i (shadow_inputs_q[0].data_rvalid),
|
||||
.data_we_o (shadow_outputs.data_we),
|
||||
.data_be_o (shadow_outputs.data_be),
|
||||
.data_addr_o (shadow_outputs.data_addr),
|
||||
.data_wdata_o (shadow_outputs.data_wdata),
|
||||
.data_rdata_i (shadow_inputs_q[0].data_rdata),
|
||||
.data_err_i (shadow_inputs_q[0].data_err),
|
||||
|
||||
.dummy_instr_id_o (shadow_outputs.dummy_instr_id),
|
||||
.rf_raddr_a_o (shadow_outputs.rf_raddr_a),
|
||||
.rf_raddr_b_o (shadow_outputs.rf_raddr_b),
|
||||
.rf_waddr_wb_o (shadow_outputs.rf_waddr_wb),
|
||||
.rf_we_wb_o (shadow_outputs.rf_we_wb),
|
||||
.rf_wdata_wb_ecc_o (shadow_outputs.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),
|
||||
|
||||
.ic_tag_req_o (shadow_outputs.ic_tag_req),
|
||||
.ic_tag_write_o (shadow_outputs.ic_tag_write),
|
||||
.ic_tag_addr_o (shadow_outputs.ic_tag_addr),
|
||||
.ic_tag_wdata_o (shadow_outputs.ic_tag_wdata),
|
||||
.ic_tag_rdata_i (shadow_tag_rdata_q[0]),
|
||||
.ic_data_req_o (shadow_outputs.ic_data_req),
|
||||
.ic_data_write_o (shadow_outputs.ic_data_write),
|
||||
.ic_data_addr_o (shadow_outputs.ic_data_addr),
|
||||
.ic_data_wdata_o (shadow_outputs.ic_data_wdata),
|
||||
.ic_data_rdata_i (shadow_data_rdata_q[0]),
|
||||
|
||||
.irq_software_i (shadow_inputs_q[0].irq_software),
|
||||
.irq_timer_i (shadow_inputs_q[0].irq_timer),
|
||||
.irq_external_i (shadow_inputs_q[0].irq_external),
|
||||
.irq_fast_i (shadow_inputs_q[0].irq_fast),
|
||||
.irq_nm_i (shadow_inputs_q[0].irq_nm),
|
||||
.irq_pending_o (shadow_outputs.irq_pending),
|
||||
|
||||
.debug_req_i (shadow_inputs_q[0].debug_req),
|
||||
.crash_dump_o (shadow_outputs.crash_dump),
|
||||
|
||||
`ifdef RVFI
|
||||
.rvfi_valid (),
|
||||
.rvfi_order (),
|
||||
.rvfi_insn (),
|
||||
.rvfi_trap (),
|
||||
.rvfi_halt (),
|
||||
.rvfi_intr (),
|
||||
.rvfi_mode (),
|
||||
.rvfi_ixl (),
|
||||
.rvfi_rs1_addr (),
|
||||
.rvfi_rs2_addr (),
|
||||
.rvfi_rs3_addr (),
|
||||
.rvfi_rs1_rdata (),
|
||||
.rvfi_rs2_rdata (),
|
||||
.rvfi_rs3_rdata (),
|
||||
.rvfi_rd_addr (),
|
||||
.rvfi_rd_wdata (),
|
||||
.rvfi_pc_rdata (),
|
||||
.rvfi_pc_wdata (),
|
||||
.rvfi_mem_addr (),
|
||||
.rvfi_mem_rmask (),
|
||||
.rvfi_mem_wmask (),
|
||||
.rvfi_mem_rdata (),
|
||||
.rvfi_mem_wdata (),
|
||||
`endif
|
||||
|
||||
.alert_minor_o (shadow_alert_minor),
|
||||
.alert_major_o (shadow_alert_major),
|
||||
.core_busy_o (shadow_outputs.core_busy)
|
||||
);
|
||||
|
||||
/////////////////////////
|
||||
// Compare the outputs //
|
||||
/////////////////////////
|
||||
|
||||
logic outputs_mismatch;
|
||||
|
||||
// TODO evaluate the timing here - might need to register shadow_outputs
|
||||
assign outputs_mismatch = rst_shadow_n & (shadow_outputs != core_outputs_q[0]);
|
||||
assign alert_major_o = outputs_mismatch | shadow_alert_major;
|
||||
assign alert_minor_o = shadow_alert_minor;
|
||||
|
||||
endmodule
|
108
rtl/ibex_top.sv
108
rtl/ibex_top.sv
|
@ -109,6 +109,7 @@ module ibex_top #(
|
|||
|
||||
import ibex_pkg::*;
|
||||
|
||||
localparam bit Lockstep = SecureIbex;
|
||||
localparam bit DummyInstructions = SecureIbex;
|
||||
localparam bit RegFileECC = SecureIbex;
|
||||
localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32;
|
||||
|
@ -143,6 +144,9 @@ module ibex_top #(
|
|||
logic [IC_INDEX_W-1:0] ic_data_addr;
|
||||
logic [LineSizeECC-1:0] ic_data_wdata;
|
||||
logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS];
|
||||
// Alert signals
|
||||
logic core_alert_major, core_alert_minor;
|
||||
logic lockstep_alert_major, lockstep_alert_minor;
|
||||
|
||||
/////////////////////
|
||||
// Main clock gate //
|
||||
|
@ -284,8 +288,8 @@ module ibex_top #(
|
|||
.rvfi_mem_wdata,
|
||||
`endif
|
||||
|
||||
.alert_minor_o,
|
||||
.alert_major_o,
|
||||
.alert_minor_o (core_alert_minor),
|
||||
.alert_major_o (core_alert_major),
|
||||
.core_busy_o (core_busy_d)
|
||||
);
|
||||
|
||||
|
@ -408,4 +412,104 @@ module ibex_top #(
|
|||
|
||||
end
|
||||
|
||||
// Redundant lockstep core implementation
|
||||
if (Lockstep) begin : gen_lockstep
|
||||
ibex_lockstep #(
|
||||
.PMPEnable ( PMPEnable ),
|
||||
.PMPGranularity ( PMPGranularity ),
|
||||
.PMPNumRegions ( PMPNumRegions ),
|
||||
.MHPMCounterNum ( MHPMCounterNum ),
|
||||
.MHPMCounterWidth ( MHPMCounterWidth ),
|
||||
.RV32E ( RV32E ),
|
||||
.RV32M ( RV32M ),
|
||||
.RV32B ( RV32B ),
|
||||
.BranchTargetALU ( BranchTargetALU ),
|
||||
.ICache ( ICache ),
|
||||
.ICacheECC ( ICacheECC ),
|
||||
.BusSizeECC ( BusSizeECC ),
|
||||
.TagSizeECC ( TagSizeECC ),
|
||||
.LineSizeECC ( LineSizeECC ),
|
||||
.BranchPredictor ( BranchPredictor ),
|
||||
.DbgTriggerEn ( DbgTriggerEn ),
|
||||
.DbgHwBreakNum ( DbgHwBreakNum ),
|
||||
.WritebackStage ( WritebackStage ),
|
||||
.SecureIbex ( SecureIbex ),
|
||||
.DummyInstructions ( DummyInstructions ),
|
||||
.RegFileECC ( RegFileECC ),
|
||||
.RegFileDataWidth ( RegFileDataWidth ),
|
||||
.DmHaltAddr ( DmHaltAddr ),
|
||||
.DmExceptionAddr ( DmExceptionAddr )
|
||||
) u_ibex_lockstep (
|
||||
.clk_i (clk),
|
||||
.rst_ni (rst_ni),
|
||||
|
||||
.hart_id_i (hart_id_i),
|
||||
.boot_addr_i (boot_addr_i),
|
||||
|
||||
.instr_req_i (instr_req_o),
|
||||
.instr_gnt_i (instr_gnt_i),
|
||||
.instr_rvalid_i (instr_rvalid_i),
|
||||
.instr_addr_i (instr_addr_o),
|
||||
.instr_rdata_i (instr_rdata_i),
|
||||
.instr_err_i (instr_err_i),
|
||||
|
||||
.data_req_i (data_req_o),
|
||||
.data_gnt_i (data_gnt_i),
|
||||
.data_rvalid_i (data_rvalid_i),
|
||||
.data_we_i (data_we_o),
|
||||
.data_be_i (data_be_o),
|
||||
.data_addr_i (data_addr_o),
|
||||
.data_wdata_i (data_wdata_o),
|
||||
.data_rdata_i (data_rdata_i),
|
||||
.data_err_i (data_err_i),
|
||||
|
||||
.dummy_instr_id_i (dummy_instr_id),
|
||||
.rf_raddr_a_i (rf_raddr_a),
|
||||
.rf_raddr_b_i (rf_raddr_b),
|
||||
.rf_waddr_wb_i (rf_waddr_wb),
|
||||
.rf_we_wb_i (rf_we_wb),
|
||||
.rf_wdata_wb_ecc_i (rf_wdata_wb_ecc),
|
||||
.rf_rdata_a_ecc_i (rf_rdata_a_ecc),
|
||||
.rf_rdata_b_ecc_i (rf_rdata_b_ecc),
|
||||
|
||||
.ic_tag_req_i (ic_tag_req),
|
||||
.ic_tag_write_i (ic_tag_write),
|
||||
.ic_tag_addr_i (ic_tag_addr),
|
||||
.ic_tag_wdata_i (ic_tag_wdata),
|
||||
.ic_tag_rdata_i (ic_tag_rdata),
|
||||
.ic_data_req_i (ic_data_req),
|
||||
.ic_data_write_i (ic_data_write),
|
||||
.ic_data_addr_i (ic_data_addr),
|
||||
.ic_data_wdata_i (ic_data_wdata),
|
||||
.ic_data_rdata_i (ic_data_rdata),
|
||||
|
||||
.irq_software_i (irq_software_i),
|
||||
.irq_timer_i (irq_timer_i),
|
||||
.irq_external_i (irq_external_i),
|
||||
.irq_fast_i (irq_fast_i),
|
||||
.irq_nm_i (irq_nm_i),
|
||||
.irq_pending_i (irq_pending),
|
||||
|
||||
.debug_req_i (debug_req_i),
|
||||
.crash_dump_i (crash_dump_o),
|
||||
|
||||
.alert_minor_o (lockstep_alert_minor),
|
||||
.alert_major_o (lockstep_alert_major),
|
||||
.core_busy_i (core_busy_d)
|
||||
);
|
||||
end else begin : gen_no_lockstep
|
||||
assign lockstep_alert_major = 1'b0;
|
||||
assign lockstep_alert_minor = 1'b0;
|
||||
end
|
||||
|
||||
// TODO - need a config to reset all registers before the lockstep alert can be used
|
||||
logic unused_lockstep_alert_major;
|
||||
assign unused_lockstep_alert_major = lockstep_alert_major;
|
||||
|
||||
assign alert_major_o = core_alert_major;// | lockstep_alert_major;
|
||||
assign alert_minor_o = core_alert_minor | lockstep_alert_minor;
|
||||
|
||||
`ASSERT_KNOWN(IbexAlertMinorX, alert_minor_o)
|
||||
`ASSERT_KNOWN(IbexAlertMajorX, alert_major_o)
|
||||
|
||||
endmodule
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue