[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