[flash_ctrl] Various clean-up and updates
- use prim_intr_hw, (#8035 for flash)
- clean-up error mechanisms and related usage
- clean-up error and data signaling when multi-bit errors are seen
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.hjson b/hw/ip/flash_ctrl/data/flash_ctrl.hjson
index 6c800cb..1d37a7e 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson
@@ -28,21 +28,15 @@
{ name: "rd_full", desc: "Read FIFO full" },
{ name: "rd_lvl", desc: "Read FIFO filled to level" },
{ name: "op_done", desc: "Operation complete" },
- { name: "err", desc: "Error encountered"},
+ { name: "corr_err", desc: "Correctable error encountered"},
],
alert_list: [
{ name: "recov_err",
- desc: "flash alerts directly from prim_flash",
+ desc: "flash recoverable errors",
},
- { name: "recov_mp_err",
- desc: "recoverable flash alert for permission error"
- },
- { name: "recov_ecc_err",
- desc: "recoverable flash alert for ecc error"
- },
- { name: "fatal_intg_err",
- desc: "Fatal integrity error"
+ { name: "fatal_err",
+ desc: "flash fatal errors"
},
],
@@ -1384,159 +1378,172 @@
]
},
- { name: "ERR_CODE_INTR_EN",
- desc: '''
- Interrupt enable mask for error code.
- Only enabled bits will generate interrupts.
- Bits that are not enabled will still be reflected in the !!ERR_CODE register, but will not trigger
- an interrupt
- '''
- swaccess: "rw",
- hwaccess: "hro",
- fields: [
- { bits: "0",
- name: "flash_err_en",
- desc: "interrupt mask for flash error"
- },
- { bits: "1",
- name: "flash_alert_en",
- desc: "interrupt mask for flash alert"
- },
- { bits: "2",
- name: "oob_err",
- desc: "interrupt mask for software address out of bounds error"
- },
- { bits: "3",
- name: "mp_err",
- desc: "interrupt mask for memory properties error"
- },
- { bits: "4",
- name: "ecc_single_err",
- desc: "interrupt mask for single bit ecc error"
- },
- { bits: "5",
- name: "ecc_multi_err",
- desc: "interrupt mask for multiple bits ecc error"
- },
- ]
- },
-
{ name: "ERR_CODE",
desc: '''
Flash error code register.
This register tabulates detailed error status of the flash.
This is separate from !!OP_STATUS, which is used to indicate the current state of the software initiated
flash operation.
+
+ Note, all errors in this register are considered recoverable errors, ie, errors that could have been
+ generated by software.
'''
swaccess: "rw1c",
- hwaccess: "hrw",
+ hwaccess: "hwo",
fields: [
{ bits: "0",
- name: "flash_err",
- desc: '''
- The flash memory itself has an error, please check the vendor specs for details of the error.
- '''
- },
- { bits: "1",
- name: "flash_alert",
- desc: '''
- The flash memory itself has triggered an alert, please check the vendor specs for details of the error.
- '''
- },
- { bits: "2",
name: "oob_err",
desc: '''
The supplied address !!ADDR is invalid and out of bounds.
+ This is a synchronous error.
'''
},
- { bits: "3",
+ { bits: "1",
name: "mp_err",
desc: '''
Flash access has encountered an access permission error.
Please see !!ERR_ADDR for exact address.
+ This is a synchronous error.
+ '''
+ },
+ { bits: "2",
+ name: "rd_err",
+ desc: '''
+ Flash read has an uncorrectable data error.
+ Please see !!ERR_ADDR for exact address.
+ This is a synchronous error.
+ '''
+ },
+ { bits: "3",
+ name: "prog_win_err",
+ desc: '''
+ Flash program has a window resolution error. Ie, the start of program
+ and end of program are in different windows. Please check !!ADDR.
+ This is a synchronous error.
'''
},
{ bits: "4",
- name: "ecc_single_err",
+ name: "prog_type_err",
desc: '''
- Flash access has encountered a single bit ECC error.
- Please see !!ECC_SINGLE_ERR_ADDR for exact address.
+ Flash program selected unavailable type, see !!PROG_TYPE_EN.
+ This is a synchronous error.
'''
},
{ bits: "5",
- name: "ecc_multi_err",
+ name: "flash_phy_err",
desc: '''
- Flash access has encountered a multi bit ECC error.
- Please see !!ECC_MULTI_ERR_ADDR for exact address.
+ The flash access encountered a native flash error.
+ Please check the vendor specs for details of the error.
+ This is a synchronous error.
+ '''
+ },
+ ]
+ },
+
+ { name: "FAULT_STATUS",
+ desc: '''
+ Flash fault status register.
+ This register tabulates detailed fault status of the flash.
+
+ These are errors that are impossible to have been caused by software or unrecoverable
+ in nature.
+ '''
+ swaccess: "ro",
+ hwaccess: "hrw",
+ fields: [
+ { bits: "0",
+ name: "oob_err",
+ desc: '''
+ The flash hardware interface supplied an out of bound value.
+ '''
+ },
+ { bits: "1",
+ name: "mp_err",
+ desc: '''
+ The flash hardware interface encountered a memory permission error.
+ '''
+ },
+ { bits: "2",
+ name: "rd_err",
+ desc: '''
+ The flash hardware interface encountered a read data error.
+ '''
+ },
+ { bits: "3",
+ name: "prog_win_err",
+ desc: '''
+ The flash hardware interface encountered a program resolution error.
+ '''
+ },
+ { bits: "4",
+ name: "prog_type_err",
+ desc: '''
+ The flash hardware interface encountered a program type error.
+ '''
+ },
+ { bits: "5",
+ name: "flash_phy_err",
+ desc: '''
+ The flash hardware interface encountered a native flash error.
+ '''
+ },
+ { bits: "6",
+ name: "reg_intg_err",
+ desc: '''
+ The flash controller encountered a register integrity error.
+ '''
+ },
+ { bits: "7",
+ name: "phy_intg_err",
+ desc: '''
+ The flash memory encountered a register integrity error.
'''
},
]
},
{ name: "ERR_ADDR",
- desc: "Access permission error address",
+ desc: "Synchronous error address",
swaccess: "ro",
hwaccess: "hwo",
fields: [
- { bits: "8:0",
- resval: 0,
- },
- ]
- },
-
- { name: "ECC_SINGLE_ERR_CNT",
- desc: "Total number of single bit ECC error count",
- swaccess: "rw1c",
- hwaccess: "hrw",
- fields: [
- { bits: "7:0",
- desc: "This count will not wrap when saturated",
+ { bits: "31:0",
resval: 0,
},
]
},
{ multireg: {
- cname: "ECC_SINGLE_ERR"
+ cname: "ECC_SINGLE_ERR",
+ name: "ECC_SINGLE_ERR_CNT",
+ desc: "Total number of single bit ECC error count",
+ count: "RegNumBanks",
+ swaccess: "rw",
+ hwaccess: "hrw",
+ fields: [
+ { bits: "7:0",
+ desc: "This count will not wrap when saturated",
+ resval: 0,
+ },
+ ]
+ }
+ },
+
+ { multireg: {
+ cname: "ECC_SINGLE_ERR",
name: "ECC_SINGLE_ERR_ADDR",
- desc: "Latest single bit error address (correctable)",
+ desc: "Latest address of ECC single err",
count: "RegNumBanks",
swaccess: "ro",
hwaccess: "hwo",
fields: [
{ bits: "19:0",
+ desc: "Latest single error address for this bank",
resval: 0,
},
]
}
- },
-
- { name: "ECC_MULTI_ERR_CNT",
- desc: "Total number of multi bit ECC error count",
- swaccess: "rw1c",
- hwaccess: "hrw",
- fields: [
- { bits: "7:0",
- desc: "This count will not wrap when saturated",
- resval: 0,
- },
- ]
- },
-
- { multireg: {
- cname: "ECC_MULTI_ERR"
- name: "ECC_MULTI_ERR_ADDR",
- desc: "Latest multi bit error address (uncorrectable)",
- count: "RegNumBanks",
- swaccess: "ro",
- hwaccess: "hwo",
- fields: [
- { bits: "19:0",
- resval: 0,
- },
- ]
- }
- },
+ }
{ name: "PHY_ERR_CFG_REGWEN",
swaccess: "rw0c",
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
index 9a91548..e3fac44 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
@@ -35,21 +35,15 @@
{ name: "rd_full", desc: "Read FIFO full" },
{ name: "rd_lvl", desc: "Read FIFO filled to level" },
{ name: "op_done", desc: "Operation complete" },
- { name: "err", desc: "Error encountered"},
+ { name: "corr_err", desc: "Correctable error encountered"},
],
alert_list: [
{ name: "recov_err",
- desc: "flash alerts directly from prim_flash",
+ desc: "flash recoverable errors",
},
- { name: "recov_mp_err",
- desc: "recoverable flash alert for permission error"
- },
- { name: "recov_ecc_err",
- desc: "recoverable flash alert for ecc error"
- },
- { name: "fatal_intg_err",
- desc: "Fatal integrity error"
+ { name: "fatal_err",
+ desc: "flash fatal errors"
},
],
@@ -900,159 +894,172 @@
]
},
- { name: "ERR_CODE_INTR_EN",
- desc: '''
- Interrupt enable mask for error code.
- Only enabled bits will generate interrupts.
- Bits that are not enabled will still be reflected in the !!ERR_CODE register, but will not trigger
- an interrupt
- '''
- swaccess: "rw",
- hwaccess: "hro",
- fields: [
- { bits: "0",
- name: "flash_err_en",
- desc: "interrupt mask for flash error"
- },
- { bits: "1",
- name: "flash_alert_en",
- desc: "interrupt mask for flash alert"
- },
- { bits: "2",
- name: "oob_err",
- desc: "interrupt mask for software address out of bounds error"
- },
- { bits: "3",
- name: "mp_err",
- desc: "interrupt mask for memory properties error"
- },
- { bits: "4",
- name: "ecc_single_err",
- desc: "interrupt mask for single bit ecc error"
- },
- { bits: "5",
- name: "ecc_multi_err",
- desc: "interrupt mask for multiple bits ecc error"
- },
- ]
- },
-
{ name: "ERR_CODE",
desc: '''
Flash error code register.
This register tabulates detailed error status of the flash.
This is separate from !!OP_STATUS, which is used to indicate the current state of the software initiated
flash operation.
+
+ Note, all errors in this register are considered recoverable errors, ie, errors that could have been
+ generated by software.
'''
swaccess: "rw1c",
- hwaccess: "hrw",
+ hwaccess: "hwo",
fields: [
{ bits: "0",
- name: "flash_err",
- desc: '''
- The flash memory itself has an error, please check the vendor specs for details of the error.
- '''
- },
- { bits: "1",
- name: "flash_alert",
- desc: '''
- The flash memory itself has triggered an alert, please check the vendor specs for details of the error.
- '''
- },
- { bits: "2",
name: "oob_err",
desc: '''
The supplied address !!ADDR is invalid and out of bounds.
+ This is a synchronous error.
'''
},
- { bits: "3",
+ { bits: "1",
name: "mp_err",
desc: '''
Flash access has encountered an access permission error.
Please see !!ERR_ADDR for exact address.
+ This is a synchronous error.
+ '''
+ },
+ { bits: "2",
+ name: "rd_err",
+ desc: '''
+ Flash read has an uncorrectable data error.
+ Please see !!ERR_ADDR for exact address.
+ This is a synchronous error.
+ '''
+ },
+ { bits: "3",
+ name: "prog_win_err",
+ desc: '''
+ Flash program has a window resolution error. Ie, the start of program
+ and end of program are in different windows. Please check !!ADDR.
+ This is a synchronous error.
'''
},
{ bits: "4",
- name: "ecc_single_err",
+ name: "prog_type_err",
desc: '''
- Flash access has encountered a single bit ECC error.
- Please see !!ECC_SINGLE_ERR_ADDR for exact address.
+ Flash program selected unavailable type, see !!PROG_TYPE_EN.
+ This is a synchronous error.
'''
},
{ bits: "5",
- name: "ecc_multi_err",
+ name: "flash_phy_err",
desc: '''
- Flash access has encountered a multi bit ECC error.
- Please see !!ECC_MULTI_ERR_ADDR for exact address.
+ The flash access encountered a native flash error.
+ Please check the vendor specs for details of the error.
+ This is a synchronous error.
+ '''
+ },
+ ]
+ },
+
+ { name: "FAULT_STATUS",
+ desc: '''
+ Flash fault status register.
+ This register tabulates detailed fault status of the flash.
+
+ These are errors that are impossible to have been caused by software or unrecoverable
+ in nature.
+ '''
+ swaccess: "ro",
+ hwaccess: "hrw",
+ fields: [
+ { bits: "0",
+ name: "oob_err",
+ desc: '''
+ The flash hardware interface supplied an out of bound value.
+ '''
+ },
+ { bits: "1",
+ name: "mp_err",
+ desc: '''
+ The flash hardware interface encountered a memory permission error.
+ '''
+ },
+ { bits: "2",
+ name: "rd_err",
+ desc: '''
+ The flash hardware interface encountered a read data error.
+ '''
+ },
+ { bits: "3",
+ name: "prog_win_err",
+ desc: '''
+ The flash hardware interface encountered a program resolution error.
+ '''
+ },
+ { bits: "4",
+ name: "prog_type_err",
+ desc: '''
+ The flash hardware interface encountered a program type error.
+ '''
+ },
+ { bits: "5",
+ name: "flash_phy_err",
+ desc: '''
+ The flash hardware interface encountered a native flash error.
+ '''
+ },
+ { bits: "6",
+ name: "reg_intg_err",
+ desc: '''
+ The flash controller encountered a register integrity error.
+ '''
+ },
+ { bits: "7",
+ name: "phy_intg_err",
+ desc: '''
+ The flash memory encountered a register integrity error.
'''
},
]
},
{ name: "ERR_ADDR",
- desc: "Access permission error address",
+ desc: "Synchronous error address",
swaccess: "ro",
hwaccess: "hwo",
fields: [
- { bits: "${bank_width + page_width -1}:0",
- resval: 0,
- },
- ]
- },
-
- { name: "ECC_SINGLE_ERR_CNT",
- desc: "Total number of single bit ECC error count",
- swaccess: "rw1c",
- hwaccess: "hrw",
- fields: [
- { bits: "7:0",
- desc: "This count will not wrap when saturated",
+ { bits: "31:0",
resval: 0,
},
]
},
{ multireg: {
- cname: "ECC_SINGLE_ERR"
+ cname: "ECC_SINGLE_ERR",
+ name: "ECC_SINGLE_ERR_CNT",
+ desc: "Total number of single bit ECC error count",
+ count: "RegNumBanks",
+ swaccess: "rw",
+ hwaccess: "hrw",
+ fields: [
+ { bits: "7:0",
+ desc: "This count will not wrap when saturated",
+ resval: 0,
+ },
+ ]
+ }
+ },
+
+ { multireg: {
+ cname: "ECC_SINGLE_ERR",
name: "ECC_SINGLE_ERR_ADDR",
- desc: "Latest single bit error address (correctable)",
+ desc: "Latest address of ECC single err",
count: "RegNumBanks",
swaccess: "ro",
hwaccess: "hwo",
fields: [
{ bits: "${total_byte_width-1}:0",
+ desc: "Latest single error address for this bank",
resval: 0,
},
]
}
- },
-
- { name: "ECC_MULTI_ERR_CNT",
- desc: "Total number of multi bit ECC error count",
- swaccess: "rw1c",
- hwaccess: "hrw",
- fields: [
- { bits: "7:0",
- desc: "This count will not wrap when saturated",
- resval: 0,
- },
- ]
- },
-
- { multireg: {
- cname: "ECC_MULTI_ERR"
- name: "ECC_MULTI_ERR_ADDR",
- desc: "Latest multi bit error address (uncorrectable)",
- count: "RegNumBanks",
- swaccess: "ro",
- hwaccess: "hwo",
- fields: [
- { bits: "${total_byte_width-1}:0",
- resval: 0,
- },
- ]
- }
- },
+ }
{ name: "PHY_ERR_CFG_REGWEN",
swaccess: "rw0c",
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
index 925a158..4565bef 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
@@ -58,7 +58,7 @@
output logic cio_tdo_o,
// Interrupts
- output logic intr_err_o, // ERR_CODE is non-zero
+ output logic intr_corr_err_o, // Correctable errors encountered
output logic intr_prog_empty_o, // Program fifo is empty
output logic intr_prog_lvl_o, // Program fifo is empty
output logic intr_rd_full_o, // Read fifo is full
@@ -144,18 +144,16 @@
flash_erase_e erase_flash_type;
logic erase_op_valid;
- // combined indication that an operation has started
- logic op_valid;
-
// Done / Error signaling from ctrl modules
logic prog_done, rd_done, erase_done;
- logic prog_err, rd_err, erase_err;
+ flash_ctrl_err_t prog_err, rd_err, erase_err;
+ logic [BusAddrW-1:0] prog_err_addr, rd_err_addr, erase_err_addr;
// Flash Memory Properties Connections
logic [BusAddrW-1:0] flash_addr;
logic flash_req;
logic flash_rd_done, flash_prog_done, flash_erase_done;
- logic flash_mp_error;
+ logic flash_mp_err;
logic [BusWidth-1:0] flash_prog_data;
logic flash_prog_last;
flash_prog_e flash_prog_type;
@@ -165,7 +163,6 @@
logic rd_op;
logic prog_op;
logic erase_op;
- logic [AllPagesW-1:0] err_addr;
flash_lcmgr_phase_e phase;
// Flash control arbitration connections to hardware interface
@@ -177,7 +174,7 @@
logic hw_req;
logic [top_pkg::TL_AW-1:0] hw_addr;
logic hw_done;
- logic hw_err;
+ flash_ctrl_err_t hw_err;
logic hw_rvalid;
logic hw_rready;
logic hw_wvalid;
@@ -191,7 +188,7 @@
// Flash control arbitration connections to software interface
logic sw_ctrl_done;
- logic sw_ctrl_err;
+ flash_ctrl_err_t sw_ctrl_err;
// Flash control muxed connections
flash_ctrl_reg2hw_control_reg_t muxed_ctrl;
@@ -199,6 +196,7 @@
logic op_start;
logic [11:0] op_num_words;
logic [BusAddrW-1:0] op_addr;
+ logic [BusAddrW-1:0] ctrl_err_addr;
// SW or HW supplied address is out of bounds
logic op_addr_oob;
flash_op_e op_type;
@@ -305,6 +303,9 @@
.clk_i,
.rst_ni,
+ // error output shared by both interfaces
+ .ctrl_err_addr_o(ctrl_err_addr),
+
// software interface to rd_ctrl / erase_ctrl
.sw_ctrl_i(reg2hw.control),
.sw_addr_i(reg2hw.addr.q),
@@ -346,10 +347,13 @@
.muxed_addr_o(muxed_addr),
.prog_ack_i(prog_done),
.prog_err_i(prog_err),
+ .prog_err_addr_i(prog_err_addr),
.rd_ack_i(rd_done),
.rd_err_i(rd_err),
+ .rd_err_addr_i(rd_err_addr),
.erase_ack_i(erase_done),
.erase_err_i(erase_err),
+ .erase_err_addr_i(erase_err_addr),
// muxed interface to rd_fifo
.rd_fifo_rvalid_i(rd_fifo_rvalid),
@@ -388,7 +392,6 @@
assign prog_op = op_type == FlashOpProgram;
assign erase_op = op_type == FlashOpErase;
assign sw_sel = if_sel == SwSel;
- assign op_valid = prog_op_valid | rd_op_valid | erase_op_valid;
// software privilege to creator seed
assign creator_seed_priv = lc_creator_seed_sw_rw_en == lc_ctrl_pkg::On;
@@ -524,6 +527,7 @@
.op_addr_oob_i (op_addr_oob),
.op_type_i (op_prog_type),
.type_avail_i (prog_type_en),
+ .op_err_addr_o (prog_err_addr),
// FIFO Interface
.data_i (prog_fifo_rdata),
@@ -538,7 +542,9 @@
.flash_last_o (flash_prog_last),
.flash_type_o (flash_prog_type),
.flash_done_i (flash_prog_done),
- .flash_error_i (flash_mp_error)
+ // TODO, pending feedback
+ .flash_phy_err_i(flash_phy_rsp.flash_err),
+ .flash_mp_err_i (flash_mp_err)
);
always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -602,6 +608,7 @@
.op_num_words_i (op_num_words),
.op_done_o (rd_done),
.op_err_o (rd_err),
+ .op_err_addr_o (rd_err_addr),
.op_addr_i (op_addr),
.op_addr_oob_i (op_addr_oob),
@@ -616,7 +623,9 @@
.flash_ovfl_o (rd_flash_ovfl),
.flash_data_i (flash_rd_data),
.flash_done_i (flash_rd_done),
- .flash_error_i (flash_mp_error | flash_rd_err)
+ .flash_mp_err_i (flash_mp_err),
+ .flash_rd_err_i (flash_rd_err),
+ .flash_phy_err_i(flash_phy_rsp.flash_err)
);
// Erase handler does not consume fifo
@@ -629,13 +638,15 @@
.op_err_o (erase_err),
.op_addr_i (op_addr),
.op_addr_oob_i (op_addr_oob),
+ .op_err_addr_o (erase_err_addr),
// Flash Macro Interface
.flash_req_o (erase_flash_req),
.flash_addr_o (erase_flash_addr),
.flash_op_o (erase_flash_type),
.flash_done_i (flash_erase_done),
- .flash_error_i (flash_mp_error)
+ .flash_mp_err_i (flash_mp_err),
+ .flash_phy_err_i(flash_phy_rsp.flash_err)
);
// Final muxing to flash macro module
@@ -755,8 +766,7 @@
.rd_done_o(flash_rd_done),
.prog_done_o(flash_prog_done),
.erase_done_o(flash_erase_done),
- .error_o(flash_mp_error),
- .err_addr_o(err_addr),
+ .error_o(flash_mp_err),
// flash phy interface
.req_o(flash_phy_req.req),
@@ -780,7 +790,7 @@
assign hw2reg.op_status.done.d = 1'b1;
assign hw2reg.op_status.done.de = sw_ctrl_done;
assign hw2reg.op_status.err.d = 1'b1;
- assign hw2reg.op_status.err.de = sw_ctrl_err;
+ assign hw2reg.op_status.err.de = |sw_ctrl_err;
assign hw2reg.status.rd_full.d = rd_fifo_full;
assign hw2reg.status.rd_full.de = sw_sel;
assign hw2reg.status.rd_empty.d = ~rd_fifo_rvalid;
@@ -855,31 +865,24 @@
logic [NumAlerts-1:0] alert_srcs;
logic [NumAlerts-1:0] alert_tests;
+ // TODO Add shadow update
+ // An excessive number of recoverable errors may also indicate an attack
logic recov_err;
- assign recov_err = flash_phy_rsp.flash_alert_p | ~flash_phy_rsp.flash_alert_n;
+ assign recov_err = sw_ctrl_done & |sw_ctrl_err;
- logic recov_mp_err;
- assign recov_mp_err = flash_mp_error;
+ logic fatal_err;
+ assign fatal_err = |reg2hw.fault_status;
- logic recov_ecc_err;
- assign recov_ecc_err = |flash_phy_rsp.ecc_single_err | |flash_phy_rsp.ecc_multi_err;
- logic fatal_intg_err;
- assign fatal_intg_err = flash_phy_rsp.intg_err | intg_err;
-
- assign alert_srcs = { fatal_intg_err,
- recov_ecc_err,
- recov_mp_err,
+ assign alert_srcs = { fatal_err,
recov_err
};
- assign alert_tests = { reg2hw.alert_test.fatal_intg_err.q & reg2hw.alert_test.fatal_intg_err.qe,
- reg2hw.alert_test.recov_ecc_err.q & reg2hw.alert_test.recov_ecc_err.qe,
- reg2hw.alert_test.recov_mp_err.q & reg2hw.alert_test.recov_mp_err.qe,
- reg2hw.alert_test.recov_err.q & reg2hw.alert_test.recov_err.qe
+ assign alert_tests = { reg2hw.alert_test.fatal_err.q & reg2hw.alert_test.fatal_err.qe,
+ reg2hw.alert_test.recov_err.q & reg2hw.alert_test.recov_err.qe
};
- localparam logic [NumAlerts-1:0] IsFatal = {1'b1, 1'b0, 1'b0, 1'b0};
+ localparam logic [NumAlerts-1:0] IsFatal = {1'b1, 1'b0};
for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_senders
prim_alert_sender #(
.AsyncOn(AlertAsyncOn[i]),
@@ -900,7 +903,7 @@
// Flash Disable
//////////////////////////////////////
assign flash_disable = reg2hw.flash_disable.q ? lc_ctrl_pkg::On :
- fatal_intg_err ? lc_ctrl_pkg::On : lc_ctrl_pkg::Off;
+ fatal_err ? lc_ctrl_pkg::On : lc_ctrl_pkg::Off;
lc_ctrl_pkg::lc_tx_t lc_escalate_en;
prim_lc_sync #(
@@ -918,133 +921,184 @@
// Errors and Interrupts
//////////////////////////////////////
- assign hw2reg.err_code.oob_err.d = 1'b1;
- assign hw2reg.err_code.mp_err.d = 1'b1;
- assign hw2reg.err_code.ecc_single_err.d = 1'b1;
- assign hw2reg.err_code.ecc_multi_err.d = 1'b1;
- assign hw2reg.err_code.flash_err.d = 1'b1;
- assign hw2reg.err_code.flash_alert.d = 1'b1;
- assign hw2reg.err_code.oob_err.de = op_valid & op_addr_oob;
- assign hw2reg.err_code.mp_err.de = flash_mp_error;
- assign hw2reg.err_code.ecc_single_err.de = |flash_phy_rsp.ecc_single_err;
- assign hw2reg.err_code.ecc_multi_err.de = |flash_phy_rsp.ecc_multi_err;
- assign hw2reg.err_code.flash_err.de = flash_phy_rsp.flash_err;
- assign hw2reg.err_code.flash_alert.de = flash_phy_rsp.flash_alert_p |
- ~flash_phy_rsp.flash_alert_n;
- assign hw2reg.err_addr.d = err_addr;
- assign hw2reg.err_addr.de = flash_mp_error;
+ // all software interface errors are treated as synchronous errors
+ assign hw2reg.err_code.oob_err.d = 1'b1;
+ assign hw2reg.err_code.mp_err.d = 1'b1;
+ assign hw2reg.err_code.rd_err.d = 1'b1;
+ assign hw2reg.err_code.prog_win_err.d = 1'b1;
+ assign hw2reg.err_code.prog_type_err.d = 1'b1;
+ assign hw2reg.err_code.flash_phy_err.d = 1'b1;
+ assign hw2reg.err_code.oob_err.de = sw_ctrl_err.oob_err;
+ assign hw2reg.err_code.mp_err.de = sw_ctrl_err.mp_err;
+ assign hw2reg.err_code.rd_err.de = sw_ctrl_err.rd_err;
+ assign hw2reg.err_code.prog_win_err.de = sw_ctrl_err.prog_win_err;
+ assign hw2reg.err_code.prog_type_err.de = sw_ctrl_err.prog_type_err;
+ assign hw2reg.err_code.flash_phy_err.de = sw_ctrl_err.phy_err;
+ assign hw2reg.err_addr.d = {reg2hw.addr.q[31:BusAddrW],ctrl_err_addr};
+ assign hw2reg.err_addr.de = sw_ctrl_err.mp_err |
+ sw_ctrl_err.rd_err |
+ sw_ctrl_err.phy_err;
- for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_single_err_cons
- assign hw2reg.ecc_single_err_addr[bank].d = {flash_phy_rsp.ecc_addr[bank],
- {BusByteWidth{1'b0}}};
- assign hw2reg.ecc_single_err_addr[bank].de = flash_phy_rsp.ecc_single_err[bank];
+ // all hardware interface errors are considered faults
+ assign hw2reg.fault_status.oob_err.d = 1'b1;
+ assign hw2reg.fault_status.mp_err.d = 1'b1;
+ assign hw2reg.fault_status.rd_err.d = 1'b1;
+ assign hw2reg.fault_status.prog_win_err.d = 1'b1;
+ assign hw2reg.fault_status.prog_type_err.d = 1'b1;
+ assign hw2reg.fault_status.flash_phy_err.d = 1'b1;
+ assign hw2reg.fault_status.reg_intg_err.d = 1'b1;
+ assign hw2reg.fault_status.phy_intg_err.d = 1'b1;
+ assign hw2reg.fault_status.oob_err.de = hw_err.oob_err;
+ assign hw2reg.fault_status.mp_err.de = hw_err.mp_err;
+ assign hw2reg.fault_status.rd_err.de = hw_err.rd_err;
+ assign hw2reg.fault_status.prog_win_err.de = hw_err.prog_win_err;
+ assign hw2reg.fault_status.prog_type_err.de = hw_err.prog_type_err;
+ assign hw2reg.fault_status.flash_phy_err.de = hw_err.phy_err;
+ assign hw2reg.fault_status.reg_intg_err.de = intg_err;
+ assign hw2reg.fault_status.phy_intg_err.de = flash_phy_rsp.intg_err;
+
+ // Correctable ECC count / address
+ for (genvar i = 0; i < NumBanks; i++) begin : gen_ecc_single_err_reg
+ assign hw2reg.ecc_single_err_cnt[i].de = flash_phy_rsp.ecc_single_err[i];
+ assign hw2reg.ecc_single_err_cnt[i].d = ®2hw.ecc_single_err_cnt[i].q ?
+ reg2hw.ecc_single_err_cnt[i].q :
+ reg2hw.ecc_single_err_cnt[i].q + 1'b1;
+
+ assign hw2reg.ecc_single_err_addr[i].de = flash_phy_rsp.ecc_single_err[i];
+ assign hw2reg.ecc_single_err_addr[i].d = {flash_phy_rsp.ecc_addr[i], {BusByteWidth{1'b0}}};
end
- for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_multi_err_cons
- assign hw2reg.ecc_multi_err_addr[bank].d = {flash_phy_rsp.ecc_addr[bank],
- {BusByteWidth{1'b0}}};
- assign hw2reg.ecc_multi_err_addr[bank].de = flash_phy_rsp.ecc_multi_err[bank];
- end
-
- logic [7:0] single_err_cnt_d, multi_err_cnt_d;
- always_comb begin
- single_err_cnt_d = reg2hw.ecc_single_err_cnt.q;
- multi_err_cnt_d = reg2hw.ecc_multi_err_cnt.q;
-
- if (|flash_phy_rsp.ecc_single_err && single_err_cnt_d < '1) begin
- single_err_cnt_d = single_err_cnt_d + 1'b1;
- end
-
- if (|flash_phy_rsp.ecc_multi_err && multi_err_cnt_d < '1) begin
- multi_err_cnt_d = multi_err_cnt_d + 1'b1;
- end
- end
-
- // feed back in error count
- assign hw2reg.ecc_single_err_cnt.de = 1'b1;
- assign hw2reg.ecc_single_err_cnt.d = single_err_cnt_d;
- assign hw2reg.ecc_multi_err_cnt.de = 1'b1;
- assign hw2reg.ecc_multi_err_cnt.d = multi_err_cnt_d;
-
- // err code interrupt event
- flash_ctrl_reg2hw_err_code_reg_t err_code_d, err_code_q;
- logic err_code_intr_event;
-
- assign err_code_d = reg2hw.err_code & reg2hw.err_code_intr_en;
-
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- err_code_q <= '0;
- end else begin
- err_code_q <= err_code_d;
- end
- end
-
- assign err_code_intr_event = err_code_d != err_code_q;
-
// general interrupt events
- logic [3:0] intr_src_d;
- logic [3:0] intr_src_q;
+ logic [LastIntrIdx-1:0] intr_event;
- assign intr_src_d = { ~prog_fifo_rvalid,
- reg2hw.fifo_lvl.prog.q == prog_fifo_depth,
- rd_fifo_full,
- reg2hw.fifo_lvl.rd.q == rd_fifo_depth
- };
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(1)
+ ) u_prog_empty_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(~prog_fifo_rvalid),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[ProgEmpty]),
+ .q_negedge_pulse_o()
+ );
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- intr_src_q <= 4'h8; //prog_fifo is empty by default
- end else begin
- if (sw_sel) begin
- intr_src_q[3:0] <= intr_src_d[3:0];
- end
- end
- end
+ prim_intr_hw #(.Width(1)) u_intr_prog_empty (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[ProgEmpty]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.prog_empty.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.prog_empty.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.prog_empty.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.prog_empty.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.prog_empty.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.prog_empty.d),
+ .intr_o (intr_prog_empty_o)
+ );
- // interrupt events
- logic [4:0] intr_assert;
- assign intr_assert[4] = err_code_intr_event;
- assign intr_assert[3:0] = ~intr_src_q & intr_src_d;
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(0)
+ ) u_prog_lvl_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(reg2hw.fifo_lvl.prog.q == prog_fifo_depth),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[ProgLvl]),
+ .q_negedge_pulse_o()
+ );
- assign intr_prog_empty_o = reg2hw.intr_enable.prog_empty.q & reg2hw.intr_state.prog_empty.q;
- assign intr_prog_lvl_o = reg2hw.intr_enable.prog_lvl.q & reg2hw.intr_state.prog_lvl.q;
- assign intr_rd_full_o = reg2hw.intr_enable.rd_full.q & reg2hw.intr_state.rd_full.q;
- assign intr_rd_lvl_o = reg2hw.intr_enable.rd_lvl.q & reg2hw.intr_state.rd_lvl.q;
- assign intr_op_done_o = reg2hw.intr_enable.op_done.q & reg2hw.intr_state.op_done.q;
- assign intr_err_o = reg2hw.intr_enable.err.q & reg2hw.intr_state.err.q;
+ prim_intr_hw #(.Width(1)) u_intr_prog_lvl (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[ProgLvl]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.prog_lvl.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.prog_lvl.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.prog_lvl.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.prog_lvl.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.prog_lvl.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.prog_lvl.d),
+ .intr_o (intr_prog_lvl_o)
+ );
- assign hw2reg.intr_state.err.d = 1'b1;
- assign hw2reg.intr_state.err.de = intr_assert[4] |
- (reg2hw.intr_test.err.qe &
- reg2hw.intr_test.err.q);
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(0)
+ ) u_rd_full_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(rd_fifo_full),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[RdFull]),
+ .q_negedge_pulse_o()
+ );
- assign hw2reg.intr_state.prog_empty.d = 1'b1;
- assign hw2reg.intr_state.prog_empty.de = intr_assert[3] |
- (reg2hw.intr_test.prog_empty.qe &
- reg2hw.intr_test.prog_empty.q);
+ prim_intr_hw #(.Width(1)) u_intr_rd_full (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[RdFull]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rd_full.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.rd_full.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.rd_full.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.rd_full.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.rd_full.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.rd_full.d),
+ .intr_o (intr_rd_full_o)
+ );
- assign hw2reg.intr_state.prog_lvl.d = 1'b1;
- assign hw2reg.intr_state.prog_lvl.de = intr_assert[2] |
- (reg2hw.intr_test.prog_lvl.qe &
- reg2hw.intr_test.prog_lvl.q);
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(0)
+ ) u_rd_lvl_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(reg2hw.fifo_lvl.rd.q == rd_fifo_depth),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[RdLvl]),
+ .q_negedge_pulse_o()
+ );
- assign hw2reg.intr_state.rd_full.d = 1'b1;
- assign hw2reg.intr_state.rd_full.de = intr_assert[1] |
- (reg2hw.intr_test.rd_full.qe &
- reg2hw.intr_test.rd_full.q);
+ prim_intr_hw #(.Width(1)) u_intr_rd_lvl (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[RdLvl]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rd_lvl.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.rd_lvl.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.rd_lvl.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.rd_lvl.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.rd_lvl.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.rd_lvl.d),
+ .intr_o (intr_rd_lvl_o)
+ );
- assign hw2reg.intr_state.rd_lvl.d = 1'b1;
- assign hw2reg.intr_state.rd_lvl.de = intr_assert[0] |
- (reg2hw.intr_test.rd_lvl.qe &
- reg2hw.intr_test.rd_lvl.q);
+ assign intr_event[OpDone] = sw_ctrl_done;
+ assign intr_event[CorrErr] = |flash_phy_rsp.ecc_single_err;
- assign hw2reg.intr_state.op_done.d = 1'b1;
- assign hw2reg.intr_state.op_done.de = sw_ctrl_done |
- (reg2hw.intr_test.op_done.qe &
- reg2hw.intr_test.op_done.q);
+ prim_intr_hw #(.Width(1)) u_intr_op_done (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[OpDone]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.op_done.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.op_done.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.op_done.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.op_done.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.op_done.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.op_done.d),
+ .intr_o (intr_op_done_o)
+ );
-
+ prim_intr_hw #(.Width(1)) u_intr_corr_err (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[CorrErr]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.corr_err.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.corr_err.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.corr_err.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.corr_err.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.corr_err.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.corr_err.d),
+ .intr_o (intr_corr_err_o)
+ );
// Unused bits
logic [BusByteWidth-1:0] unused_byte_sel;
@@ -1143,12 +1197,15 @@
`ASSERT_KNOWN(IntrProgRdFullKnownO_A, intr_rd_full_o )
`ASSERT_KNOWN(IntrRdLvlKnownO_A, intr_rd_lvl_o )
`ASSERT_KNOWN(IntrOpDoneKnownO_A, intr_op_done_o )
- `ASSERT_KNOWN(IntrErrO_A, intr_err_o )
+ `ASSERT_KNOWN(IntrErrO_A, intr_corr_err_o )
-
+ // combined indication that an operation has started
+ // This is used only for assertions
+ logic unused_op_valid;
+ assign unused_op_valid = prog_op_valid | rd_op_valid | erase_op_valid;
// if there is an out of bounds error, flash request should never assert
- `ASSERT(OutofBoundsReq_A, op_valid & op_addr_oob |-> ~flash_phy_req.req)
+ `ASSERT(OutofBoundsReq_A, unused_op_valid & op_addr_oob |-> ~flash_phy_req.req)
// add more assertions
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
index 545e2ec..d41b4bb 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
@@ -364,10 +364,7 @@
logic [BusWidth-1:0] rd_data;
logic init_busy;
logic flash_err;
- logic flash_alert_p;
- logic flash_alert_n;
logic [NumBanks-1:0] ecc_single_err;
- logic [NumBanks-1:0] ecc_multi_err;
logic [NumBanks-1:0][BusAddrW-1:0] ecc_addr;
jtag_pkg::jtag_rsp_t jtag_rsp;
logic intg_err;
@@ -383,10 +380,7 @@
rd_data: '0,
init_busy: 1'b0,
flash_err: 1'b0,
- flash_alert_p: 1'b0,
- flash_alert_n: 1'b1,
ecc_single_err: '0,
- ecc_multi_err: '0,
ecc_addr: '0,
jtag_rsp: '0,
intg_err: '0
@@ -468,6 +462,27 @@
FlashLcDftLast
} flash_lc_jtag_e;
+ // Error bit positioning
+ typedef struct packed {
+ logic oob_err;
+ logic mp_err;
+ logic rd_err;
+ logic prog_win_err;
+ logic prog_type_err;
+ logic phy_err;
+ } flash_ctrl_err_t;
+
+ // interrupt bit positioning
+ typedef enum logic[2:0] {
+ ProgEmpty,
+ ProgLvl,
+ RdFull,
+ RdLvl,
+ OpDone,
+ CorrErr,
+ LastIntrIdx
+ } flash_ctrl_intr_e;
+
// find the max number pages among info types
function automatic integer max_info_pages(int infos[InfoTypes]);
int current_max = 0;
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
index 9695ad0..fab4915 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
@@ -22,7 +22,7 @@
// parameters
parameter string LIST_OF_ALERTS[] = {
- "recov_err", "recov_mp_err", "recov_ecc_err", "fatal_intg_err"
+ "recov_err", "fatal_err"
};
parameter uint NUM_ALERTS = 4;
diff --git a/hw/ip/flash_ctrl/dv/tb/tb.sv b/hw/ip/flash_ctrl/dv/tb/tb.sv
index d47739f..1b2a162 100644
--- a/hw/ip/flash_ctrl/dv/tb/tb.sv
+++ b/hw/ip/flash_ctrl/dv/tb/tb.sv
@@ -99,7 +99,7 @@
.intr_rd_full_o (intr_rd_full ),
.intr_rd_lvl_o (intr_rd_lvl ),
.intr_op_done_o (intr_op_done ),
- .intr_err_o (intr_err ),
+ .intr_corr_err_o (intr_err ),
.alert_rx_i (alert_rx ),
.alert_tx_o (alert_tx )
);
diff --git a/hw/ip/flash_ctrl/flash_ctrl.core b/hw/ip/flash_ctrl/flash_ctrl.core
index a52c69b..0466737 100644
--- a/hw/ip/flash_ctrl/flash_ctrl.core
+++ b/hw/ip/flash_ctrl/flash_ctrl.core
@@ -10,6 +10,7 @@
depend:
- lowrisc:ip:tlul
- lowrisc:prim:all
+ - lowrisc:prim:edge_detector
- lowrisc:prim:secded
- lowrisc:prim:lfsr
- lowrisc:prim:flash
diff --git a/hw/ip/flash_ctrl/lint/flash_ctrl.waiver b/hw/ip/flash_ctrl/lint/flash_ctrl.waiver
index ad4073d..171ab8e 100644
--- a/hw/ip/flash_ctrl/lint/flash_ctrl.waiver
+++ b/hw/ip/flash_ctrl/lint/flash_ctrl.waiver
@@ -21,3 +21,7 @@
waive -rules INPUT_NOT_READ -location {prim_flop_2sync.sv} -regexp {Input port.*} \
-comment "Silience prim related errors"
+
+# State is handled as part of "default"
+waive -rules MISSING_STATE -location {flash_phy_core.sv} \
+ -regexp {.*'StDisable' does not have corresponding case branch tag}
\ No newline at end of file
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
index 029a5dd..fae6622 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
@@ -58,7 +58,7 @@
output logic cio_tdo_o,
// Interrupts
- output logic intr_err_o, // ERR_CODE is non-zero
+ output logic intr_corr_err_o, // Correctable errors encountered
output logic intr_prog_empty_o, // Program fifo is empty
output logic intr_prog_lvl_o, // Program fifo is empty
output logic intr_rd_full_o, // Read fifo is full
@@ -144,18 +144,16 @@
flash_erase_e erase_flash_type;
logic erase_op_valid;
- // combined indication that an operation has started
- logic op_valid;
-
// Done / Error signaling from ctrl modules
logic prog_done, rd_done, erase_done;
- logic prog_err, rd_err, erase_err;
+ flash_ctrl_err_t prog_err, rd_err, erase_err;
+ logic [BusAddrW-1:0] prog_err_addr, rd_err_addr, erase_err_addr;
// Flash Memory Properties Connections
logic [BusAddrW-1:0] flash_addr;
logic flash_req;
logic flash_rd_done, flash_prog_done, flash_erase_done;
- logic flash_mp_error;
+ logic flash_mp_err;
logic [BusWidth-1:0] flash_prog_data;
logic flash_prog_last;
flash_prog_e flash_prog_type;
@@ -165,7 +163,6 @@
logic rd_op;
logic prog_op;
logic erase_op;
- logic [AllPagesW-1:0] err_addr;
flash_lcmgr_phase_e phase;
// Flash control arbitration connections to hardware interface
@@ -177,7 +174,7 @@
logic hw_req;
logic [top_pkg::TL_AW-1:0] hw_addr;
logic hw_done;
- logic hw_err;
+ flash_ctrl_err_t hw_err;
logic hw_rvalid;
logic hw_rready;
logic hw_wvalid;
@@ -191,7 +188,7 @@
// Flash control arbitration connections to software interface
logic sw_ctrl_done;
- logic sw_ctrl_err;
+ flash_ctrl_err_t sw_ctrl_err;
// Flash control muxed connections
flash_ctrl_reg2hw_control_reg_t muxed_ctrl;
@@ -199,6 +196,7 @@
logic op_start;
logic [11:0] op_num_words;
logic [BusAddrW-1:0] op_addr;
+ logic [BusAddrW-1:0] ctrl_err_addr;
// SW or HW supplied address is out of bounds
logic op_addr_oob;
flash_op_e op_type;
@@ -305,6 +303,9 @@
.clk_i,
.rst_ni,
+ // error output shared by both interfaces
+ .ctrl_err_addr_o(ctrl_err_addr),
+
// software interface to rd_ctrl / erase_ctrl
.sw_ctrl_i(reg2hw.control),
.sw_addr_i(reg2hw.addr.q),
@@ -346,10 +347,13 @@
.muxed_addr_o(muxed_addr),
.prog_ack_i(prog_done),
.prog_err_i(prog_err),
+ .prog_err_addr_i(prog_err_addr),
.rd_ack_i(rd_done),
.rd_err_i(rd_err),
+ .rd_err_addr_i(rd_err_addr),
.erase_ack_i(erase_done),
.erase_err_i(erase_err),
+ .erase_err_addr_i(erase_err_addr),
// muxed interface to rd_fifo
.rd_fifo_rvalid_i(rd_fifo_rvalid),
@@ -388,7 +392,6 @@
assign prog_op = op_type == FlashOpProgram;
assign erase_op = op_type == FlashOpErase;
assign sw_sel = if_sel == SwSel;
- assign op_valid = prog_op_valid | rd_op_valid | erase_op_valid;
// software privilege to creator seed
assign creator_seed_priv = lc_creator_seed_sw_rw_en == lc_ctrl_pkg::On;
@@ -524,6 +527,7 @@
.op_addr_oob_i (op_addr_oob),
.op_type_i (op_prog_type),
.type_avail_i (prog_type_en),
+ .op_err_addr_o (prog_err_addr),
// FIFO Interface
.data_i (prog_fifo_rdata),
@@ -538,7 +542,9 @@
.flash_last_o (flash_prog_last),
.flash_type_o (flash_prog_type),
.flash_done_i (flash_prog_done),
- .flash_error_i (flash_mp_error)
+ // TODO, pending feedback
+ .flash_phy_err_i(flash_phy_rsp.flash_err),
+ .flash_mp_err_i (flash_mp_err)
);
always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -602,6 +608,7 @@
.op_num_words_i (op_num_words),
.op_done_o (rd_done),
.op_err_o (rd_err),
+ .op_err_addr_o (rd_err_addr),
.op_addr_i (op_addr),
.op_addr_oob_i (op_addr_oob),
@@ -616,7 +623,9 @@
.flash_ovfl_o (rd_flash_ovfl),
.flash_data_i (flash_rd_data),
.flash_done_i (flash_rd_done),
- .flash_error_i (flash_mp_error | flash_rd_err)
+ .flash_mp_err_i (flash_mp_err),
+ .flash_rd_err_i (flash_rd_err),
+ .flash_phy_err_i(flash_phy_rsp.flash_err)
);
// Erase handler does not consume fifo
@@ -629,13 +638,15 @@
.op_err_o (erase_err),
.op_addr_i (op_addr),
.op_addr_oob_i (op_addr_oob),
+ .op_err_addr_o (erase_err_addr),
// Flash Macro Interface
.flash_req_o (erase_flash_req),
.flash_addr_o (erase_flash_addr),
.flash_op_o (erase_flash_type),
.flash_done_i (flash_erase_done),
- .flash_error_i (flash_mp_error)
+ .flash_mp_err_i (flash_mp_err),
+ .flash_phy_err_i(flash_phy_rsp.flash_err)
);
// Final muxing to flash macro module
@@ -756,8 +767,7 @@
.rd_done_o(flash_rd_done),
.prog_done_o(flash_prog_done),
.erase_done_o(flash_erase_done),
- .error_o(flash_mp_error),
- .err_addr_o(err_addr),
+ .error_o(flash_mp_err),
// flash phy interface
.req_o(flash_phy_req.req),
@@ -781,7 +791,7 @@
assign hw2reg.op_status.done.d = 1'b1;
assign hw2reg.op_status.done.de = sw_ctrl_done;
assign hw2reg.op_status.err.d = 1'b1;
- assign hw2reg.op_status.err.de = sw_ctrl_err;
+ assign hw2reg.op_status.err.de = |sw_ctrl_err;
assign hw2reg.status.rd_full.d = rd_fifo_full;
assign hw2reg.status.rd_full.de = sw_sel;
assign hw2reg.status.rd_empty.d = ~rd_fifo_rvalid;
@@ -856,31 +866,24 @@
logic [NumAlerts-1:0] alert_srcs;
logic [NumAlerts-1:0] alert_tests;
+ // TODO Add shadow update
+ // An excessive number of recoverable errors may also indicate an attack
logic recov_err;
- assign recov_err = flash_phy_rsp.flash_alert_p | ~flash_phy_rsp.flash_alert_n;
+ assign recov_err = sw_ctrl_done & |sw_ctrl_err;
- logic recov_mp_err;
- assign recov_mp_err = flash_mp_error;
+ logic fatal_err;
+ assign fatal_err = |reg2hw.fault_status;
- logic recov_ecc_err;
- assign recov_ecc_err = |flash_phy_rsp.ecc_single_err | |flash_phy_rsp.ecc_multi_err;
- logic fatal_intg_err;
- assign fatal_intg_err = flash_phy_rsp.intg_err | intg_err;
-
- assign alert_srcs = { fatal_intg_err,
- recov_ecc_err,
- recov_mp_err,
+ assign alert_srcs = { fatal_err,
recov_err
};
- assign alert_tests = { reg2hw.alert_test.fatal_intg_err.q & reg2hw.alert_test.fatal_intg_err.qe,
- reg2hw.alert_test.recov_ecc_err.q & reg2hw.alert_test.recov_ecc_err.qe,
- reg2hw.alert_test.recov_mp_err.q & reg2hw.alert_test.recov_mp_err.qe,
- reg2hw.alert_test.recov_err.q & reg2hw.alert_test.recov_err.qe
+ assign alert_tests = { reg2hw.alert_test.fatal_err.q & reg2hw.alert_test.fatal_err.qe,
+ reg2hw.alert_test.recov_err.q & reg2hw.alert_test.recov_err.qe
};
- localparam logic [NumAlerts-1:0] IsFatal = {1'b1, 1'b0, 1'b0, 1'b0};
+ localparam logic [NumAlerts-1:0] IsFatal = {1'b1, 1'b0};
for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_senders
prim_alert_sender #(
.AsyncOn(AlertAsyncOn[i]),
@@ -901,7 +904,7 @@
// Flash Disable
//////////////////////////////////////
assign flash_disable = reg2hw.flash_disable.q ? lc_ctrl_pkg::On :
- fatal_intg_err ? lc_ctrl_pkg::On : lc_ctrl_pkg::Off;
+ fatal_err ? lc_ctrl_pkg::On : lc_ctrl_pkg::Off;
lc_ctrl_pkg::lc_tx_t lc_escalate_en;
prim_lc_sync #(
@@ -919,133 +922,184 @@
// Errors and Interrupts
//////////////////////////////////////
- assign hw2reg.err_code.oob_err.d = 1'b1;
- assign hw2reg.err_code.mp_err.d = 1'b1;
- assign hw2reg.err_code.ecc_single_err.d = 1'b1;
- assign hw2reg.err_code.ecc_multi_err.d = 1'b1;
- assign hw2reg.err_code.flash_err.d = 1'b1;
- assign hw2reg.err_code.flash_alert.d = 1'b1;
- assign hw2reg.err_code.oob_err.de = op_valid & op_addr_oob;
- assign hw2reg.err_code.mp_err.de = flash_mp_error;
- assign hw2reg.err_code.ecc_single_err.de = |flash_phy_rsp.ecc_single_err;
- assign hw2reg.err_code.ecc_multi_err.de = |flash_phy_rsp.ecc_multi_err;
- assign hw2reg.err_code.flash_err.de = flash_phy_rsp.flash_err;
- assign hw2reg.err_code.flash_alert.de = flash_phy_rsp.flash_alert_p |
- ~flash_phy_rsp.flash_alert_n;
- assign hw2reg.err_addr.d = err_addr;
- assign hw2reg.err_addr.de = flash_mp_error;
+ // all software interface errors are treated as synchronous errors
+ assign hw2reg.err_code.oob_err.d = 1'b1;
+ assign hw2reg.err_code.mp_err.d = 1'b1;
+ assign hw2reg.err_code.rd_err.d = 1'b1;
+ assign hw2reg.err_code.prog_win_err.d = 1'b1;
+ assign hw2reg.err_code.prog_type_err.d = 1'b1;
+ assign hw2reg.err_code.flash_phy_err.d = 1'b1;
+ assign hw2reg.err_code.oob_err.de = sw_ctrl_err.oob_err;
+ assign hw2reg.err_code.mp_err.de = sw_ctrl_err.mp_err;
+ assign hw2reg.err_code.rd_err.de = sw_ctrl_err.rd_err;
+ assign hw2reg.err_code.prog_win_err.de = sw_ctrl_err.prog_win_err;
+ assign hw2reg.err_code.prog_type_err.de = sw_ctrl_err.prog_type_err;
+ assign hw2reg.err_code.flash_phy_err.de = sw_ctrl_err.phy_err;
+ assign hw2reg.err_addr.d = {reg2hw.addr.q[31:BusAddrW],ctrl_err_addr};
+ assign hw2reg.err_addr.de = sw_ctrl_err.mp_err |
+ sw_ctrl_err.rd_err |
+ sw_ctrl_err.phy_err;
- for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_single_err_cons
- assign hw2reg.ecc_single_err_addr[bank].d = {flash_phy_rsp.ecc_addr[bank],
- {BusByteWidth{1'b0}}};
- assign hw2reg.ecc_single_err_addr[bank].de = flash_phy_rsp.ecc_single_err[bank];
+ // all hardware interface errors are considered faults
+ assign hw2reg.fault_status.oob_err.d = 1'b1;
+ assign hw2reg.fault_status.mp_err.d = 1'b1;
+ assign hw2reg.fault_status.rd_err.d = 1'b1;
+ assign hw2reg.fault_status.prog_win_err.d = 1'b1;
+ assign hw2reg.fault_status.prog_type_err.d = 1'b1;
+ assign hw2reg.fault_status.flash_phy_err.d = 1'b1;
+ assign hw2reg.fault_status.reg_intg_err.d = 1'b1;
+ assign hw2reg.fault_status.phy_intg_err.d = 1'b1;
+ assign hw2reg.fault_status.oob_err.de = hw_err.oob_err;
+ assign hw2reg.fault_status.mp_err.de = hw_err.mp_err;
+ assign hw2reg.fault_status.rd_err.de = hw_err.rd_err;
+ assign hw2reg.fault_status.prog_win_err.de = hw_err.prog_win_err;
+ assign hw2reg.fault_status.prog_type_err.de = hw_err.prog_type_err;
+ assign hw2reg.fault_status.flash_phy_err.de = hw_err.phy_err;
+ assign hw2reg.fault_status.reg_intg_err.de = intg_err;
+ assign hw2reg.fault_status.phy_intg_err.de = flash_phy_rsp.intg_err;
+
+ // Correctable ECC count / address
+ for (genvar i = 0; i < NumBanks; i++) begin : gen_ecc_single_err_reg
+ assign hw2reg.ecc_single_err_cnt[i].de = flash_phy_rsp.ecc_single_err[i];
+ assign hw2reg.ecc_single_err_cnt[i].d = ®2hw.ecc_single_err_cnt[i].q ?
+ reg2hw.ecc_single_err_cnt[i].q :
+ reg2hw.ecc_single_err_cnt[i].q + 1'b1;
+
+ assign hw2reg.ecc_single_err_addr[i].de = flash_phy_rsp.ecc_single_err[i];
+ assign hw2reg.ecc_single_err_addr[i].d = {flash_phy_rsp.ecc_addr[i], {BusByteWidth{1'b0}}};
end
- for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_multi_err_cons
- assign hw2reg.ecc_multi_err_addr[bank].d = {flash_phy_rsp.ecc_addr[bank],
- {BusByteWidth{1'b0}}};
- assign hw2reg.ecc_multi_err_addr[bank].de = flash_phy_rsp.ecc_multi_err[bank];
- end
-
- logic [7:0] single_err_cnt_d, multi_err_cnt_d;
- always_comb begin
- single_err_cnt_d = reg2hw.ecc_single_err_cnt.q;
- multi_err_cnt_d = reg2hw.ecc_multi_err_cnt.q;
-
- if (|flash_phy_rsp.ecc_single_err && single_err_cnt_d < '1) begin
- single_err_cnt_d = single_err_cnt_d + 1'b1;
- end
-
- if (|flash_phy_rsp.ecc_multi_err && multi_err_cnt_d < '1) begin
- multi_err_cnt_d = multi_err_cnt_d + 1'b1;
- end
- end
-
- // feed back in error count
- assign hw2reg.ecc_single_err_cnt.de = 1'b1;
- assign hw2reg.ecc_single_err_cnt.d = single_err_cnt_d;
- assign hw2reg.ecc_multi_err_cnt.de = 1'b1;
- assign hw2reg.ecc_multi_err_cnt.d = multi_err_cnt_d;
-
- // err code interrupt event
- flash_ctrl_reg2hw_err_code_reg_t err_code_d, err_code_q;
- logic err_code_intr_event;
-
- assign err_code_d = reg2hw.err_code & reg2hw.err_code_intr_en;
-
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- err_code_q <= '0;
- end else begin
- err_code_q <= err_code_d;
- end
- end
-
- assign err_code_intr_event = err_code_d != err_code_q;
-
// general interrupt events
- logic [3:0] intr_src_d;
- logic [3:0] intr_src_q;
+ logic [LastIntrIdx-1:0] intr_event;
- assign intr_src_d = { ~prog_fifo_rvalid,
- reg2hw.fifo_lvl.prog.q == prog_fifo_depth,
- rd_fifo_full,
- reg2hw.fifo_lvl.rd.q == rd_fifo_depth
- };
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(1)
+ ) u_prog_empty_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(~prog_fifo_rvalid),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[ProgEmpty]),
+ .q_negedge_pulse_o()
+ );
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- intr_src_q <= 4'h8; //prog_fifo is empty by default
- end else begin
- if (sw_sel) begin
- intr_src_q[3:0] <= intr_src_d[3:0];
- end
- end
- end
+ prim_intr_hw #(.Width(1)) u_intr_prog_empty (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[ProgEmpty]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.prog_empty.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.prog_empty.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.prog_empty.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.prog_empty.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.prog_empty.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.prog_empty.d),
+ .intr_o (intr_prog_empty_o)
+ );
- // interrupt events
- logic [4:0] intr_assert;
- assign intr_assert[4] = err_code_intr_event;
- assign intr_assert[3:0] = ~intr_src_q & intr_src_d;
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(0)
+ ) u_prog_lvl_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(reg2hw.fifo_lvl.prog.q == prog_fifo_depth),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[ProgLvl]),
+ .q_negedge_pulse_o()
+ );
- assign intr_prog_empty_o = reg2hw.intr_enable.prog_empty.q & reg2hw.intr_state.prog_empty.q;
- assign intr_prog_lvl_o = reg2hw.intr_enable.prog_lvl.q & reg2hw.intr_state.prog_lvl.q;
- assign intr_rd_full_o = reg2hw.intr_enable.rd_full.q & reg2hw.intr_state.rd_full.q;
- assign intr_rd_lvl_o = reg2hw.intr_enable.rd_lvl.q & reg2hw.intr_state.rd_lvl.q;
- assign intr_op_done_o = reg2hw.intr_enable.op_done.q & reg2hw.intr_state.op_done.q;
- assign intr_err_o = reg2hw.intr_enable.err.q & reg2hw.intr_state.err.q;
+ prim_intr_hw #(.Width(1)) u_intr_prog_lvl (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[ProgLvl]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.prog_lvl.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.prog_lvl.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.prog_lvl.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.prog_lvl.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.prog_lvl.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.prog_lvl.d),
+ .intr_o (intr_prog_lvl_o)
+ );
- assign hw2reg.intr_state.err.d = 1'b1;
- assign hw2reg.intr_state.err.de = intr_assert[4] |
- (reg2hw.intr_test.err.qe &
- reg2hw.intr_test.err.q);
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(0)
+ ) u_rd_full_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(rd_fifo_full),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[RdFull]),
+ .q_negedge_pulse_o()
+ );
- assign hw2reg.intr_state.prog_empty.d = 1'b1;
- assign hw2reg.intr_state.prog_empty.de = intr_assert[3] |
- (reg2hw.intr_test.prog_empty.qe &
- reg2hw.intr_test.prog_empty.q);
+ prim_intr_hw #(.Width(1)) u_intr_rd_full (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[RdFull]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rd_full.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.rd_full.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.rd_full.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.rd_full.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.rd_full.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.rd_full.d),
+ .intr_o (intr_rd_full_o)
+ );
- assign hw2reg.intr_state.prog_lvl.d = 1'b1;
- assign hw2reg.intr_state.prog_lvl.de = intr_assert[2] |
- (reg2hw.intr_test.prog_lvl.qe &
- reg2hw.intr_test.prog_lvl.q);
+ prim_edge_detector #(
+ .Width(1),
+ .ResetValue(0)
+ ) u_rd_lvl_event (
+ .clk_i,
+ .rst_ni,
+ .d_i(reg2hw.fifo_lvl.rd.q == rd_fifo_depth),
+ .q_sync_o(),
+ .q_posedge_pulse_o(intr_event[RdLvl]),
+ .q_negedge_pulse_o()
+ );
- assign hw2reg.intr_state.rd_full.d = 1'b1;
- assign hw2reg.intr_state.rd_full.de = intr_assert[1] |
- (reg2hw.intr_test.rd_full.qe &
- reg2hw.intr_test.rd_full.q);
+ prim_intr_hw #(.Width(1)) u_intr_rd_lvl (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[RdLvl]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rd_lvl.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.rd_lvl.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.rd_lvl.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.rd_lvl.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.rd_lvl.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.rd_lvl.d),
+ .intr_o (intr_rd_lvl_o)
+ );
- assign hw2reg.intr_state.rd_lvl.d = 1'b1;
- assign hw2reg.intr_state.rd_lvl.de = intr_assert[0] |
- (reg2hw.intr_test.rd_lvl.qe &
- reg2hw.intr_test.rd_lvl.q);
+ assign intr_event[OpDone] = sw_ctrl_done;
+ assign intr_event[CorrErr] = |flash_phy_rsp.ecc_single_err;
- assign hw2reg.intr_state.op_done.d = 1'b1;
- assign hw2reg.intr_state.op_done.de = sw_ctrl_done |
- (reg2hw.intr_test.op_done.qe &
- reg2hw.intr_test.op_done.q);
+ prim_intr_hw #(.Width(1)) u_intr_op_done (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[OpDone]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.op_done.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.op_done.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.op_done.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.op_done.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.op_done.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.op_done.d),
+ .intr_o (intr_op_done_o)
+ );
-
+ prim_intr_hw #(.Width(1)) u_intr_corr_err (
+ .clk_i,
+ .rst_ni,
+ .event_intr_i (intr_event[CorrErr]),
+ .reg2hw_intr_enable_q_i (reg2hw.intr_enable.corr_err.q),
+ .reg2hw_intr_test_q_i (reg2hw.intr_test.corr_err.q),
+ .reg2hw_intr_test_qe_i (reg2hw.intr_test.corr_err.qe),
+ .reg2hw_intr_state_q_i (reg2hw.intr_state.corr_err.q),
+ .hw2reg_intr_state_de_o (hw2reg.intr_state.corr_err.de),
+ .hw2reg_intr_state_d_o (hw2reg.intr_state.corr_err.d),
+ .intr_o (intr_corr_err_o)
+ );
// Unused bits
logic [BusByteWidth-1:0] unused_byte_sel;
@@ -1144,12 +1198,15 @@
`ASSERT_KNOWN(IntrProgRdFullKnownO_A, intr_rd_full_o )
`ASSERT_KNOWN(IntrRdLvlKnownO_A, intr_rd_lvl_o )
`ASSERT_KNOWN(IntrOpDoneKnownO_A, intr_op_done_o )
- `ASSERT_KNOWN(IntrErrO_A, intr_err_o )
+ `ASSERT_KNOWN(IntrErrO_A, intr_corr_err_o )
-
+ // combined indication that an operation has started
+ // This is used only for assertions
+ logic unused_op_valid;
+ assign unused_op_valid = prog_op_valid | rd_op_valid | erase_op_valid;
// if there is an out of bounds error, flash request should never assert
- `ASSERT(OutofBoundsReq_A, op_valid & op_addr_oob |-> ~flash_phy_req.req)
+ `ASSERT(OutofBoundsReq_A, unused_op_valid & op_addr_oob |-> ~flash_phy_req.req)
// add more assertions
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
index 0ec54d7..1963079 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
@@ -16,11 +16,14 @@
input clk_i,
input rst_ni,
+ // error address shared between interfaces
+ output logic [BusAddrW-1:0] ctrl_err_addr_o,
+
// software interface to rd_ctrl / erase_ctrl
input flash_ctrl_reg_pkg::flash_ctrl_reg2hw_control_reg_t sw_ctrl_i,
input [31:0] sw_addr_i,
output logic sw_ack_o,
- output logic sw_err_o,
+ output flash_ctrl_err_t sw_err_o,
// software interface to rd_fifo
output logic sw_rvalid_o,
@@ -37,7 +40,7 @@
input flash_lcmgr_phase_e hw_phase_i,
input [31:0] hw_addr_i,
output logic hw_ack_o,
- output logic hw_err_o,
+ output flash_ctrl_err_t hw_err_o,
// hardware interface to rd_fifo
output logic hw_rvalid_o,
@@ -52,11 +55,14 @@
output flash_ctrl_reg_pkg::flash_ctrl_reg2hw_control_reg_t muxed_ctrl_o,
output logic [31:0] muxed_addr_o,
input prog_ack_i,
- input prog_err_i,
+ input flash_ctrl_err_t prog_err_i,
+ input [BusAddrW-1:0] prog_err_addr_i,
input rd_ack_i,
- input rd_err_i,
+ input flash_ctrl_err_t rd_err_i,
+ input [BusAddrW-1:0] rd_err_addr_i,
input erase_ack_i,
- input erase_err_i,
+ input flash_ctrl_err_t erase_err_i,
+ input [BusAddrW-1:0] erase_err_addr_i,
// muxed interface to rd_fifo
input rd_fifo_rvalid_i,
@@ -156,22 +162,23 @@
endcase // unique case (state_q)
end // always_comb
- logic ctrl_ack, ctrl_err;
+ logic ctrl_ack;
+ flash_ctrl_err_t ctrl_err;
always_comb begin
muxed_ctrl_o = '0;
muxed_addr_o = '0;
- sw_ack_o = 1'b0;
- sw_err_o = 1'b0;
- sw_rvalid_o = 1'b0;
- sw_wready_o = 1'b0;
- hw_ack_o = 1'b0;
- hw_err_o = 1'b0;
- hw_rvalid_o = 1'b0;
- hw_wready_o = 1'b0;
- prog_fifo_wvalid_o = 1'b0;
+ sw_ack_o = '0;
+ sw_err_o = '0;
+ sw_rvalid_o = '0;
+ sw_wready_o = '0;
+ hw_ack_o = '0;
+ hw_err_o = '0;
+ hw_rvalid_o = '0;
+ hw_wready_o = '0;
+ prog_fifo_wvalid_o = '0;
prog_fifo_wdata_o = '0;
- rd_fifo_rready_o = 1'b0;
+ rd_fifo_rready_o = '0;
unique case (func_sel)
HwSel: begin
@@ -213,16 +220,29 @@
always_comb begin
ctrl_ack = '0;
ctrl_err = '0;
- if (muxed_ctrl_o.op.q == FlashOpProgram) begin
- ctrl_ack = prog_ack_i;
- ctrl_err = prog_err_i;
- end else if (muxed_ctrl_o.op.q == FlashOpErase) begin
- ctrl_ack = erase_ack_i;
- ctrl_err = erase_err_i;
- end else if (muxed_ctrl_o.op.q == FlashOpRead) begin
- ctrl_ack = rd_ack_i;
- ctrl_err = rd_err_i;
- end
+ ctrl_err_addr_o = '0;
+
+ unique case (muxed_ctrl_o.op.q)
+ FlashOpProgram: begin
+ ctrl_ack = prog_ack_i;
+ ctrl_err = prog_err_i;
+ ctrl_err_addr_o = prog_err_addr_i;
+ end
+
+ FlashOpErase: begin
+ ctrl_ack = erase_ack_i;
+ ctrl_err = erase_err_i;
+ ctrl_err_addr_o = erase_err_addr_i;
+ end
+
+ FlashOpRead: begin
+ ctrl_ack = rd_ack_i;
+ ctrl_err = rd_err_i;
+ ctrl_err_addr_o = rd_err_addr_i;
+ end
+
+ default:;
+ endcase // unique case (muxed_ctrl_o.op.q)
end
assign sel_o = func_sel;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv
index 4ca672f..59d2a99 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv
@@ -121,10 +121,10 @@
reg_steer = 2; // Default set to register
// TODO: Can below codes be unique case () inside ?
- if (tl_i.a_address[AW-1:0] >= 400 && tl_i.a_address[AW-1:0] < 404) begin
+ if (tl_i.a_address[AW-1:0] >= 388 && tl_i.a_address[AW-1:0] < 392) begin
reg_steer = 0;
end
- if (tl_i.a_address[AW-1:0] >= 404 && tl_i.a_address[AW-1:0] < 408) begin
+ if (tl_i.a_address[AW-1:0] >= 392 && tl_i.a_address[AW-1:0] < 396) begin
reg_steer = 1;
end
if (intg_err) begin
@@ -172,8 +172,8 @@
logic intr_state_rd_lvl_wd;
logic intr_state_op_done_qs;
logic intr_state_op_done_wd;
- logic intr_state_err_qs;
- logic intr_state_err_wd;
+ logic intr_state_corr_err_qs;
+ logic intr_state_corr_err_wd;
logic intr_enable_we;
logic intr_enable_prog_empty_qs;
logic intr_enable_prog_empty_wd;
@@ -185,20 +185,18 @@
logic intr_enable_rd_lvl_wd;
logic intr_enable_op_done_qs;
logic intr_enable_op_done_wd;
- logic intr_enable_err_qs;
- logic intr_enable_err_wd;
+ logic intr_enable_corr_err_qs;
+ logic intr_enable_corr_err_wd;
logic intr_test_we;
logic intr_test_prog_empty_wd;
logic intr_test_prog_lvl_wd;
logic intr_test_rd_full_wd;
logic intr_test_rd_lvl_wd;
logic intr_test_op_done_wd;
- logic intr_test_err_wd;
+ logic intr_test_corr_err_wd;
logic alert_test_we;
logic alert_test_recov_err_wd;
- logic alert_test_recov_mp_err_wd;
- logic alert_test_recov_ecc_err_wd;
- logic alert_test_fatal_intg_err_wd;
+ logic alert_test_fatal_err_wd;
logic flash_disable_we;
logic flash_disable_qs;
logic flash_disable_wd;
@@ -908,43 +906,35 @@
logic status_prog_full_qs;
logic status_prog_empty_qs;
logic status_init_wip_qs;
- logic err_code_intr_en_we;
- logic err_code_intr_en_flash_err_en_qs;
- logic err_code_intr_en_flash_err_en_wd;
- logic err_code_intr_en_flash_alert_en_qs;
- logic err_code_intr_en_flash_alert_en_wd;
- logic err_code_intr_en_oob_err_qs;
- logic err_code_intr_en_oob_err_wd;
- logic err_code_intr_en_mp_err_qs;
- logic err_code_intr_en_mp_err_wd;
- logic err_code_intr_en_ecc_single_err_qs;
- logic err_code_intr_en_ecc_single_err_wd;
- logic err_code_intr_en_ecc_multi_err_qs;
- logic err_code_intr_en_ecc_multi_err_wd;
logic err_code_we;
- logic err_code_flash_err_qs;
- logic err_code_flash_err_wd;
- logic err_code_flash_alert_qs;
- logic err_code_flash_alert_wd;
logic err_code_oob_err_qs;
logic err_code_oob_err_wd;
logic err_code_mp_err_qs;
logic err_code_mp_err_wd;
- logic err_code_ecc_single_err_qs;
- logic err_code_ecc_single_err_wd;
- logic err_code_ecc_multi_err_qs;
- logic err_code_ecc_multi_err_wd;
- logic [8:0] err_addr_qs;
+ logic err_code_rd_err_qs;
+ logic err_code_rd_err_wd;
+ logic err_code_prog_win_err_qs;
+ logic err_code_prog_win_err_wd;
+ logic err_code_prog_type_err_qs;
+ logic err_code_prog_type_err_wd;
+ logic err_code_flash_phy_err_qs;
+ logic err_code_flash_phy_err_wd;
+ logic fault_status_oob_err_qs;
+ logic fault_status_mp_err_qs;
+ logic fault_status_rd_err_qs;
+ logic fault_status_prog_win_err_qs;
+ logic fault_status_prog_type_err_qs;
+ logic fault_status_flash_phy_err_qs;
+ logic fault_status_reg_intg_err_qs;
+ logic fault_status_phy_intg_err_qs;
+ logic [31:0] err_addr_qs;
logic ecc_single_err_cnt_we;
- logic [7:0] ecc_single_err_cnt_qs;
- logic [7:0] ecc_single_err_cnt_wd;
+ logic [7:0] ecc_single_err_cnt_ecc_single_err_cnt_0_qs;
+ logic [7:0] ecc_single_err_cnt_ecc_single_err_cnt_0_wd;
+ logic [7:0] ecc_single_err_cnt_ecc_single_err_cnt_1_qs;
+ logic [7:0] ecc_single_err_cnt_ecc_single_err_cnt_1_wd;
logic [19:0] ecc_single_err_addr_0_qs;
logic [19:0] ecc_single_err_addr_1_qs;
- logic ecc_multi_err_cnt_we;
- logic [7:0] ecc_multi_err_cnt_qs;
- logic [7:0] ecc_multi_err_cnt_wd;
- logic [19:0] ecc_multi_err_addr_0_qs;
- logic [19:0] ecc_multi_err_addr_1_qs;
logic phy_err_cfg_regwen_we;
logic phy_err_cfg_regwen_qs;
logic phy_err_cfg_regwen_wd;
@@ -1098,29 +1088,29 @@
.qs (intr_state_op_done_qs)
);
- // F[err]: 5:5
+ // F[corr_err]: 5:5
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
.RESVAL (1'h0)
- ) u_intr_state_err (
+ ) u_intr_state_corr_err (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (intr_state_we),
- .wd (intr_state_err_wd),
+ .wd (intr_state_corr_err_wd),
// from internal hardware
- .de (hw2reg.intr_state.err.de),
- .d (hw2reg.intr_state.err.d),
+ .de (hw2reg.intr_state.corr_err.de),
+ .d (hw2reg.intr_state.corr_err.d),
// to internal hardware
.qe (),
- .q (reg2hw.intr_state.err.q),
+ .q (reg2hw.intr_state.corr_err.q),
// to register interface (read)
- .qs (intr_state_err_qs)
+ .qs (intr_state_corr_err_qs)
);
@@ -1250,18 +1240,18 @@
.qs (intr_enable_op_done_qs)
);
- // F[err]: 5:5
+ // F[corr_err]: 5:5
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRW),
.RESVAL (1'h0)
- ) u_intr_enable_err (
+ ) u_intr_enable_corr_err (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (intr_enable_we),
- .wd (intr_enable_err_wd),
+ .wd (intr_enable_corr_err_wd),
// from internal hardware
.de (1'b0),
@@ -1269,10 +1259,10 @@
// to internal hardware
.qe (),
- .q (reg2hw.intr_enable.err.q),
+ .q (reg2hw.intr_enable.corr_err.q),
// to register interface (read)
- .qs (intr_enable_err_qs)
+ .qs (intr_enable_corr_err_qs)
);
@@ -1347,17 +1337,17 @@
.qs ()
);
- // F[err]: 5:5
+ // F[corr_err]: 5:5
prim_subreg_ext #(
.DW (1)
- ) u_intr_test_err (
+ ) u_intr_test_corr_err (
.re (1'b0),
.we (intr_test_we),
- .wd (intr_test_err_wd),
+ .wd (intr_test_corr_err_wd),
.d ('0),
.qre (),
- .qe (reg2hw.intr_test.err.qe),
- .q (reg2hw.intr_test.err.q),
+ .qe (reg2hw.intr_test.corr_err.qe),
+ .q (reg2hw.intr_test.corr_err.q),
.qs ()
);
@@ -1377,45 +1367,17 @@
.qs ()
);
- // F[recov_mp_err]: 1:1
+ // F[fatal_err]: 1:1
prim_subreg_ext #(
.DW (1)
- ) u_alert_test_recov_mp_err (
+ ) u_alert_test_fatal_err (
.re (1'b0),
.we (alert_test_we),
- .wd (alert_test_recov_mp_err_wd),
+ .wd (alert_test_fatal_err_wd),
.d ('0),
.qre (),
- .qe (reg2hw.alert_test.recov_mp_err.qe),
- .q (reg2hw.alert_test.recov_mp_err.q),
- .qs ()
- );
-
- // F[recov_ecc_err]: 2:2
- prim_subreg_ext #(
- .DW (1)
- ) u_alert_test_recov_ecc_err (
- .re (1'b0),
- .we (alert_test_we),
- .wd (alert_test_recov_ecc_err_wd),
- .d ('0),
- .qre (),
- .qe (reg2hw.alert_test.recov_ecc_err.qe),
- .q (reg2hw.alert_test.recov_ecc_err.q),
- .qs ()
- );
-
- // F[fatal_intg_err]: 3:3
- prim_subreg_ext #(
- .DW (1)
- ) u_alert_test_fatal_intg_err (
- .re (1'b0),
- .we (alert_test_we),
- .wd (alert_test_fatal_intg_err_wd),
- .d ('0),
- .qre (),
- .qe (reg2hw.alert_test.fatal_intg_err.qe),
- .q (reg2hw.alert_test.fatal_intg_err.q),
+ .qe (reg2hw.alert_test.fatal_err.qe),
+ .q (reg2hw.alert_test.fatal_err.q),
.qs ()
);
@@ -9548,210 +9510,8 @@
);
- // R[err_code_intr_en]: V(False)
- // F[flash_err_en]: 0:0
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessRW),
- .RESVAL (1'h0)
- ) u_err_code_intr_en_flash_err_en (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_intr_en_we),
- .wd (err_code_intr_en_flash_err_en_wd),
-
- // from internal hardware
- .de (1'b0),
- .d ('0),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code_intr_en.flash_err_en.q),
-
- // to register interface (read)
- .qs (err_code_intr_en_flash_err_en_qs)
- );
-
- // F[flash_alert_en]: 1:1
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessRW),
- .RESVAL (1'h0)
- ) u_err_code_intr_en_flash_alert_en (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_intr_en_we),
- .wd (err_code_intr_en_flash_alert_en_wd),
-
- // from internal hardware
- .de (1'b0),
- .d ('0),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code_intr_en.flash_alert_en.q),
-
- // to register interface (read)
- .qs (err_code_intr_en_flash_alert_en_qs)
- );
-
- // F[oob_err]: 2:2
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessRW),
- .RESVAL (1'h0)
- ) u_err_code_intr_en_oob_err (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_intr_en_we),
- .wd (err_code_intr_en_oob_err_wd),
-
- // from internal hardware
- .de (1'b0),
- .d ('0),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code_intr_en.oob_err.q),
-
- // to register interface (read)
- .qs (err_code_intr_en_oob_err_qs)
- );
-
- // F[mp_err]: 3:3
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessRW),
- .RESVAL (1'h0)
- ) u_err_code_intr_en_mp_err (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_intr_en_we),
- .wd (err_code_intr_en_mp_err_wd),
-
- // from internal hardware
- .de (1'b0),
- .d ('0),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code_intr_en.mp_err.q),
-
- // to register interface (read)
- .qs (err_code_intr_en_mp_err_qs)
- );
-
- // F[ecc_single_err]: 4:4
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessRW),
- .RESVAL (1'h0)
- ) u_err_code_intr_en_ecc_single_err (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_intr_en_we),
- .wd (err_code_intr_en_ecc_single_err_wd),
-
- // from internal hardware
- .de (1'b0),
- .d ('0),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code_intr_en.ecc_single_err.q),
-
- // to register interface (read)
- .qs (err_code_intr_en_ecc_single_err_qs)
- );
-
- // F[ecc_multi_err]: 5:5
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessRW),
- .RESVAL (1'h0)
- ) u_err_code_intr_en_ecc_multi_err (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_intr_en_we),
- .wd (err_code_intr_en_ecc_multi_err_wd),
-
- // from internal hardware
- .de (1'b0),
- .d ('0),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code_intr_en.ecc_multi_err.q),
-
- // to register interface (read)
- .qs (err_code_intr_en_ecc_multi_err_qs)
- );
-
-
// R[err_code]: V(False)
- // F[flash_err]: 0:0
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessW1C),
- .RESVAL (1'h0)
- ) u_err_code_flash_err (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_we),
- .wd (err_code_flash_err_wd),
-
- // from internal hardware
- .de (hw2reg.err_code.flash_err.de),
- .d (hw2reg.err_code.flash_err.d),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code.flash_err.q),
-
- // to register interface (read)
- .qs (err_code_flash_err_qs)
- );
-
- // F[flash_alert]: 1:1
- prim_subreg #(
- .DW (1),
- .SwAccess(prim_subreg_pkg::SwAccessW1C),
- .RESVAL (1'h0)
- ) u_err_code_flash_alert (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (err_code_we),
- .wd (err_code_flash_alert_wd),
-
- // from internal hardware
- .de (hw2reg.err_code.flash_alert.de),
- .d (hw2reg.err_code.flash_alert.d),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.err_code.flash_alert.q),
-
- // to register interface (read)
- .qs (err_code_flash_alert_qs)
- );
-
- // F[oob_err]: 2:2
+ // F[oob_err]: 0:0
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
@@ -9770,13 +9530,13 @@
// to internal hardware
.qe (),
- .q (reg2hw.err_code.oob_err.q),
+ .q (),
// to register interface (read)
.qs (err_code_oob_err_qs)
);
- // F[mp_err]: 3:3
+ // F[mp_err]: 1:1
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
@@ -9795,68 +9555,320 @@
// to internal hardware
.qe (),
- .q (reg2hw.err_code.mp_err.q),
+ .q (),
// to register interface (read)
.qs (err_code_mp_err_qs)
);
- // F[ecc_single_err]: 4:4
+ // F[rd_err]: 2:2
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
.RESVAL (1'h0)
- ) u_err_code_ecc_single_err (
+ ) u_err_code_rd_err (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (err_code_we),
- .wd (err_code_ecc_single_err_wd),
+ .wd (err_code_rd_err_wd),
// from internal hardware
- .de (hw2reg.err_code.ecc_single_err.de),
- .d (hw2reg.err_code.ecc_single_err.d),
+ .de (hw2reg.err_code.rd_err.de),
+ .d (hw2reg.err_code.rd_err.d),
// to internal hardware
.qe (),
- .q (reg2hw.err_code.ecc_single_err.q),
+ .q (),
// to register interface (read)
- .qs (err_code_ecc_single_err_qs)
+ .qs (err_code_rd_err_qs)
);
- // F[ecc_multi_err]: 5:5
+ // F[prog_win_err]: 3:3
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessW1C),
.RESVAL (1'h0)
- ) u_err_code_ecc_multi_err (
+ ) u_err_code_prog_win_err (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (err_code_we),
- .wd (err_code_ecc_multi_err_wd),
+ .wd (err_code_prog_win_err_wd),
// from internal hardware
- .de (hw2reg.err_code.ecc_multi_err.de),
- .d (hw2reg.err_code.ecc_multi_err.d),
+ .de (hw2reg.err_code.prog_win_err.de),
+ .d (hw2reg.err_code.prog_win_err.d),
// to internal hardware
.qe (),
- .q (reg2hw.err_code.ecc_multi_err.q),
+ .q (),
// to register interface (read)
- .qs (err_code_ecc_multi_err_qs)
+ .qs (err_code_prog_win_err_qs)
+ );
+
+ // F[prog_type_err]: 4:4
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessW1C),
+ .RESVAL (1'h0)
+ ) u_err_code_prog_type_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (err_code_we),
+ .wd (err_code_prog_type_err_wd),
+
+ // from internal hardware
+ .de (hw2reg.err_code.prog_type_err.de),
+ .d (hw2reg.err_code.prog_type_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (),
+
+ // to register interface (read)
+ .qs (err_code_prog_type_err_qs)
+ );
+
+ // F[flash_phy_err]: 5:5
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessW1C),
+ .RESVAL (1'h0)
+ ) u_err_code_flash_phy_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (err_code_we),
+ .wd (err_code_flash_phy_err_wd),
+
+ // from internal hardware
+ .de (hw2reg.err_code.flash_phy_err.de),
+ .d (hw2reg.err_code.flash_phy_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (),
+
+ // to register interface (read)
+ .qs (err_code_flash_phy_err_qs)
+ );
+
+
+ // R[fault_status]: V(False)
+ // F[oob_err]: 0:0
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_oob_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.oob_err.de),
+ .d (hw2reg.fault_status.oob_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.oob_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_oob_err_qs)
+ );
+
+ // F[mp_err]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_mp_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.mp_err.de),
+ .d (hw2reg.fault_status.mp_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.mp_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_mp_err_qs)
+ );
+
+ // F[rd_err]: 2:2
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_rd_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.rd_err.de),
+ .d (hw2reg.fault_status.rd_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.rd_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_rd_err_qs)
+ );
+
+ // F[prog_win_err]: 3:3
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_prog_win_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.prog_win_err.de),
+ .d (hw2reg.fault_status.prog_win_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.prog_win_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_prog_win_err_qs)
+ );
+
+ // F[prog_type_err]: 4:4
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_prog_type_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.prog_type_err.de),
+ .d (hw2reg.fault_status.prog_type_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.prog_type_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_prog_type_err_qs)
+ );
+
+ // F[flash_phy_err]: 5:5
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_flash_phy_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.flash_phy_err.de),
+ .d (hw2reg.fault_status.flash_phy_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.flash_phy_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_flash_phy_err_qs)
+ );
+
+ // F[reg_intg_err]: 6:6
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_reg_intg_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.reg_intg_err.de),
+ .d (hw2reg.fault_status.reg_intg_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.reg_intg_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_reg_intg_err_qs)
+ );
+
+ // F[phy_intg_err]: 7:7
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_phy_intg_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.phy_intg_err.de),
+ .d (hw2reg.fault_status.phy_intg_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.phy_intg_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_phy_intg_err_qs)
);
// R[err_addr]: V(False)
prim_subreg #(
- .DW (9),
+ .DW (32),
.SwAccess(prim_subreg_pkg::SwAccessRO),
- .RESVAL (9'h0)
+ .RESVAL (32'h0)
) u_err_addr (
.clk_i (clk_i),
.rst_ni (rst_ni),
@@ -9878,29 +9890,56 @@
);
+ // Subregister 0 of Multireg ecc_single_err_cnt
// R[ecc_single_err_cnt]: V(False)
+ // F[ecc_single_err_cnt_0]: 7:0
prim_subreg #(
.DW (8),
- .SwAccess(prim_subreg_pkg::SwAccessW1C),
+ .SwAccess(prim_subreg_pkg::SwAccessRW),
.RESVAL (8'h0)
- ) u_ecc_single_err_cnt (
+ ) u_ecc_single_err_cnt_ecc_single_err_cnt_0 (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ecc_single_err_cnt_we),
- .wd (ecc_single_err_cnt_wd),
+ .wd (ecc_single_err_cnt_ecc_single_err_cnt_0_wd),
// from internal hardware
- .de (hw2reg.ecc_single_err_cnt.de),
- .d (hw2reg.ecc_single_err_cnt.d),
+ .de (hw2reg.ecc_single_err_cnt[0].de),
+ .d (hw2reg.ecc_single_err_cnt[0].d),
// to internal hardware
.qe (),
- .q (reg2hw.ecc_single_err_cnt.q),
+ .q (reg2hw.ecc_single_err_cnt[0].q),
// to register interface (read)
- .qs (ecc_single_err_cnt_qs)
+ .qs (ecc_single_err_cnt_ecc_single_err_cnt_0_qs)
+ );
+
+ // F[ecc_single_err_cnt_1]: 15:8
+ prim_subreg #(
+ .DW (8),
+ .SwAccess(prim_subreg_pkg::SwAccessRW),
+ .RESVAL (8'h0)
+ ) u_ecc_single_err_cnt_ecc_single_err_cnt_1 (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (ecc_single_err_cnt_we),
+ .wd (ecc_single_err_cnt_ecc_single_err_cnt_1_wd),
+
+ // from internal hardware
+ .de (hw2reg.ecc_single_err_cnt[1].de),
+ .d (hw2reg.ecc_single_err_cnt[1].d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.ecc_single_err_cnt[1].q),
+
+ // to register interface (read)
+ .qs (ecc_single_err_cnt_ecc_single_err_cnt_1_qs)
);
@@ -9958,86 +9997,6 @@
);
- // R[ecc_multi_err_cnt]: V(False)
- prim_subreg #(
- .DW (8),
- .SwAccess(prim_subreg_pkg::SwAccessW1C),
- .RESVAL (8'h0)
- ) u_ecc_multi_err_cnt (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (ecc_multi_err_cnt_we),
- .wd (ecc_multi_err_cnt_wd),
-
- // from internal hardware
- .de (hw2reg.ecc_multi_err_cnt.de),
- .d (hw2reg.ecc_multi_err_cnt.d),
-
- // to internal hardware
- .qe (),
- .q (reg2hw.ecc_multi_err_cnt.q),
-
- // to register interface (read)
- .qs (ecc_multi_err_cnt_qs)
- );
-
-
- // Subregister 0 of Multireg ecc_multi_err_addr
- // R[ecc_multi_err_addr_0]: V(False)
- prim_subreg #(
- .DW (20),
- .SwAccess(prim_subreg_pkg::SwAccessRO),
- .RESVAL (20'h0)
- ) u_ecc_multi_err_addr_0 (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (1'b0),
- .wd ('0),
-
- // from internal hardware
- .de (hw2reg.ecc_multi_err_addr[0].de),
- .d (hw2reg.ecc_multi_err_addr[0].d),
-
- // to internal hardware
- .qe (),
- .q (),
-
- // to register interface (read)
- .qs (ecc_multi_err_addr_0_qs)
- );
-
-
- // Subregister 1 of Multireg ecc_multi_err_addr
- // R[ecc_multi_err_addr_1]: V(False)
- prim_subreg #(
- .DW (20),
- .SwAccess(prim_subreg_pkg::SwAccessRO),
- .RESVAL (20'h0)
- ) u_ecc_multi_err_addr_1 (
- .clk_i (clk_i),
- .rst_ni (rst_ni),
-
- // from register interface
- .we (1'b0),
- .wd ('0),
-
- // from internal hardware
- .de (hw2reg.ecc_multi_err_addr[1].de),
- .d (hw2reg.ecc_multi_err_addr[1].d),
-
- // to internal hardware
- .qe (),
- .q (),
-
- // to register interface (read)
- .qs (ecc_multi_err_addr_1_qs)
- );
-
-
// R[phy_err_cfg_regwen]: V(False)
prim_subreg #(
.DW (1),
@@ -10324,7 +10283,7 @@
- logic [99:0] addr_hit;
+ logic [96:0] addr_hit;
always_comb begin
addr_hit = '0;
addr_hit[ 0] = (reg_addr == FLASH_CTRL_INTR_STATE_OFFSET);
@@ -10411,22 +10370,19 @@
addr_hit[81] = (reg_addr == FLASH_CTRL_MP_BANK_CFG_OFFSET);
addr_hit[82] = (reg_addr == FLASH_CTRL_OP_STATUS_OFFSET);
addr_hit[83] = (reg_addr == FLASH_CTRL_STATUS_OFFSET);
- addr_hit[84] = (reg_addr == FLASH_CTRL_ERR_CODE_INTR_EN_OFFSET);
- addr_hit[85] = (reg_addr == FLASH_CTRL_ERR_CODE_OFFSET);
+ addr_hit[84] = (reg_addr == FLASH_CTRL_ERR_CODE_OFFSET);
+ addr_hit[85] = (reg_addr == FLASH_CTRL_FAULT_STATUS_OFFSET);
addr_hit[86] = (reg_addr == FLASH_CTRL_ERR_ADDR_OFFSET);
addr_hit[87] = (reg_addr == FLASH_CTRL_ECC_SINGLE_ERR_CNT_OFFSET);
addr_hit[88] = (reg_addr == FLASH_CTRL_ECC_SINGLE_ERR_ADDR_0_OFFSET);
addr_hit[89] = (reg_addr == FLASH_CTRL_ECC_SINGLE_ERR_ADDR_1_OFFSET);
- addr_hit[90] = (reg_addr == FLASH_CTRL_ECC_MULTI_ERR_CNT_OFFSET);
- addr_hit[91] = (reg_addr == FLASH_CTRL_ECC_MULTI_ERR_ADDR_0_OFFSET);
- addr_hit[92] = (reg_addr == FLASH_CTRL_ECC_MULTI_ERR_ADDR_1_OFFSET);
- addr_hit[93] = (reg_addr == FLASH_CTRL_PHY_ERR_CFG_REGWEN_OFFSET);
- addr_hit[94] = (reg_addr == FLASH_CTRL_PHY_ERR_CFG_OFFSET);
- addr_hit[95] = (reg_addr == FLASH_CTRL_PHY_ALERT_CFG_OFFSET);
- addr_hit[96] = (reg_addr == FLASH_CTRL_PHY_STATUS_OFFSET);
- addr_hit[97] = (reg_addr == FLASH_CTRL_SCRATCH_OFFSET);
- addr_hit[98] = (reg_addr == FLASH_CTRL_FIFO_LVL_OFFSET);
- addr_hit[99] = (reg_addr == FLASH_CTRL_FIFO_RST_OFFSET);
+ addr_hit[90] = (reg_addr == FLASH_CTRL_PHY_ERR_CFG_REGWEN_OFFSET);
+ addr_hit[91] = (reg_addr == FLASH_CTRL_PHY_ERR_CFG_OFFSET);
+ addr_hit[92] = (reg_addr == FLASH_CTRL_PHY_ALERT_CFG_OFFSET);
+ addr_hit[93] = (reg_addr == FLASH_CTRL_PHY_STATUS_OFFSET);
+ addr_hit[94] = (reg_addr == FLASH_CTRL_SCRATCH_OFFSET);
+ addr_hit[95] = (reg_addr == FLASH_CTRL_FIFO_LVL_OFFSET);
+ addr_hit[96] = (reg_addr == FLASH_CTRL_FIFO_RST_OFFSET);
end
assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -10530,10 +10486,7 @@
(addr_hit[93] & (|(FLASH_CTRL_CORE_PERMIT[93] & ~reg_be))) |
(addr_hit[94] & (|(FLASH_CTRL_CORE_PERMIT[94] & ~reg_be))) |
(addr_hit[95] & (|(FLASH_CTRL_CORE_PERMIT[95] & ~reg_be))) |
- (addr_hit[96] & (|(FLASH_CTRL_CORE_PERMIT[96] & ~reg_be))) |
- (addr_hit[97] & (|(FLASH_CTRL_CORE_PERMIT[97] & ~reg_be))) |
- (addr_hit[98] & (|(FLASH_CTRL_CORE_PERMIT[98] & ~reg_be))) |
- (addr_hit[99] & (|(FLASH_CTRL_CORE_PERMIT[99] & ~reg_be)))));
+ (addr_hit[96] & (|(FLASH_CTRL_CORE_PERMIT[96] & ~reg_be)))));
end
assign intr_state_we = addr_hit[0] & reg_we & !reg_error;
@@ -10547,7 +10500,7 @@
assign intr_state_op_done_wd = reg_wdata[4];
- assign intr_state_err_wd = reg_wdata[5];
+ assign intr_state_corr_err_wd = reg_wdata[5];
assign intr_enable_we = addr_hit[1] & reg_we & !reg_error;
assign intr_enable_prog_empty_wd = reg_wdata[0];
@@ -10560,7 +10513,7 @@
assign intr_enable_op_done_wd = reg_wdata[4];
- assign intr_enable_err_wd = reg_wdata[5];
+ assign intr_enable_corr_err_wd = reg_wdata[5];
assign intr_test_we = addr_hit[2] & reg_we & !reg_error;
assign intr_test_prog_empty_wd = reg_wdata[0];
@@ -10573,16 +10526,12 @@
assign intr_test_op_done_wd = reg_wdata[4];
- assign intr_test_err_wd = reg_wdata[5];
+ assign intr_test_corr_err_wd = reg_wdata[5];
assign alert_test_we = addr_hit[3] & reg_we & !reg_error;
assign alert_test_recov_err_wd = reg_wdata[0];
- assign alert_test_recov_mp_err_wd = reg_wdata[1];
-
- assign alert_test_recov_ecc_err_wd = reg_wdata[2];
-
- assign alert_test_fatal_intg_err_wd = reg_wdata[3];
+ assign alert_test_fatal_err_wd = reg_wdata[1];
assign flash_disable_we = addr_hit[4] & reg_we & !reg_error;
assign flash_disable_wd = reg_wdata[0];
@@ -11286,58 +11235,44 @@
assign op_status_done_wd = reg_wdata[0];
assign op_status_err_wd = reg_wdata[1];
- assign err_code_intr_en_we = addr_hit[84] & reg_we & !reg_error;
+ assign err_code_we = addr_hit[84] & reg_we & !reg_error;
- assign err_code_intr_en_flash_err_en_wd = reg_wdata[0];
+ assign err_code_oob_err_wd = reg_wdata[0];
- assign err_code_intr_en_flash_alert_en_wd = reg_wdata[1];
+ assign err_code_mp_err_wd = reg_wdata[1];
- assign err_code_intr_en_oob_err_wd = reg_wdata[2];
+ assign err_code_rd_err_wd = reg_wdata[2];
- assign err_code_intr_en_mp_err_wd = reg_wdata[3];
+ assign err_code_prog_win_err_wd = reg_wdata[3];
- assign err_code_intr_en_ecc_single_err_wd = reg_wdata[4];
+ assign err_code_prog_type_err_wd = reg_wdata[4];
- assign err_code_intr_en_ecc_multi_err_wd = reg_wdata[5];
- assign err_code_we = addr_hit[85] & reg_we & !reg_error;
-
- assign err_code_flash_err_wd = reg_wdata[0];
-
- assign err_code_flash_alert_wd = reg_wdata[1];
-
- assign err_code_oob_err_wd = reg_wdata[2];
-
- assign err_code_mp_err_wd = reg_wdata[3];
-
- assign err_code_ecc_single_err_wd = reg_wdata[4];
-
- assign err_code_ecc_multi_err_wd = reg_wdata[5];
+ assign err_code_flash_phy_err_wd = reg_wdata[5];
assign ecc_single_err_cnt_we = addr_hit[87] & reg_we & !reg_error;
- assign ecc_single_err_cnt_wd = reg_wdata[7:0];
- assign ecc_multi_err_cnt_we = addr_hit[90] & reg_we & !reg_error;
+ assign ecc_single_err_cnt_ecc_single_err_cnt_0_wd = reg_wdata[7:0];
- assign ecc_multi_err_cnt_wd = reg_wdata[7:0];
- assign phy_err_cfg_regwen_we = addr_hit[93] & reg_we & !reg_error;
+ assign ecc_single_err_cnt_ecc_single_err_cnt_1_wd = reg_wdata[15:8];
+ assign phy_err_cfg_regwen_we = addr_hit[90] & reg_we & !reg_error;
assign phy_err_cfg_regwen_wd = reg_wdata[0];
- assign phy_err_cfg_we = addr_hit[94] & reg_we & !reg_error;
+ assign phy_err_cfg_we = addr_hit[91] & reg_we & !reg_error;
assign phy_err_cfg_wd = reg_wdata[0];
- assign phy_alert_cfg_we = addr_hit[95] & reg_we & !reg_error;
+ assign phy_alert_cfg_we = addr_hit[92] & reg_we & !reg_error;
assign phy_alert_cfg_alert_ack_wd = reg_wdata[0];
assign phy_alert_cfg_alert_trig_wd = reg_wdata[1];
- assign scratch_we = addr_hit[97] & reg_we & !reg_error;
+ assign scratch_we = addr_hit[94] & reg_we & !reg_error;
assign scratch_wd = reg_wdata[31:0];
- assign fifo_lvl_we = addr_hit[98] & reg_we & !reg_error;
+ assign fifo_lvl_we = addr_hit[95] & reg_we & !reg_error;
assign fifo_lvl_prog_wd = reg_wdata[4:0];
assign fifo_lvl_rd_wd = reg_wdata[12:8];
- assign fifo_rst_we = addr_hit[99] & reg_we & !reg_error;
+ assign fifo_rst_we = addr_hit[96] & reg_we & !reg_error;
assign fifo_rst_wd = reg_wdata[0];
@@ -11351,7 +11286,7 @@
reg_rdata_next[2] = intr_state_rd_full_qs;
reg_rdata_next[3] = intr_state_rd_lvl_qs;
reg_rdata_next[4] = intr_state_op_done_qs;
- reg_rdata_next[5] = intr_state_err_qs;
+ reg_rdata_next[5] = intr_state_corr_err_qs;
end
addr_hit[1]: begin
@@ -11360,7 +11295,7 @@
reg_rdata_next[2] = intr_enable_rd_full_qs;
reg_rdata_next[3] = intr_enable_rd_lvl_qs;
reg_rdata_next[4] = intr_enable_op_done_qs;
- reg_rdata_next[5] = intr_enable_err_qs;
+ reg_rdata_next[5] = intr_enable_corr_err_qs;
end
addr_hit[2]: begin
@@ -11375,8 +11310,6 @@
addr_hit[3]: begin
reg_rdata_next[0] = '0;
reg_rdata_next[1] = '0;
- reg_rdata_next[2] = '0;
- reg_rdata_next[3] = '0;
end
addr_hit[4]: begin
@@ -11938,29 +11871,32 @@
end
addr_hit[84]: begin
- reg_rdata_next[0] = err_code_intr_en_flash_err_en_qs;
- reg_rdata_next[1] = err_code_intr_en_flash_alert_en_qs;
- reg_rdata_next[2] = err_code_intr_en_oob_err_qs;
- reg_rdata_next[3] = err_code_intr_en_mp_err_qs;
- reg_rdata_next[4] = err_code_intr_en_ecc_single_err_qs;
- reg_rdata_next[5] = err_code_intr_en_ecc_multi_err_qs;
+ reg_rdata_next[0] = err_code_oob_err_qs;
+ reg_rdata_next[1] = err_code_mp_err_qs;
+ reg_rdata_next[2] = err_code_rd_err_qs;
+ reg_rdata_next[3] = err_code_prog_win_err_qs;
+ reg_rdata_next[4] = err_code_prog_type_err_qs;
+ reg_rdata_next[5] = err_code_flash_phy_err_qs;
end
addr_hit[85]: begin
- reg_rdata_next[0] = err_code_flash_err_qs;
- reg_rdata_next[1] = err_code_flash_alert_qs;
- reg_rdata_next[2] = err_code_oob_err_qs;
- reg_rdata_next[3] = err_code_mp_err_qs;
- reg_rdata_next[4] = err_code_ecc_single_err_qs;
- reg_rdata_next[5] = err_code_ecc_multi_err_qs;
+ reg_rdata_next[0] = fault_status_oob_err_qs;
+ reg_rdata_next[1] = fault_status_mp_err_qs;
+ reg_rdata_next[2] = fault_status_rd_err_qs;
+ reg_rdata_next[3] = fault_status_prog_win_err_qs;
+ reg_rdata_next[4] = fault_status_prog_type_err_qs;
+ reg_rdata_next[5] = fault_status_flash_phy_err_qs;
+ reg_rdata_next[6] = fault_status_reg_intg_err_qs;
+ reg_rdata_next[7] = fault_status_phy_intg_err_qs;
end
addr_hit[86]: begin
- reg_rdata_next[8:0] = err_addr_qs;
+ reg_rdata_next[31:0] = err_addr_qs;
end
addr_hit[87]: begin
- reg_rdata_next[7:0] = ecc_single_err_cnt_qs;
+ reg_rdata_next[7:0] = ecc_single_err_cnt_ecc_single_err_cnt_0_qs;
+ reg_rdata_next[15:8] = ecc_single_err_cnt_ecc_single_err_cnt_1_qs;
end
addr_hit[88]: begin
@@ -11972,46 +11908,34 @@
end
addr_hit[90]: begin
- reg_rdata_next[7:0] = ecc_multi_err_cnt_qs;
- end
-
- addr_hit[91]: begin
- reg_rdata_next[19:0] = ecc_multi_err_addr_0_qs;
- end
-
- addr_hit[92]: begin
- reg_rdata_next[19:0] = ecc_multi_err_addr_1_qs;
- end
-
- addr_hit[93]: begin
reg_rdata_next[0] = phy_err_cfg_regwen_qs;
end
- addr_hit[94]: begin
+ addr_hit[91]: begin
reg_rdata_next[0] = phy_err_cfg_qs;
end
- addr_hit[95]: begin
+ addr_hit[92]: begin
reg_rdata_next[0] = phy_alert_cfg_alert_ack_qs;
reg_rdata_next[1] = phy_alert_cfg_alert_trig_qs;
end
- addr_hit[96]: begin
+ addr_hit[93]: begin
reg_rdata_next[0] = phy_status_init_wip_qs;
reg_rdata_next[1] = phy_status_prog_normal_avail_qs;
reg_rdata_next[2] = phy_status_prog_repair_avail_qs;
end
- addr_hit[97]: begin
+ addr_hit[94]: begin
reg_rdata_next[31:0] = scratch_qs;
end
- addr_hit[98]: begin
+ addr_hit[95]: begin
reg_rdata_next[4:0] = fifo_lvl_prog_qs;
reg_rdata_next[12:8] = fifo_lvl_rd_qs;
end
- addr_hit[99]: begin
+ addr_hit[96]: begin
reg_rdata_next[0] = fifo_rst_qs;
end
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_erase.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_erase.sv
index b20e22b..9243916 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_erase.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_erase.sv
@@ -12,14 +12,16 @@
input [BusAddrW-1:0] op_addr_i,
input op_addr_oob_i,
output logic op_done_o,
- output logic op_err_o,
+ output flash_ctrl_err_t op_err_o,
+ output logic [BusAddrW-1:0] op_err_addr_o,
// Flash Macro Interface
output logic flash_req_o,
output logic [BusAddrW-1:0] flash_addr_o,
output flash_erase_e flash_op_o,
input flash_done_i,
- input flash_error_i
+ input flash_mp_err_i,
+ input flash_phy_err_i
);
import flash_ctrl_pkg::*;
@@ -42,8 +44,15 @@
assign oob_err = op_start_i & op_addr_oob_i;
// IO assignments
- assign op_done_o = flash_req_o & flash_done_i | oob_err;
- assign op_err_o = flash_req_o & flash_error_i | oob_err;
+ assign op_done_o = flash_req_o & (flash_done_i | oob_err);
+
+ always_comb begin
+ op_err_o = '0;
+ op_err_o.oob_err = op_done_o & oob_err;
+ op_err_o.mp_err = op_done_o & flash_mp_err_i;
+ op_err_o.phy_err = op_done_o & flash_phy_err_i;
+ end
+
// Flash Interface assignments
assign flash_req_o = op_start_i & ~op_addr_oob_i;
@@ -52,6 +61,8 @@
op_addr_i & PageAddrMask :
op_addr_i & BankAddrMask;
+ assign op_err_addr_o = flash_addr_o;
+
// unused bus
logic [WordsBitWidth-1:0] unused_addr_i;
assign unused_addr_i = op_addr_i[WordsBitWidth-1:0];
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
index fd5931b..53b8e1f 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
@@ -25,7 +25,7 @@
output logic req_o,
output logic [top_pkg::TL_AW-1:0] addr_o,
input done_i,
- input err_i,
+ input flash_ctrl_err_t err_i,
// interface to ctrl_arb data ports
output logic rready_o,
@@ -590,7 +590,7 @@
rma_start = 1'b1;
rma_op = FlashOpErase;
if (done_i) begin
- err_sts_set = err_i;
+ err_sts_set = |err_i;
rma_state_d = StRmaWordSel;
end
end
@@ -621,7 +621,7 @@
if (done_i) begin
beat_cnt_clr = 1'b1;
- err_sts_set = err_i;
+ err_sts_set = |err_i;
rma_state_d = StRmaRdVerify;
end
end
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
index 46b6a37..2cd5948 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
@@ -364,10 +364,7 @@
logic [BusWidth-1:0] rd_data;
logic init_busy;
logic flash_err;
- logic flash_alert_p;
- logic flash_alert_n;
logic [NumBanks-1:0] ecc_single_err;
- logic [NumBanks-1:0] ecc_multi_err;
logic [NumBanks-1:0][BusAddrW-1:0] ecc_addr;
jtag_pkg::jtag_rsp_t jtag_rsp;
logic intg_err;
@@ -383,10 +380,7 @@
rd_data: '0,
init_busy: 1'b0,
flash_err: 1'b0,
- flash_alert_p: 1'b0,
- flash_alert_n: 1'b1,
ecc_single_err: '0,
- ecc_multi_err: '0,
ecc_addr: '0,
jtag_rsp: '0,
intg_err: '0
@@ -468,6 +462,27 @@
FlashLcDftLast
} flash_lc_jtag_e;
+ // Error bit positioning
+ typedef struct packed {
+ logic oob_err;
+ logic mp_err;
+ logic rd_err;
+ logic prog_win_err;
+ logic prog_type_err;
+ logic phy_err;
+ } flash_ctrl_err_t;
+
+ // interrupt bit positioning
+ typedef enum logic[2:0] {
+ ProgEmpty,
+ ProgLvl,
+ RdFull,
+ RdLvl,
+ OpDone,
+ CorrErr,
+ LastIntrIdx
+ } flash_ctrl_intr_e;
+
// find the max number pages among info types
function automatic integer max_info_pages(int infos[InfoTypes]);
int current_max = 0;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv
index 6c5f714..9b925e9 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv
@@ -13,11 +13,12 @@
input op_start_i,
input [11:0] op_num_words_i,
output logic op_done_o,
- output logic op_err_o,
+ output flash_ctrl_err_t op_err_o,
input [BusAddrW-1:0] op_addr_i,
input op_addr_oob_i,
input flash_prog_e op_type_i,
input [ProgTypes-1:0] type_avail_i,
+ output logic [BusAddrW-1:0] op_err_addr_o,
// FIFO Interface
input data_rdy_i,
@@ -32,7 +33,8 @@
output logic flash_last_o, // last beat of prog data
output flash_prog_e flash_type_o,
input flash_done_i,
- input flash_error_i
+ input flash_phy_err_i,
+ input flash_mp_err_i
);
typedef enum logic {
@@ -40,26 +42,53 @@
StErr = 'h1
} state_e;
- state_e st, st_nxt;
- logic [11:0] cnt, cnt_nxt;
+ state_e st_q, st_d;
+ logic [11:0] cnt;
logic cnt_hit;
logic [BusAddrW:0] int_addr;
logic txn_done;
+ flash_ctrl_err_t op_err_q, op_err_d;
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ st_q <= StNorm;
+ end else begin
+ st_q <= st_d;
+ end
+ end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
cnt <= '0;
- st <= StNorm;
- end else begin
- cnt <= cnt_nxt;
- st <= st_nxt;
+ end else if (op_start_i && op_done_o) begin
+ cnt <= '0;
+ end else if (data_rd_o) begin
+ cnt <= cnt + 1'b1;
+ end
+ end
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ op_err_addr_o <= '0;
+ end else if (~|op_err_q && |op_err_d) begin
+ op_err_addr_o <= flash_addr_o;
end
end
assign txn_done = flash_req_o && flash_done_i;
assign cnt_hit = (cnt == op_num_words_i);
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ op_err_q <= '0;
+ end else if (op_start_i && op_done_o) begin
+ op_err_q <= '0;
+ end else begin
+ op_err_q <= op_err_d;
+ end
+ end
+
// if the requested prog type is available
logic prog_type_avail;
assign prog_type_avail = type_avail_i[op_type_i];
@@ -70,53 +99,58 @@
localparam int WindowWidth = BusAddrW - BusPgmResWidth;
logic [WindowWidth-1:0] start_window, end_window;
logic [BusAddrW-1:0] end_addr;
+ logic pgm_res_err;
logic win_err;
assign end_addr = op_addr_i + BusAddrW'(op_num_words_i);
assign start_window = op_addr_i[BusAddrW-1:BusPgmResWidth];
assign end_window = end_addr[BusAddrW-1:BusPgmResWidth];
- assign win_err = (start_window != end_window) | op_addr_oob_i;
+ assign pgm_res_err = start_window != end_window;
+ assign win_err = pgm_res_err | op_addr_oob_i;
// when error'd, continue to drain all program fifo contents like normal operation
// if this is not done, software may fill up the fifo without anyone
// draining the contents, leading to a lockup
always_comb begin
- st_nxt = st;
- cnt_nxt = cnt;
+ st_d = st_q;
flash_req_o = 1'b0;
data_rd_o = 1'b0;
op_done_o = 1'b0;
- op_err_o = 1'b0;
+ op_err_d = op_err_q;
- unique case (st)
+ unique case (st_q)
+
+ // Note the address counter is incremented on tx_done
+ // and cleared when the entire operation is complete.
StNorm: begin
// if the select operation type is not available, error
if (op_start_i && prog_type_avail && !win_err) begin
flash_req_o = data_rdy_i;
- if(txn_done && cnt_hit) begin
- cnt_nxt = '0;
+ if (txn_done) begin
+ op_err_d.mp_err = flash_mp_err_i;
+ op_err_d.phy_err = flash_phy_err_i;
data_rd_o = 1'b1;
- op_done_o = 1'b1;
- op_err_o = flash_error_i;
- end else if(txn_done) begin
- cnt_nxt = cnt + 1'b1;
- data_rd_o = 1'b1;
- st_nxt = flash_error_i ? StErr : StNorm;
+
+ if (cnt_hit) begin
+ op_done_o = 1'b1;
+ end else begin
+ st_d = |op_err_d ? StErr : StNorm;
+ end
end
+
end else if (op_start_i && (!prog_type_avail || win_err)) begin
- st_nxt = StErr;
+ op_err_d.oob_err = op_addr_oob_i;
+ op_err_d.prog_type_err = !prog_type_avail;
+ op_err_d.prog_win_err = pgm_res_err;
+ st_d = StErr;
end
end
StErr: begin
data_rd_o = data_rdy_i;
if (data_rdy_i && cnt_hit) begin
- st_nxt = StNorm;
- cnt_nxt = '0;
+ st_d = StNorm;
op_done_o = 1'b1;
- op_err_o = 1'b1;
- end else if (data_rdy_i) begin
- cnt_nxt = cnt + 1'b1;
end
end
default:;
@@ -129,6 +163,7 @@
assign flash_ovfl_o = int_addr[BusAddrW];
assign flash_last_o = flash_req_o & cnt_hit;
assign flash_type_o = op_type_i;
+ assign op_err_o = op_err_q | op_err_d;
// unused signals
logic [BusPgmResWidth-1:0] unused_end_addr;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_rd.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_rd.sv
index 80d7f99..4973761 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_rd.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_rd.sv
@@ -13,9 +13,10 @@
input op_start_i,
input [11:0] op_num_words_i,
output logic op_done_o,
- output logic op_err_o,
+ flash_ctrl_err_t op_err_o,
input [BusAddrW-1:0] op_addr_i,
input op_addr_oob_i,
+ output logic [BusAddrW-1:0] op_err_addr_o,
// FIFO Interface
input data_rdy_i,
@@ -28,7 +29,9 @@
output logic flash_ovfl_o,
input [BusWidth-1:0] flash_data_i,
input flash_done_i,
- input flash_error_i
+ input flash_phy_err_i,
+ input flash_rd_err_i,
+ input flash_mp_err_i
);
typedef enum logic [1:0] {
@@ -37,75 +40,100 @@
StErr
} state_e;
- state_e st, st_nxt;
- logic [11:0] cnt, cnt_nxt;
+ state_e st_q, st_d;
+ logic [11:0] cnt;
logic cnt_hit;
logic [BusAddrW:0] int_addr;
logic txn_done;
logic err_sel; //1 selects error data, 0 selects normal data
+ flash_ctrl_err_t op_err_q, op_err_d;
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ st_q <= StIdle;
+ end else begin
+ st_q <= st_d;
+ end
+ end
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ op_err_q <= '0;
+ end else if (op_start_i && op_done_o) begin
+ op_err_q <= '0;
+ end else begin
+ op_err_q <= op_err_d;
+ end
+ end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
cnt <= '0;
- st <= StIdle;
- end else begin
- cnt <= cnt_nxt;
- st <= st_nxt;
+ end else if (op_start_i && op_done_o) begin
+ cnt <= '0;
+ end else if (data_wr_o) begin
+ cnt <= cnt + 1'b1;
+ end
+ end
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ op_err_addr_o <= '0;
+ end else if (~|op_err_q && |op_err_d) begin
+ op_err_addr_o <= flash_addr_o;
end
end
assign txn_done = flash_req_o & flash_done_i;
assign cnt_hit = (cnt == op_num_words_i);
+
// when error'd, continue to complete existing read transaction but fill in with all 1's
// if this is not done, software may continue to attempt to read out of the fifo
// and eventually cause a bus deadlock as the fifo would be empty
// This scheme is similar to burst completion up an error
always_comb begin
- st_nxt = st;
- cnt_nxt = cnt;
+ st_d = st_q;
flash_req_o = 1'b0;
data_wr_o = 1'b0;
op_done_o = 1'b0;
- op_err_o = 1'b0;
- err_sel = 1'b0;
+ op_err_d = op_err_q;
- unique case (st)
+ unique case (st_q)
StIdle: begin
- if (op_start_i && op_addr_oob_i) begin
- st_nxt = StErr;
- end else if (op_start_i) begin
- st_nxt = StNorm;
+ if (op_start_i) begin
+ op_err_d.oob_err = op_addr_oob_i;
+ st_d = |op_err_d ? StErr : StNorm;
end
end
+ // Note the address counter is incremented on tx_done
+ // and cleared when the entire operation is complete.
StNorm: begin
flash_req_o = op_start_i & data_rdy_i;
- if (txn_done && cnt_hit) begin
- cnt_nxt = '0;
+ if (txn_done) begin
+ op_err_d.mp_err = flash_mp_err_i;
+ op_err_d.rd_err = flash_rd_err_i;
+ op_err_d.phy_err = flash_phy_err_i;
+
data_wr_o = 1'b1;
- op_done_o = 1'b1;
- op_err_o = flash_error_i;
- end else if (txn_done) begin
- cnt_nxt = cnt + 1'b1;
- data_wr_o = 1'b1;
- err_sel = flash_error_i;
- st_nxt = flash_error_i ? StErr : StIdle;
+
+ if (cnt_hit) begin
+ op_done_o = 1'b1;
+ st_d = StIdle;
+ end else begin
+ st_d = |op_err_d ? StErr : StNorm;
+ end
end
end
StErr: begin
data_wr_o = data_rdy_i;
- err_sel = 1'b1;
if (data_rdy_i && cnt_hit) begin
- st_nxt = StIdle;
- cnt_nxt = '0;
+ st_d = StIdle;
op_done_o = 1'b1;
- op_err_o = 1'b1;
- end else if (data_rdy_i) begin
- cnt_nxt = cnt + 1'b1;
end
end
default:;
@@ -117,7 +145,9 @@
assign flash_addr_o = int_addr[0 +: BusAddrW];
assign flash_ovfl_o = int_addr[BusAddrW];
// if error, return "empty" data
+ assign err_sel = data_wr_o & |op_err_o;
assign data_o = err_sel ? {BusWidth{1'b1}} : flash_data_i;
+ assign op_err_o = op_err_q | op_err_d;
endmodule // flash_ctrl_rd
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
index 7955b1f..2d8ce15 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
@@ -20,7 +20,7 @@
parameter int BytesPerWord = 8;
parameter int BytesPerPage = 2048;
parameter int BytesPerBank = 524288;
- parameter int NumAlerts = 4;
+ parameter int NumAlerts = 2;
// Address widths within the block
parameter int CoreAw = 9;
@@ -49,7 +49,7 @@
} op_done;
struct packed {
logic q;
- } err;
+ } corr_err;
} flash_ctrl_reg2hw_intr_state_reg_t;
typedef struct packed {
@@ -70,7 +70,7 @@
} op_done;
struct packed {
logic q;
- } err;
+ } corr_err;
} flash_ctrl_reg2hw_intr_enable_reg_t;
typedef struct packed {
@@ -97,7 +97,7 @@
struct packed {
logic q;
logic qe;
- } err;
+ } corr_err;
} flash_ctrl_reg2hw_intr_test_reg_t;
typedef struct packed {
@@ -108,15 +108,7 @@
struct packed {
logic q;
logic qe;
- } recov_mp_err;
- struct packed {
- logic q;
- logic qe;
- } recov_ecc_err;
- struct packed {
- logic q;
- logic qe;
- } fatal_intg_err;
+ } fatal_err;
} flash_ctrl_reg2hw_alert_test_reg_t;
typedef struct packed {
@@ -370,52 +362,33 @@
typedef struct packed {
struct packed {
logic q;
- } flash_err_en;
- struct packed {
- logic q;
- } flash_alert_en;
- struct packed {
- logic q;
} oob_err;
struct packed {
logic q;
} mp_err;
struct packed {
logic q;
- } ecc_single_err;
+ } rd_err;
struct packed {
logic q;
- } ecc_multi_err;
- } flash_ctrl_reg2hw_err_code_intr_en_reg_t;
-
- typedef struct packed {
+ } prog_win_err;
struct packed {
logic q;
- } flash_err;
+ } prog_type_err;
struct packed {
logic q;
- } flash_alert;
+ } flash_phy_err;
struct packed {
logic q;
- } oob_err;
+ } reg_intg_err;
struct packed {
logic q;
- } mp_err;
- struct packed {
- logic q;
- } ecc_single_err;
- struct packed {
- logic q;
- } ecc_multi_err;
- } flash_ctrl_reg2hw_err_code_reg_t;
+ } phy_intg_err;
+ } flash_ctrl_reg2hw_fault_status_reg_t;
typedef struct packed {
logic [7:0] q;
- } flash_ctrl_reg2hw_ecc_single_err_cnt_reg_t;
-
- typedef struct packed {
- logic [7:0] q;
- } flash_ctrl_reg2hw_ecc_multi_err_cnt_reg_t;
+ } flash_ctrl_reg2hw_ecc_single_err_cnt_mreg_t;
typedef struct packed {
logic q;
@@ -471,7 +444,7 @@
struct packed {
logic d;
logic de;
- } err;
+ } corr_err;
} flash_ctrl_hw2reg_intr_state_reg_t;
typedef struct packed {
@@ -528,11 +501,30 @@
struct packed {
logic d;
logic de;
- } flash_err;
+ } oob_err;
struct packed {
logic d;
logic de;
- } flash_alert;
+ } mp_err;
+ struct packed {
+ logic d;
+ logic de;
+ } rd_err;
+ struct packed {
+ logic d;
+ logic de;
+ } prog_win_err;
+ struct packed {
+ logic d;
+ logic de;
+ } prog_type_err;
+ struct packed {
+ logic d;
+ logic de;
+ } flash_phy_err;
+ } flash_ctrl_hw2reg_err_code_reg_t;
+
+ typedef struct packed {
struct packed {
logic d;
logic de;
@@ -544,22 +536,38 @@
struct packed {
logic d;
logic de;
- } ecc_single_err;
+ } rd_err;
struct packed {
logic d;
logic de;
- } ecc_multi_err;
- } flash_ctrl_hw2reg_err_code_reg_t;
+ } prog_win_err;
+ struct packed {
+ logic d;
+ logic de;
+ } prog_type_err;
+ struct packed {
+ logic d;
+ logic de;
+ } flash_phy_err;
+ struct packed {
+ logic d;
+ logic de;
+ } reg_intg_err;
+ struct packed {
+ logic d;
+ logic de;
+ } phy_intg_err;
+ } flash_ctrl_hw2reg_fault_status_reg_t;
typedef struct packed {
- logic [8:0] d;
+ logic [31:0] d;
logic de;
} flash_ctrl_hw2reg_err_addr_reg_t;
typedef struct packed {
logic [7:0] d;
logic de;
- } flash_ctrl_hw2reg_ecc_single_err_cnt_reg_t;
+ } flash_ctrl_hw2reg_ecc_single_err_cnt_mreg_t;
typedef struct packed {
logic [19:0] d;
@@ -567,16 +575,6 @@
} flash_ctrl_hw2reg_ecc_single_err_addr_mreg_t;
typedef struct packed {
- logic [7:0] d;
- logic de;
- } flash_ctrl_hw2reg_ecc_multi_err_cnt_reg_t;
-
- typedef struct packed {
- logic [19:0] d;
- logic de;
- } flash_ctrl_hw2reg_ecc_multi_err_addr_mreg_t;
-
- typedef struct packed {
struct packed {
logic d;
logic de;
@@ -593,29 +591,27 @@
// Register -> HW type for core interface
typedef struct packed {
- flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [560:555]
- flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [554:549]
- flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [548:537]
- flash_ctrl_reg2hw_alert_test_reg_t alert_test; // [536:529]
- flash_ctrl_reg2hw_flash_disable_reg_t flash_disable; // [528:528]
- flash_ctrl_reg2hw_init_reg_t init; // [527:527]
- flash_ctrl_reg2hw_control_reg_t control; // [526:507]
- flash_ctrl_reg2hw_addr_reg_t addr; // [506:475]
- flash_ctrl_reg2hw_prog_type_en_reg_t prog_type_en; // [474:473]
- flash_ctrl_reg2hw_erase_suspend_reg_t erase_suspend; // [472:472]
- flash_ctrl_reg2hw_mp_region_cfg_mreg_t [7:0] mp_region_cfg; // [471:264]
- flash_ctrl_reg2hw_default_region_reg_t default_region; // [263:258]
- flash_ctrl_reg2hw_bank0_info0_page_cfg_mreg_t [9:0] bank0_info0_page_cfg; // [257:188]
- flash_ctrl_reg2hw_bank0_info1_page_cfg_mreg_t [0:0] bank0_info1_page_cfg; // [187:181]
- flash_ctrl_reg2hw_bank0_info2_page_cfg_mreg_t [1:0] bank0_info2_page_cfg; // [180:167]
- flash_ctrl_reg2hw_bank1_info0_page_cfg_mreg_t [9:0] bank1_info0_page_cfg; // [166:97]
- flash_ctrl_reg2hw_bank1_info1_page_cfg_mreg_t [0:0] bank1_info1_page_cfg; // [96:90]
- flash_ctrl_reg2hw_bank1_info2_page_cfg_mreg_t [1:0] bank1_info2_page_cfg; // [89:76]
- flash_ctrl_reg2hw_mp_bank_cfg_mreg_t [1:0] mp_bank_cfg; // [75:74]
- flash_ctrl_reg2hw_err_code_intr_en_reg_t err_code_intr_en; // [73:68]
- flash_ctrl_reg2hw_err_code_reg_t err_code; // [67:62]
- flash_ctrl_reg2hw_ecc_single_err_cnt_reg_t ecc_single_err_cnt; // [61:54]
- flash_ctrl_reg2hw_ecc_multi_err_cnt_reg_t ecc_multi_err_cnt; // [53:46]
+ flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [552:547]
+ flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [546:541]
+ flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [540:529]
+ flash_ctrl_reg2hw_alert_test_reg_t alert_test; // [528:525]
+ flash_ctrl_reg2hw_flash_disable_reg_t flash_disable; // [524:524]
+ flash_ctrl_reg2hw_init_reg_t init; // [523:523]
+ flash_ctrl_reg2hw_control_reg_t control; // [522:503]
+ flash_ctrl_reg2hw_addr_reg_t addr; // [502:471]
+ flash_ctrl_reg2hw_prog_type_en_reg_t prog_type_en; // [470:469]
+ flash_ctrl_reg2hw_erase_suspend_reg_t erase_suspend; // [468:468]
+ flash_ctrl_reg2hw_mp_region_cfg_mreg_t [7:0] mp_region_cfg; // [467:260]
+ flash_ctrl_reg2hw_default_region_reg_t default_region; // [259:254]
+ flash_ctrl_reg2hw_bank0_info0_page_cfg_mreg_t [9:0] bank0_info0_page_cfg; // [253:184]
+ flash_ctrl_reg2hw_bank0_info1_page_cfg_mreg_t [0:0] bank0_info1_page_cfg; // [183:177]
+ flash_ctrl_reg2hw_bank0_info2_page_cfg_mreg_t [1:0] bank0_info2_page_cfg; // [176:163]
+ flash_ctrl_reg2hw_bank1_info0_page_cfg_mreg_t [9:0] bank1_info0_page_cfg; // [162:93]
+ flash_ctrl_reg2hw_bank1_info1_page_cfg_mreg_t [0:0] bank1_info1_page_cfg; // [92:86]
+ flash_ctrl_reg2hw_bank1_info2_page_cfg_mreg_t [1:0] bank1_info2_page_cfg; // [85:72]
+ flash_ctrl_reg2hw_mp_bank_cfg_mreg_t [1:0] mp_bank_cfg; // [71:70]
+ flash_ctrl_reg2hw_fault_status_reg_t fault_status; // [69:62]
+ flash_ctrl_reg2hw_ecc_single_err_cnt_mreg_t [1:0] ecc_single_err_cnt; // [61:46]
flash_ctrl_reg2hw_phy_err_cfg_reg_t phy_err_cfg; // [45:45]
flash_ctrl_reg2hw_phy_alert_cfg_reg_t phy_alert_cfg; // [44:43]
flash_ctrl_reg2hw_scratch_reg_t scratch; // [42:11]
@@ -625,18 +621,17 @@
// HW -> register type for core interface
typedef struct packed {
- flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [160:149]
- flash_ctrl_hw2reg_ctrl_regwen_reg_t ctrl_regwen; // [148:148]
- flash_ctrl_hw2reg_control_reg_t control; // [147:146]
- flash_ctrl_hw2reg_erase_suspend_reg_t erase_suspend; // [145:144]
- flash_ctrl_hw2reg_op_status_reg_t op_status; // [143:140]
- flash_ctrl_hw2reg_status_reg_t status; // [139:130]
- flash_ctrl_hw2reg_err_code_reg_t err_code; // [129:118]
- flash_ctrl_hw2reg_err_addr_reg_t err_addr; // [117:108]
- flash_ctrl_hw2reg_ecc_single_err_cnt_reg_t ecc_single_err_cnt; // [107:99]
- flash_ctrl_hw2reg_ecc_single_err_addr_mreg_t [1:0] ecc_single_err_addr; // [98:57]
- flash_ctrl_hw2reg_ecc_multi_err_cnt_reg_t ecc_multi_err_cnt; // [56:48]
- flash_ctrl_hw2reg_ecc_multi_err_addr_mreg_t [1:0] ecc_multi_err_addr; // [47:6]
+ flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [157:146]
+ flash_ctrl_hw2reg_ctrl_regwen_reg_t ctrl_regwen; // [145:145]
+ flash_ctrl_hw2reg_control_reg_t control; // [144:143]
+ flash_ctrl_hw2reg_erase_suspend_reg_t erase_suspend; // [142:141]
+ flash_ctrl_hw2reg_op_status_reg_t op_status; // [140:137]
+ flash_ctrl_hw2reg_status_reg_t status; // [136:127]
+ flash_ctrl_hw2reg_err_code_reg_t err_code; // [126:115]
+ flash_ctrl_hw2reg_fault_status_reg_t fault_status; // [114:99]
+ flash_ctrl_hw2reg_err_addr_reg_t err_addr; // [98:66]
+ flash_ctrl_hw2reg_ecc_single_err_cnt_mreg_t [1:0] ecc_single_err_cnt; // [65:48]
+ flash_ctrl_hw2reg_ecc_single_err_addr_mreg_t [1:0] ecc_single_err_addr; // [47:6]
flash_ctrl_hw2reg_phy_status_reg_t phy_status; // [5:0]
} flash_ctrl_core_hw2reg_t;
@@ -725,22 +720,19 @@
parameter logic [CoreAw-1:0] FLASH_CTRL_MP_BANK_CFG_OFFSET = 9'h 144;
parameter logic [CoreAw-1:0] FLASH_CTRL_OP_STATUS_OFFSET = 9'h 148;
parameter logic [CoreAw-1:0] FLASH_CTRL_STATUS_OFFSET = 9'h 14c;
- parameter logic [CoreAw-1:0] FLASH_CTRL_ERR_CODE_INTR_EN_OFFSET = 9'h 150;
- parameter logic [CoreAw-1:0] FLASH_CTRL_ERR_CODE_OFFSET = 9'h 154;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_ERR_CODE_OFFSET = 9'h 150;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_FAULT_STATUS_OFFSET = 9'h 154;
parameter logic [CoreAw-1:0] FLASH_CTRL_ERR_ADDR_OFFSET = 9'h 158;
parameter logic [CoreAw-1:0] FLASH_CTRL_ECC_SINGLE_ERR_CNT_OFFSET = 9'h 15c;
parameter logic [CoreAw-1:0] FLASH_CTRL_ECC_SINGLE_ERR_ADDR_0_OFFSET = 9'h 160;
parameter logic [CoreAw-1:0] FLASH_CTRL_ECC_SINGLE_ERR_ADDR_1_OFFSET = 9'h 164;
- parameter logic [CoreAw-1:0] FLASH_CTRL_ECC_MULTI_ERR_CNT_OFFSET = 9'h 168;
- parameter logic [CoreAw-1:0] FLASH_CTRL_ECC_MULTI_ERR_ADDR_0_OFFSET = 9'h 16c;
- parameter logic [CoreAw-1:0] FLASH_CTRL_ECC_MULTI_ERR_ADDR_1_OFFSET = 9'h 170;
- parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_ERR_CFG_REGWEN_OFFSET = 9'h 174;
- parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_ERR_CFG_OFFSET = 9'h 178;
- parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_ALERT_CFG_OFFSET = 9'h 17c;
- parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_STATUS_OFFSET = 9'h 180;
- parameter logic [CoreAw-1:0] FLASH_CTRL_SCRATCH_OFFSET = 9'h 184;
- parameter logic [CoreAw-1:0] FLASH_CTRL_FIFO_LVL_OFFSET = 9'h 188;
- parameter logic [CoreAw-1:0] FLASH_CTRL_FIFO_RST_OFFSET = 9'h 18c;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_ERR_CFG_REGWEN_OFFSET = 9'h 168;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_ERR_CFG_OFFSET = 9'h 16c;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_ALERT_CFG_OFFSET = 9'h 170;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_PHY_STATUS_OFFSET = 9'h 174;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_SCRATCH_OFFSET = 9'h 178;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_FIFO_LVL_OFFSET = 9'h 17c;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_FIFO_RST_OFFSET = 9'h 180;
// Reset values for hwext registers and their fields for core interface
parameter logic [5:0] FLASH_CTRL_INTR_TEST_RESVAL = 6'h 0;
@@ -749,19 +741,17 @@
parameter logic [0:0] FLASH_CTRL_INTR_TEST_RD_FULL_RESVAL = 1'h 0;
parameter logic [0:0] FLASH_CTRL_INTR_TEST_RD_LVL_RESVAL = 1'h 0;
parameter logic [0:0] FLASH_CTRL_INTR_TEST_OP_DONE_RESVAL = 1'h 0;
- parameter logic [0:0] FLASH_CTRL_INTR_TEST_ERR_RESVAL = 1'h 0;
- parameter logic [3:0] FLASH_CTRL_ALERT_TEST_RESVAL = 4'h 0;
+ parameter logic [0:0] FLASH_CTRL_INTR_TEST_CORR_ERR_RESVAL = 1'h 0;
+ parameter logic [1:0] FLASH_CTRL_ALERT_TEST_RESVAL = 2'h 0;
parameter logic [0:0] FLASH_CTRL_ALERT_TEST_RECOV_ERR_RESVAL = 1'h 0;
- parameter logic [0:0] FLASH_CTRL_ALERT_TEST_RECOV_MP_ERR_RESVAL = 1'h 0;
- parameter logic [0:0] FLASH_CTRL_ALERT_TEST_RECOV_ECC_ERR_RESVAL = 1'h 0;
- parameter logic [0:0] FLASH_CTRL_ALERT_TEST_FATAL_INTG_ERR_RESVAL = 1'h 0;
+ parameter logic [0:0] FLASH_CTRL_ALERT_TEST_FATAL_ERR_RESVAL = 1'h 0;
parameter logic [0:0] FLASH_CTRL_CTRL_REGWEN_RESVAL = 1'h 1;
parameter logic [0:0] FLASH_CTRL_CTRL_REGWEN_EN_RESVAL = 1'h 1;
// Window parameters for core interface
- parameter logic [CoreAw-1:0] FLASH_CTRL_PROG_FIFO_OFFSET = 9'h 190;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_PROG_FIFO_OFFSET = 9'h 184;
parameter int unsigned FLASH_CTRL_PROG_FIFO_SIZE = 'h 4;
- parameter logic [CoreAw-1:0] FLASH_CTRL_RD_FIFO_OFFSET = 9'h 194;
+ parameter logic [CoreAw-1:0] FLASH_CTRL_RD_FIFO_OFFSET = 9'h 188;
parameter int unsigned FLASH_CTRL_RD_FIFO_SIZE = 'h 4;
// Register index for core interface
@@ -850,15 +840,12 @@
FLASH_CTRL_MP_BANK_CFG,
FLASH_CTRL_OP_STATUS,
FLASH_CTRL_STATUS,
- FLASH_CTRL_ERR_CODE_INTR_EN,
FLASH_CTRL_ERR_CODE,
+ FLASH_CTRL_FAULT_STATUS,
FLASH_CTRL_ERR_ADDR,
FLASH_CTRL_ECC_SINGLE_ERR_CNT,
FLASH_CTRL_ECC_SINGLE_ERR_ADDR_0,
FLASH_CTRL_ECC_SINGLE_ERR_ADDR_1,
- FLASH_CTRL_ECC_MULTI_ERR_CNT,
- FLASH_CTRL_ECC_MULTI_ERR_ADDR_0,
- FLASH_CTRL_ECC_MULTI_ERR_ADDR_1,
FLASH_CTRL_PHY_ERR_CFG_REGWEN,
FLASH_CTRL_PHY_ERR_CFG,
FLASH_CTRL_PHY_ALERT_CFG,
@@ -869,7 +856,7 @@
} flash_ctrl_core_id_e;
// Register width information to check illegal writes for core interface
- parameter logic [3:0] FLASH_CTRL_CORE_PERMIT [100] = '{
+ parameter logic [3:0] FLASH_CTRL_CORE_PERMIT [97] = '{
4'b 0001, // index[ 0] FLASH_CTRL_INTR_STATE
4'b 0001, // index[ 1] FLASH_CTRL_INTR_ENABLE
4'b 0001, // index[ 2] FLASH_CTRL_INTR_TEST
@@ -954,22 +941,19 @@
4'b 0001, // index[81] FLASH_CTRL_MP_BANK_CFG
4'b 0001, // index[82] FLASH_CTRL_OP_STATUS
4'b 0001, // index[83] FLASH_CTRL_STATUS
- 4'b 0001, // index[84] FLASH_CTRL_ERR_CODE_INTR_EN
- 4'b 0001, // index[85] FLASH_CTRL_ERR_CODE
- 4'b 0011, // index[86] FLASH_CTRL_ERR_ADDR
- 4'b 0001, // index[87] FLASH_CTRL_ECC_SINGLE_ERR_CNT
+ 4'b 0001, // index[84] FLASH_CTRL_ERR_CODE
+ 4'b 0001, // index[85] FLASH_CTRL_FAULT_STATUS
+ 4'b 1111, // index[86] FLASH_CTRL_ERR_ADDR
+ 4'b 0011, // index[87] FLASH_CTRL_ECC_SINGLE_ERR_CNT
4'b 0111, // index[88] FLASH_CTRL_ECC_SINGLE_ERR_ADDR_0
4'b 0111, // index[89] FLASH_CTRL_ECC_SINGLE_ERR_ADDR_1
- 4'b 0001, // index[90] FLASH_CTRL_ECC_MULTI_ERR_CNT
- 4'b 0111, // index[91] FLASH_CTRL_ECC_MULTI_ERR_ADDR_0
- 4'b 0111, // index[92] FLASH_CTRL_ECC_MULTI_ERR_ADDR_1
- 4'b 0001, // index[93] FLASH_CTRL_PHY_ERR_CFG_REGWEN
- 4'b 0001, // index[94] FLASH_CTRL_PHY_ERR_CFG
- 4'b 0001, // index[95] FLASH_CTRL_PHY_ALERT_CFG
- 4'b 0001, // index[96] FLASH_CTRL_PHY_STATUS
- 4'b 1111, // index[97] FLASH_CTRL_SCRATCH
- 4'b 0011, // index[98] FLASH_CTRL_FIFO_LVL
- 4'b 0001 // index[99] FLASH_CTRL_FIFO_RST
+ 4'b 0001, // index[90] FLASH_CTRL_PHY_ERR_CFG_REGWEN
+ 4'b 0001, // index[91] FLASH_CTRL_PHY_ERR_CFG
+ 4'b 0001, // index[92] FLASH_CTRL_PHY_ALERT_CFG
+ 4'b 0001, // index[93] FLASH_CTRL_PHY_STATUS
+ 4'b 1111, // index[94] FLASH_CTRL_SCRATCH
+ 4'b 0011, // index[95] FLASH_CTRL_FIFO_LVL
+ 4'b 0001 // index[96] FLASH_CTRL_FIFO_RST
};
endpackage
diff --git a/hw/ip/flash_ctrl/rtl/flash_mp.sv b/hw/ip/flash_ctrl/rtl/flash_mp.sv
index 3adfcf0..bafa659 100644
--- a/hw/ip/flash_ctrl/rtl/flash_mp.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_mp.sv
@@ -36,7 +36,6 @@
output logic prog_done_o,
output logic erase_done_o,
output logic error_o,
- output logic [AllPagesW-1:0] err_addr_o,
// interface signals to/from flash_phy
output logic req_o,
@@ -263,12 +262,10 @@
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
txn_err <= 1'b0;
- err_addr_o <= '0;
end else if (txn_err) begin
txn_err <= 1'b0;
end else if (no_allowed_txn) begin
txn_err <= 1'b1;
- err_addr_o <= bank_page_addr;
end
end
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy.sv b/hw/ip/flash_ctrl/rtl/flash_phy.sv
index 134fc33..da8f947 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy.sv
@@ -159,11 +159,9 @@
flash_phy_pkg::flash_phy_prim_flash_req_t [NumBanks-1:0] prim_flash_req;
flash_phy_pkg::flash_phy_prim_flash_rsp_t [NumBanks-1:0] prim_flash_rsp;
logic [NumBanks-1:0] ecc_single_err;
- logic [NumBanks-1:0] ecc_multi_err;
logic [NumBanks-1:0][BusAddrW-1:0] ecc_addr;
assign flash_ctrl_o.ecc_single_err = ecc_single_err;
- assign flash_ctrl_o.ecc_multi_err = ecc_multi_err;
assign flash_ctrl_o.ecc_addr = ecc_addr;
lc_ctrl_pkg::lc_tx_t [NumBanks-1:0] flash_disable;
@@ -250,7 +248,6 @@
.prim_flash_req_o(prim_flash_req[bank]),
.prim_flash_rsp_i(prim_flash_rsp[bank]),
.ecc_single_err_o(ecc_single_err[bank]),
- .ecc_multi_err_o(ecc_multi_err[bank]),
.ecc_addr_o(ecc_addr[bank][BusBankAddrW-1:0])
);
end // block: gen_flash_banks
@@ -311,8 +308,6 @@
);
logic unused_alert;
assign unused_alert = flash_ctrl_i.alert_trig & flash_ctrl_i.alert_ack;
- assign flash_ctrl_o.flash_alert_p = flash_alert_o.p;
- assign flash_ctrl_o.flash_alert_n = flash_alert_o.n;
logic unused_trst_n;
assign unused_trst_n = flash_ctrl_i.jtag_req.trst_n;
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
index ebc2c0b..372e878 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
@@ -52,7 +52,6 @@
output logic [BusWidth-1:0] rd_data_o,
output logic rd_err_o,
output logic ecc_single_err_o,
- output logic ecc_multi_err_o,
output logic [BusBankAddrW-1:0] ecc_addr_o
);
@@ -298,7 +297,6 @@
.mask_i(scramble_mask),
.descrambled_data_i(rd_descrambled_data),
.ecc_single_err_o,
- .ecc_multi_err_o,
.ecc_addr_o
);
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
index b5e6cae..fdec5d8 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
@@ -74,7 +74,7 @@
logic align_next;
data_sel_e data_sel;
- localparam bit [WordSelW-1:0] MaxIdx = WordSelW'(WidthMultiple - 1);
+ localparam int MaxIdx = WidthMultiple - 1;
logic [WidthMultiple-1:0][BusWidth-1:0] packed_data;
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
index 18a0498..45b915a 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
@@ -68,8 +68,9 @@
input [FullDataWidth-1:0] data_i,
// error status reporting
+ // only single bit error is shown here as multi-bit errors are
+ // actual data errors are reflected in-band through data_err_o
output logic ecc_single_err_o,
- output logic ecc_multi_err_o,
output logic [BusBankAddrW-1:0] ecc_addr_o
);
@@ -339,6 +340,7 @@
// scrambled data must pass through ECC first
logic valid_ecc;
+ logic ecc_multi_err_raw;
logic ecc_multi_err;
logic ecc_single_err;
logic [DataWidth-1:0] data_ecc_chk;
@@ -355,26 +357,27 @@
.data_i(data_i[ScrDataWidth-1:0]),
.data_o(data_ecc_chk),
.syndrome_o(),
- .err_o({ecc_multi_err, ecc_single_err})
+ .err_o({ecc_multi_err_raw, ecc_single_err})
);
- // If data needs to be de-scrambled and has not been erased, pass through ecc decoder.
- // Otherwise, pass the data through untouched.
- // Likewise, ecc error is only observed if the data needs to be de-scrambled and has not been
- // erased.
- // rd_done signal below is duplicated (already in data_erased) to show clear intent of the code.
- assign data_int = valid_ecc ? data_ecc_chk :
- data_i[DataWidth-1:0];
-
// For instruction type accesses, always return the transaction error
// For data type accesses, allow the error return to be configurable, as the actual data may
// need to be debugged
- assign data_err = (rd_attrs.req_type == tlul_pkg::InstrType) ?
- ecc_multi_err_o :
- ecc_multi_err_o & ecc_multi_err_en_i;
+ assign ecc_multi_err = (rd_attrs.req_type == tlul_pkg::InstrType) ?
+ ecc_multi_err_raw :
+ ecc_multi_err_raw & ecc_multi_err_en_i;
+
+ // If there is a detected multi-bit error or a single bit error, always return the
+ // ECC corrected result (even though it is possibly wrong).
+ // There is no data error of any kind (specifically when multi_err is disabled), just
+ // return the raw data so that it can be debugged.
+ assign data_int = data_err | ecc_single_err_o ?
+ data_ecc_chk :
+ data_i[DataWidth-1:0];
+
+ assign data_err = valid_ecc & ecc_multi_err;
// always send out sideband indication on error
- assign ecc_multi_err_o = valid_ecc & ecc_multi_err;
assign ecc_single_err_o = valid_ecc & ecc_single_err;
// ecc address return is always the full flash word
diff --git a/hw/ip/prim_generic/lint/prim_generic_flash.waiver b/hw/ip/prim_generic/lint/prim_generic_flash.waiver
index 16bdd05..c9602d5 100644
--- a/hw/ip/prim_generic/lint/prim_generic_flash.waiver
+++ b/hw/ip/prim_generic/lint/prim_generic_flash.waiver
@@ -3,3 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
#
# waiver file for prim_generic_flash
+
+# The prim generic module does not make use of the IO ports
+waive -rules INOUT_AS_IN -location {prim_generic_flash.sv} \
+ -regexp {Inout port 'flash_.*_io' has no driver}
diff --git a/sw/device/silicon_creator/lib/drivers/alert_functest.c b/sw/device/silicon_creator/lib/drivers/alert_functest.c
index de8c9a1..d232db8 100644
--- a/sw/device/silicon_creator/lib/drivers/alert_functest.c
+++ b/sw/device/silicon_creator/lib/drivers/alert_functest.c
@@ -62,13 +62,13 @@
.phase_cycles = {1, 10, 100, 1000},
};
- LOG_INFO("Configure FlashCtrlFatalIntgErr as class A");
- RETURN_IF_ERROR(alert_configure(kTopEarlgreyAlertIdFlashCtrlFatalIntgErr,
+ LOG_INFO("Configure FlashCtrlFatalErr as class A");
+ RETURN_IF_ERROR(alert_configure(kTopEarlgreyAlertIdFlashCtrlFatalErr,
kAlertClassA, kAlertEnableEnabled));
LOG_INFO("Configure class A alerts");
RETURN_IF_ERROR(alert_class_configure(kAlertClassA, &config));
LOG_INFO("Generate alert via test regs");
- abs_mmio_write32(kFlashBase + FLASH_CTRL_ALERT_TEST_REG_OFFSET, 8);
+ abs_mmio_write32(kFlashBase + FLASH_CTRL_ALERT_TEST_REG_OFFSET, 2);
return kErrorUnknown;
}