[flash_ctrl] design and dv updates for alerts
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
index 7592c78..2807c24 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
@@ -815,8 +815,10 @@
) u_alert_sender (
.clk_i,
.rst_ni,
- .alert_req_i(alert_srcs[i] | alert_tests[i]),
+ .alert_req_i(alert_srcs[i]),
+ .alert_test_i(alert_tests[i]),
.alert_ack_o(),
+ .alert_state_o(),
.alert_rx_i(alert_rx_i[i]),
.alert_tx_o(alert_tx_o[i])
);
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv
index 4461f69..c923b27 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv
@@ -25,6 +25,7 @@
`uvm_object_new
virtual function void initialize(bit [TL_AW-1:0] csr_base_addr = '1);
+ list_of_alerts = flash_ctrl_env_pkg::LIST_OF_ALERTS;
super.initialize(csr_base_addr);
// create tl agent config obj
m_eflash_tl_agent_cfg = tl_agent_cfg::type_id::create("m_eflash_tl_agent_cfg");
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 f62ac45..c80b91a 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
@@ -20,7 +20,8 @@
`include "dv_macros.svh"
// parameters
-
+ parameter string LIST_OF_ALERTS[] = {"fatal_err", "recov_mp_err", "recov_ecc_err"};
+ parameter uint NUM_ALERTS = 3;
parameter uint FlashNumPages = flash_ctrl_pkg::NumBanks * flash_ctrl_pkg::PagesPerBank;
parameter uint FlashSizeBytes = FlashNumPages * flash_ctrl_pkg::WordsPerPage *
flash_ctrl_pkg::DataWidth / 8;
diff --git a/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv b/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv
index fd4df3a..e116448 100644
--- a/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv
+++ b/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv
@@ -43,7 +43,10 @@
output logic intr_prog_lvl_o, // Program fifo is empty
output logic intr_rd_full_o, // Read fifo is full
output logic intr_rd_lvl_o, // Read fifo is full
- output logic intr_op_done_o // Requested flash operation (wr/erase) done
+ output logic intr_op_done_o, // Requested flash operation (wr/erase) done
+
+ input prim_alert_pkg::alert_rx_t [flash_ctrl_reg_pkg::NumAlerts-1:0] alert_rx_i,
+ output prim_alert_pkg::alert_tx_t [flash_ctrl_reg_pkg::NumAlerts-1:0] alert_tx_o
);
// define inter-module signals
@@ -61,6 +64,10 @@
.intr_rd_lvl_o (intr_rd_lvl_o),
.intr_op_done_o (intr_op_done_o),
+ // Alerts
+ .alert_rx_i,
+ .alert_tx_o,
+
// Inter-module signals
.flash_o (flash_ctrl_flash_req),
.flash_i (flash_ctrl_flash_rsp),
diff --git a/hw/ip/flash_ctrl/dv/tb/tb.sv b/hw/ip/flash_ctrl/dv/tb/tb.sv
index 2de60ec..287f2cf 100644
--- a/hw/ip/flash_ctrl/dv/tb/tb.sv
+++ b/hw/ip/flash_ctrl/dv/tb/tb.sv
@@ -31,6 +31,8 @@
tl_if tl_if(.clk(clk), .rst_n(rst_n));
tl_if eflash_tl_if(.clk(clk), .rst_n(rst_n));
+ `DV_ALERT_IF_CONNECT
+
// dut
flash_ctrl_wrapper dut (
.clk_i (clk ),
@@ -67,7 +69,9 @@
.intr_prog_lvl_o (intr_prog_lvl ),
.intr_rd_full_o (intr_rd_full ),
.intr_rd_lvl_o (intr_rd_lvl ),
- .intr_op_done_o (intr_op_done )
+ .intr_op_done_o (intr_op_done ),
+ .alert_rx_i (alert_rx ),
+ .alert_tx_o (alert_tx )
);
// bind mem_bkdr_if
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
index fca06d5..9661d91 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
@@ -335,10 +335,15 @@
logic data_err;
// scrambled data must pass through ECC first
+ logic valid_ecc;
+ logic ecc_multi_err;
+ logic ecc_single_err;
logic [DataWidth-1:0] data_ecc_chk;
logic [DataWidth-1:0] data_int;
logic data_erased;
+ assign valid_ecc = rd_done && rd_attrs.ecc && !data_erased;
+
// When all bits are 1, the data has been erased
// This check is only valid when read data returns.
assign data_erased = rd_done & (data_i == {FullDataWidth{1'b1}});
@@ -347,20 +352,21 @@
.in(data_i[ScrDataWidth-1:0]),
.d_o(data_ecc_chk),
.syndrome_o(),
- .err_o({ecc_multi_err_o, ecc_single_err_o})
+ .err_o({ecc_multi_err, ecc_single_err})
);
- // ecc address return is always the full flash word
- assign ecc_addr_o = {rd_attrs.addr, {LsbAddrBit{1'b0}}};
-
// 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 = (rd_done && rd_attrs.ecc && !data_erased) ? data_ecc_chk :
- data_i[DataWidth-1:0];
- assign data_err = (rd_done && rd_attrs.ecc && !data_erased) ? ecc_multi_err_o : 1'b0;
+ assign data_int = valid_ecc ? data_ecc_chk :
+ data_i[DataWidth-1:0];
+ assign data_err = valid_ecc & ecc_multi_err;
+ assign ecc_multi_err_o = data_err;
+ assign ecc_single_err_o = valid_ecc & ecc_single_err;
+ // ecc address return is always the full flash word
+ assign ecc_addr_o = {rd_attrs.addr, {LsbAddrBit{1'b0}}};
/////////////////////////////////
// De-scrambling stage