[flash] Split scramble and ecc controls
- it is now possible to enable one without the other
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
index d4ace02..7b97df1 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
@@ -388,7 +388,14 @@
{ bits: "4",
name: "SCRAMBLE_EN",
desc: '''
- Region is scramble and ECC enabled.
+ Region is scramble enabled.
+ ''',
+ resval: "0"
+ }
+ { bits: "5",
+ name: "ECC_EN",
+ desc: '''
+ Region is ECC enabled.
''',
resval: "0"
}
@@ -441,7 +448,14 @@
{ bits: "3",
name: "SCRAMBLE_EN",
desc: '''
- Region is scramble and ECC enabled
+ Region is scrambleenabled
+ ''',
+ resval: "0"
+ }
+ { bits: "4",
+ name: "ECC_EN",
+ desc: '''
+ Region is ECC enabled
''',
resval: "0"
}
@@ -527,7 +541,14 @@
{ bits: "4",
name: "SCRAMBLE_EN",
desc: '''
- Region is scramble and ECC enabled.
+ Region is scramble enabled.
+ ''',
+ resval: "0"
+ }
+ { bits: "5",
+ name: "ECC_EN",
+ desc: '''
+ Region is ECC enabled.
''',
resval: "0"
}
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
index 00f4541..e9de226 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
@@ -516,6 +516,7 @@
assign region_cfgs[MpRegions].prog_en.q = reg2hw.default_region.prog_en.q;
assign region_cfgs[MpRegions].erase_en.q = reg2hw.default_region.erase_en.q;
assign region_cfgs[MpRegions].scramble_en.q = reg2hw.default_region.scramble_en.q;
+ assign region_cfgs[MpRegions].ecc_en.q = reg2hw.default_region.ecc_en.q;
//////////////////////////////////////
// Info partition protection configuration
@@ -591,6 +592,7 @@
// flash phy interface
.req_o(flash_o.req),
.scramble_en_o(flash_o.scramble_en),
+ .ecc_en_o(flash_o.ecc_en),
.rd_o(flash_o.rd),
.prog_o(flash_o.prog),
.pg_erase_o(flash_o.pg_erase),
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 826ba75..93243a8 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
@@ -140,7 +140,8 @@
rd_en: 1'b1,
prog_en: 1'b0,
erase_en: 1'b0,
- scramble_en: 1'b0 // TBD, update to 1 once tb supports ECC
+ scramble_en: 1'b0,
+ ecc_en: 1'b0 // TBD, update to 1 once tb supports ECC
};
parameter info_page_cfg_t CfgAllowReadErase = '{
@@ -148,7 +149,8 @@
rd_en: 1'b1,
prog_en: 1'b0,
erase_en: 1'b1,
- scramble_en: 1'b0 // TBD, update to 1 once tb supports ECC
+ scramble_en: 1'b0,
+ ecc_en: 1'b0 // TBD, update to 1 once tb supports ECC
};
parameter info_page_attr_t HwInfoPageAttr[HwInfoRules] = '{
@@ -180,6 +182,7 @@
prog_en: 1'b0,
erase_en: 1'b1,
scramble_en: 1'b0,
+ ecc_en: 1'b0,
base: '0,
size: '{default:'1}
}
@@ -235,6 +238,7 @@
typedef struct packed {
logic req;
logic scramble_en;
+ logic ecc_en;
logic rd;
logic prog;
logic pg_erase;
@@ -253,6 +257,7 @@
parameter flash_req_t FLASH_REQ_DEFAULT = '{
req: 1'b0,
scramble_en: 1'b0,
+ ecc_en: 1'b0,
rd: 1'b0,
prog: 1'b0,
pg_erase: 1'b0,
diff --git a/hw/ip/flash_ctrl/rtl/flash_mp.sv b/hw/ip/flash_ctrl/rtl/flash_mp.sv
index 5e174f0..a0a8690 100644
--- a/hw/ip/flash_ctrl/rtl/flash_mp.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_mp.sv
@@ -41,6 +41,7 @@
output logic rd_o,
output logic prog_o,
output logic scramble_en_o,
+ output logic ecc_en_o,
output logic pg_erase_o,
output logic bk_erase_o,
input rd_done_i,
@@ -71,10 +72,12 @@
logic data_pg_erase_en;
logic data_bk_erase_en;
logic data_scramble_en;
+ logic data_ecc_en;
logic info_rd_en;
logic info_prog_en;
logic info_erase_en;
logic info_scramble_en;
+ logic info_ecc_en;
// Memory protection handling for hardware interface
logic hw_sel;
@@ -175,6 +178,7 @@
assign data_pg_erase_en = data_en & pg_erase_i & data_region_cfg.erase_en.q;
assign data_bk_erase_en = data_en & bk_erase_i & |bk_erase_en;
assign data_scramble_en = data_en & (rd_i | prog_i) & data_region_cfg.scramble_en.q;
+ assign data_ecc_en = data_en & (rd_i | prog_i) & data_region_cfg.ecc_en.q;
assign invalid_data_txn = req_i & data_part_sel &
@@ -227,6 +231,7 @@
assign info_prog_en = info_en & prog_i & page_cfg.prog_en.q;
assign info_erase_en = info_en & pg_erase_i & page_cfg.erase_en.q;
assign info_scramble_en = info_en & (rd_i | prog_i) & page_cfg.scramble_en.q;
+ assign info_ecc_en = info_en & (rd_i | prog_i) & page_cfg.ecc_en.q;
// check for invalid transactions
assign invalid_info_txn = req_i & info_part_sel &
@@ -241,6 +246,7 @@
assign pg_erase_o = req_i & (data_pg_erase_en | info_erase_en);
assign bk_erase_o = req_i & data_bk_erase_en;
assign scramble_en_o = req_i & (data_scramble_en | info_scramble_en);
+ assign ecc_en_o = req_i & (data_ecc_en | info_ecc_en);
assign req_o = rd_o | prog_o | pg_erase_o | bk_erase_o;
logic txn_err;
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy.sv b/hw/ip/flash_ctrl/rtl/flash_phy.sv
index 4c5969c..750cddd 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy.sv
@@ -105,7 +105,7 @@
// Generate host scramble_en indication, broadcasted to all banks
localparam int TotalRegions = MpRegions + 1;
- logic host_scramble_en;
+ logic host_scramble_en, host_ecc_en;
data_region_attr_t region_attrs [TotalRegions];
mp_region_cfg_t region_cfg, unused_cfg;
@@ -128,8 +128,9 @@
// most attributes are unused
assign unused_cfg = region_cfg;
- // only scramble attributes are looked at
+ // only scramble/ecc attributes are looked at
assign host_scramble_en = region_cfg.scramble_en.q;
+ assign host_ecc_en = region_cfg.ecc_en.q;
for (genvar bank = 0; bank < NumBanks; bank++) begin : gen_flash_banks
@@ -163,10 +164,12 @@
.rst_ni,
.req_i(ctrl_req),
.scramble_en_i(flash_ctrl_i.scramble_en),
+ .ecc_en_i(flash_ctrl_i.ecc_en),
// host request must be suppressed if response fifo cannot hold more
// otherwise the flash_phy_core and flash_phy will get out of sync
.host_req_i(host_req),
.host_scramble_en_i(host_scramble_en),
+ .host_ecc_en_i(host_ecc_en),
.host_addr_i(host_addr_i[0 +: BusBankAddrW]),
.rd_i(flash_ctrl_i.rd),
.prog_i(flash_ctrl_i.prog),
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
index 481e52a..1793443 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
@@ -17,9 +17,11 @@
input rst_ni,
input host_req_i, // host request - read only
input host_scramble_en_i,
+ input host_ecc_en_i,
input [BusBankAddrW-1:0] host_addr_i,
input req_i, // controller request
input scramble_en_i,
+ input ecc_en_i,
input rd_i,
input prog_i,
input pg_erase_i,
@@ -83,6 +85,7 @@
logic [BusBankAddrW-1:0] muxed_addr;
flash_ctrl_pkg::flash_part_e muxed_part;
logic muxed_scramble_en;
+ logic muxed_ecc_en;
// entire read stage is idle, inclusive of all stages
logic rd_stage_idle;
@@ -219,6 +222,7 @@
assign muxed_addr = host_sel ? host_addr_i : addr_i;
assign muxed_part = host_sel ? flash_ctrl_pkg::FlashPartData : part_i;
assign muxed_scramble_en = host_sel ? host_scramble_en_i : scramble_en_i;
+ assign muxed_ecc_en = host_sel ? host_ecc_en_i : ecc_en_i;
assign rd_done_o = ctrl_rsp_vld & rd_i;
assign prog_done_o = ctrl_rsp_vld & prog_i;
assign erase_done_o = ctrl_rsp_vld & (pg_erase_i | bk_erase_i);
@@ -240,6 +244,7 @@
.rst_ni,
.req_i(reqs[PhyRead]),
.descramble_i(muxed_scramble_en),
+ .ecc_i(muxed_ecc_en),
.prog_i(reqs[PhyProg]),
.pg_erase_i(reqs[PhyPgErase]),
.bk_erase_i(reqs[PhyBkErase]),
@@ -287,6 +292,7 @@
.rst_ni,
.req_i(reqs[PhyProg]),
.scramble_i(muxed_scramble_en),
+ .ecc_i(muxed_ecc_en),
.sel_i(addr_i[0 +: WordSelW]),
.data_i(prog_data_i),
.last_i(prog_last_i),
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
index 4d3b8c9..6937548 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
@@ -72,6 +72,7 @@
typedef struct packed {
logic [BankAddrW-1:0] addr;
logic descramble;
+ logic ecc;
} rd_attr_t;
// Flash Operations Supported
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
index caeac92..189e52a 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
@@ -27,6 +27,7 @@
input rst_ni,
input req_i,
input scramble_i,
+ input ecc_i,
input [WordSelW-1:0] sel_i,
input [BusWidth-1:0] data_i,
input last_i,
@@ -239,7 +240,7 @@
);
// pad the remaining bits to '0', this effectively "programs" them.
- assign data_o = scramble_i ? FullDataWidth'(ecc_data) : FullDataWidth'(packed_data);
+ assign data_o = ecc_i ? FullDataWidth'(ecc_data) : FullDataWidth'(packed_data);
/////////////////////////////////
// Assertions
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
index ef8b242..d0813df 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
@@ -33,6 +33,7 @@
// interface with arbitration unit
input req_i,
input descramble_i,
+ input ecc_i,
input prog_i,
input pg_erase_i,
input bk_erase_i,
@@ -274,6 +275,7 @@
alloc_q <= alloc;
rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
rd_attrs.descramble <= descramble_i;
+ rd_attrs.ecc <= ecc_i;
end else if (rd_done) begin
rd_busy <= 1'b0;
end
@@ -320,6 +322,7 @@
.syndrome_o(),
.err_o({ecc_err, ecc_single_err})
);
+
assign unused_err = ecc_single_err;
// If data needs to be de-scrambled and has not been erased, pass through ecc decoder.
@@ -327,9 +330,9 @@
// 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.descramble && !data_erased) ? data_ecc_chk :
- data_i[DataWidth-1:0];
- assign data_err = (rd_done && rd_attrs.descramble && !data_erased) ? ecc_err : 1'b0;
+ 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_err : 1'b0;
/////////////////////////////////
// De-scrambling stage