[flash] - Add flash info page support

Flash info pages are accessible only from the flash controller and not
from the host.

This commit adds the functionality by basically assigning an extra
address bit to access the info pages when going through the controller.

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 377dfd6..05d192f 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson
@@ -40,8 +40,42 @@
 
   regwidth: "32",
   registers: [
+
+    { name: "CTRL_REGWEN",
+      swaccess: "ro",
+      hwaccess: "hwo",
+      hwext: "true",
+      desc: '''
+      Controls the configurability of the !!CONTROL register.
+
+      This register ensures the contents of !!CONTROL cannot be changed by software once a flash
+      operation has begun.
+
+      It unlocks whenever the existing flash operation completes, regardless of success or error.
+      ''',
+
+      fields: [
+        { bits: "0",
+          name: "EN",
+          desc: '''
+            Configuration enable.
+
+            This bit defaults to 1 and is set to 0 by hardware when flash operation is initiated.
+            When the controller completes the flash operation, this bit is set
+            back to 1 to allow software configuration of !!CONTROL
+          ''',
+          resval: "1",
+        },
+      ]
+      tags: [// This regwen is completely under HW management and thus cannot be manipulated
+             // by software.
+             "excl:CsrNonInitTests:CsrExclCheck"]
+    },
+
+
     { name: "CONTROL",
       desc: "Control register",
+      regwen: "CTRL_REGWEN",
       swaccess: "rw",
       hwaccess: "hro",
       fields: [
@@ -107,8 +141,17 @@
           ]
         },
         { bits: "7",
-          name: "FIFO_RST",
-          desc: "RST FIFOs",
+          name: "PARTITION_SEL",
+          desc: '''
+            Selects either info or data partition for operation.
+
+            When 0, select data partition - this is the portion of flash that is accessible both
+            by the host and by the controller.
+
+            When 1, select info partition - this is the portion of flash that is only accessible
+            by the controller.
+
+          '''
           resval: "0"
         },
         { bits: "27:16",
@@ -257,6 +300,16 @@
               ''',
               resval: "0"
             },
+            { bits: "25",
+              name: "PARTITION",
+              desc: '''
+                Region partition select
+
+                0 selects data partition
+                1 selects info partition
+              ''',
+              resval: "0"
+            },
         ],
       },
     },
@@ -355,10 +408,10 @@
       hwaccess: "hwo",
       hwext: "true",
       fields: [
-        { bits: "0",    name: "rd_full",    desc: "Flash read fifo full, software must consume data"},
-        { bits: "1",    name: "rd_empty",   desc: "Flash read fifo empty", resval: "1"},
-        { bits: "2",    name: "prog_full",  desc: "Flash program fifo full"},
-        { bits: "3",    name: "prog_empty", desc: "Flash program fifo empty, software must provide data", resval: "1"},
+        { bits: "0",    name: "rd_full",    desc: "Flash read FIFO full, software must consume data"},
+        { bits: "1",    name: "rd_empty",   desc: "Flash read FIFO empty", resval: "1"},
+        { bits: "2",    name: "prog_full",  desc: "Flash program FIFO full"},
+        { bits: "3",    name: "prog_empty", desc: "Flash program FIFO empty, software must provide data", resval: "1"},
         { bits: "4",    name: "init_wip",   desc: "Flash controller undergoing init"},
         { bits: "16:8", name: "error_page", desc: "Flash controller error page."},
         { bits: "17",   name: "error_bank", desc: "Flash controller error bank."},
@@ -372,14 +425,14 @@
       ]
     },
     { name: "FIFO_LVL",
-      desc: "Programmable depth where fifos should generate interrupts",
+      desc: "Programmable depth where FIFOs should generate interrupts",
       swaccess: "rw",
       hwaccess: "hro",
       fields: [
         { bits: "4:0",
           name: "PROG",
           desc: '''
-            When the program fifo drains to this level, trigger an interrupt.
+            When the program FIFO drains to this level, trigger an interrupt.
             Default value is set such that interrupt does not trigger at reset.
             '''
           resval: "0xF"
@@ -387,13 +440,33 @@
         { bits: "12:8",
           name: "RD",
           desc: '''
-            When the read fifo fills to this level, trigger an interrupt.
+            When the read FIFO fills to this level, trigger an interrupt.
             Default value is set such that interrupt does not trigger at reset.
             '''
           resval: "0xF"
         },
       ]
     }
+
+    { name: "FIFO_RST",
+      desc: "Reset for flash controller FIFOs",
+      swaccess: "rw",
+      hwaccess: "hro",
+      resval: "0",
+      fields: [
+        { bits: "0",
+          name: "EN",
+          desc: '''
+            Active high resets for both program and read FIFOs.  This is especially useful after the controller
+            encounters an error of some kind.
+
+            This bit will hold the FIFO in reset as long as it is set.
+            '''
+          resval: "0"
+        },
+      ]
+    },
+
     { window: {
         name: "prog_fifo",
         items: "1",
@@ -402,11 +475,11 @@
         unusual: "false"
         swaccess: "wo",
         desc: '''
-          Flash program fifo.
+          Flash program FIFO.
 
-          The fifo is 16 entries of 4B flash words. This FIFO can only be programmed
+          The FIFO is 16 entries of 4B flash words. This FIFO can only be programmed
           by software after a program operation has been initiated via the !!CONTROL register.
-          This ensures accidental programming of the program fifo cannot lock up the system.
+          This ensures accidental programming of the program FIFO cannot lock up the system.
           '''
       },
     },
@@ -418,9 +491,9 @@
         unusual: "false"
         swaccess: "ro",
         desc: '''
-          Flash read fifo.
+          Flash read FIFO.
 
-          The fifo is 16 entries of 4B flash words
+          The FIFO is 16 entries of 4B flash words
           '''
       },
     },
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
index b0acebf..b9e4cfc 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
@@ -2,7 +2,7 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 //
-// Faux Flash Controller Module
+// Flash Controller Module
 //
 //
 
@@ -145,7 +145,7 @@
   ) u_prog_fifo (
     .clk_i,
     .rst_ni (rst_ni),
-    .clr_i  (reg2hw.control.fifo_rst.q),
+    .clr_i  (reg2hw.fifo_rst.q),
     .wvalid (prog_fifo_req & prog_fifo_wen & prog_op_valid),
     .wready (prog_fifo_wready),
     .wdata  (prog_fifo_wdata),
@@ -221,7 +221,7 @@
   ) u_rd_fifo (
     .clk_i,
     .rst_ni (rst_ni),
-    .clr_i  (reg2hw.control.fifo_rst.q),
+    .clr_i  (reg2hw.fifo_rst.q),
     .wvalid (rd_fifo_wen),
     .wready (rd_fifo_wready),
     .wdata  (rd_fifo_wdata),
@@ -311,13 +311,19 @@
 
   assign region_cfgs[MpRegions-1:0] = reg2hw.mp_region_cfg[MpRegions-1:0];
 
-  //last region
+  //default region
   assign region_cfgs[MpRegions].base.q = '0;
   assign region_cfgs[MpRegions].size.q = {AllPagesW{1'b1}};
   assign region_cfgs[MpRegions].en.q = 1'b1;
   assign region_cfgs[MpRegions].rd_en.q = reg2hw.default_region.rd_en.q;
   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;
+  // we are allowed to set default accessibility of data partitions
+  // however info partitions default to inaccessible
+  assign region_cfgs[MpRegions].partition.q = DataPart;
+
+  flash_part_e flash_part_sel;
+  assign flash_part_sel = flash_part_e'(reg2hw.control.partition_sel.q);
 
   // Flash memory protection
   flash_mp #(
@@ -335,6 +341,7 @@
     // read / prog / erase controls
     .req_i(flash_req),
     .req_addr_i(flash_addr[WordW +: AllPagesW]),
+    .req_part_i(flash_part_sel),
     .addr_ovfl_i(rd_flash_ovfl | prog_flash_ovfl),
     .req_bk_i(flash_addr[BankAddrW +: BankW]),
     .rd_i(rd_op),
@@ -373,9 +380,11 @@
   assign hw2reg.status.error_bank.d = err_bank;
   assign hw2reg.control.start.d = 1'b0;
   assign hw2reg.control.start.de = |ctrl_done;
+  assign hw2reg.ctrl_regwen.d = !reg2hw.control.start.q;
 
   // Flash Interface
   assign flash_o.addr = flash_addr;
+  assign flash_o.part = flash_part_sel;
   assign flash_o.prog_data = flash_prog_data;
   assign flash_rd_data = flash_i.rd_data;
   assign init_busy = flash_i.init_busy;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
index 130aa1c..b5f6a80 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
@@ -9,15 +9,16 @@
 
   // parameters for flash macro properties
   localparam int NumBanks        = top_pkg::FLASH_BANKS;
-  localparam int PagesPerBank    = top_pkg::FLASH_PAGES_PER_BANK;
-  localparam int WordsPerPage    = top_pkg::FLASH_WORDS_PER_PAGE;  //Number of bus words per page
+  localparam int InfosPerBank    = top_pkg::FLASH_INFO_PER_BANK;  //Info pages per bank
+  localparam int PagesPerBank    = top_pkg::FLASH_PAGES_PER_BANK; //Data pages per bank
+  localparam int WordsPerPage    = top_pkg::FLASH_WORDS_PER_PAGE; //Number of bus words per page
   localparam int BytesPerWord    = top_pkg::FLASH_BYTES_PER_WORD;
   localparam int BankW           = $clog2(NumBanks);
   localparam int PageW           = $clog2(PagesPerBank);
   localparam int WordW           = $clog2(WordsPerPage);
   localparam int AddrW           = BankW + PageW + WordW; // all flash range
   localparam int BankAddrW       = PageW + WordW;         // 1 bank of flash range
-  localparam int DataWidth       = 64;
+  localparam int DataWidth       = top_pkg::FLASH_DATA_WIDTH;
   localparam int FlashTotalPages = NumBanks * PagesPerBank;
   localparam int AllPagesW       = BankW + PageW;
 
@@ -51,6 +52,12 @@
     ReadDir      = 1'b1
   } flash_flfo_dir_e;
 
+  // Flash partition type
+  typedef enum logic {
+    DataPart     = 1'b0,
+    InfoPart     = 1'b1
+  } flash_part_e;
+
   // Flash controller to memory
   typedef struct packed {
     logic                req;
@@ -58,6 +65,7 @@
     logic                prog;
     logic                pg_erase;
     logic                bk_erase;
+    flash_part_e         part;
     logic [AddrW-1:0]    addr;
     logic [BusWidth-1:0] prog_data;
   } flash_req_t;
@@ -69,6 +77,7 @@
     prog:      1'b0,
     pg_erase:  1'b0,
     bk_erase:  1'b0,
+    part:      DataPart,
     addr:      '0,
     prog_data: '0
   };
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 44c58b7..cf3e44f 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
@@ -94,7 +94,7 @@
     } erase_sel;
     struct packed {
       logic        q;
-    } fifo_rst;
+    } partition_sel;
     struct packed {
       logic [11:0] q;
     } num;
@@ -123,6 +123,9 @@
     struct packed {
       logic [8:0]  q;
     } size;
+    struct packed {
+      logic        q;
+    } partition;
   } flash_ctrl_reg2hw_mp_region_cfg_mreg_t;
 
   typedef struct packed {
@@ -154,6 +157,10 @@
     } rd;
   } flash_ctrl_reg2hw_fifo_lvl_reg_t;
 
+  typedef struct packed {
+    logic        q;
+  } flash_ctrl_reg2hw_fifo_rst_reg_t;
+
 
   typedef struct packed {
     struct packed {
@@ -183,6 +190,10 @@
   } flash_ctrl_hw2reg_intr_state_reg_t;
 
   typedef struct packed {
+    logic        d;
+  } flash_ctrl_hw2reg_ctrl_regwen_reg_t;
+
+  typedef struct packed {
     struct packed {
       logic        d;
       logic        de;
@@ -229,55 +240,59 @@
   // Register to internal design logic //
   ///////////////////////////////////////
   typedef struct packed {
-    flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [295:290]
-    flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [289:284]
-    flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [283:272]
-    flash_ctrl_reg2hw_control_reg_t control; // [271:255]
-    flash_ctrl_reg2hw_addr_reg_t addr; // [254:223]
-    flash_ctrl_reg2hw_mp_region_cfg_mreg_t [7:0] mp_region_cfg; // [222:47]
-    flash_ctrl_reg2hw_default_region_reg_t default_region; // [46:44]
-    flash_ctrl_reg2hw_mp_bank_cfg_mreg_t [1:0] mp_bank_cfg; // [43:42]
-    flash_ctrl_reg2hw_scratch_reg_t scratch; // [41:10]
-    flash_ctrl_reg2hw_fifo_lvl_reg_t fifo_lvl; // [9:0]
+    flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [304:299]
+    flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [298:293]
+    flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [292:281]
+    flash_ctrl_reg2hw_control_reg_t control; // [280:264]
+    flash_ctrl_reg2hw_addr_reg_t addr; // [263:232]
+    flash_ctrl_reg2hw_mp_region_cfg_mreg_t [7:0] mp_region_cfg; // [231:48]
+    flash_ctrl_reg2hw_default_region_reg_t default_region; // [47:45]
+    flash_ctrl_reg2hw_mp_bank_cfg_mreg_t [1:0] mp_bank_cfg; // [44:43]
+    flash_ctrl_reg2hw_scratch_reg_t scratch; // [42:11]
+    flash_ctrl_reg2hw_fifo_lvl_reg_t fifo_lvl; // [10:1]
+    flash_ctrl_reg2hw_fifo_rst_reg_t fifo_rst; // [0:0]
   } flash_ctrl_reg2hw_t;
 
   ///////////////////////////////////////
   // Internal design logic to register //
   ///////////////////////////////////////
   typedef struct packed {
-    flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [32:27]
-    flash_ctrl_hw2reg_control_reg_t control; // [26:10]
-    flash_ctrl_hw2reg_op_status_reg_t op_status; // [9:10]
-    flash_ctrl_hw2reg_status_reg_t status; // [9:10]
+    flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [33:28]
+    flash_ctrl_hw2reg_ctrl_regwen_reg_t ctrl_regwen; // [27:28]
+    flash_ctrl_hw2reg_control_reg_t control; // [27:11]
+    flash_ctrl_hw2reg_op_status_reg_t op_status; // [10:11]
+    flash_ctrl_hw2reg_status_reg_t status; // [10:11]
   } flash_ctrl_hw2reg_t;
 
   // Register Address
   parameter logic [6:0] FLASH_CTRL_INTR_STATE_OFFSET = 7'h 0;
   parameter logic [6:0] FLASH_CTRL_INTR_ENABLE_OFFSET = 7'h 4;
   parameter logic [6:0] FLASH_CTRL_INTR_TEST_OFFSET = 7'h 8;
-  parameter logic [6:0] FLASH_CTRL_CONTROL_OFFSET = 7'h c;
-  parameter logic [6:0] FLASH_CTRL_ADDR_OFFSET = 7'h 10;
-  parameter logic [6:0] FLASH_CTRL_REGION_CFG_REGWEN_OFFSET = 7'h 14;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG0_OFFSET = 7'h 18;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG1_OFFSET = 7'h 1c;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG2_OFFSET = 7'h 20;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG3_OFFSET = 7'h 24;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG4_OFFSET = 7'h 28;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG5_OFFSET = 7'h 2c;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG6_OFFSET = 7'h 30;
-  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG7_OFFSET = 7'h 34;
-  parameter logic [6:0] FLASH_CTRL_DEFAULT_REGION_OFFSET = 7'h 38;
-  parameter logic [6:0] FLASH_CTRL_BANK_CFG_REGWEN_OFFSET = 7'h 3c;
-  parameter logic [6:0] FLASH_CTRL_MP_BANK_CFG_OFFSET = 7'h 40;
-  parameter logic [6:0] FLASH_CTRL_OP_STATUS_OFFSET = 7'h 44;
-  parameter logic [6:0] FLASH_CTRL_STATUS_OFFSET = 7'h 48;
-  parameter logic [6:0] FLASH_CTRL_SCRATCH_OFFSET = 7'h 4c;
-  parameter logic [6:0] FLASH_CTRL_FIFO_LVL_OFFSET = 7'h 50;
+  parameter logic [6:0] FLASH_CTRL_CTRL_REGWEN_OFFSET = 7'h c;
+  parameter logic [6:0] FLASH_CTRL_CONTROL_OFFSET = 7'h 10;
+  parameter logic [6:0] FLASH_CTRL_ADDR_OFFSET = 7'h 14;
+  parameter logic [6:0] FLASH_CTRL_REGION_CFG_REGWEN_OFFSET = 7'h 18;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG0_OFFSET = 7'h 1c;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG1_OFFSET = 7'h 20;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG2_OFFSET = 7'h 24;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG3_OFFSET = 7'h 28;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG4_OFFSET = 7'h 2c;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG5_OFFSET = 7'h 30;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG6_OFFSET = 7'h 34;
+  parameter logic [6:0] FLASH_CTRL_MP_REGION_CFG7_OFFSET = 7'h 38;
+  parameter logic [6:0] FLASH_CTRL_DEFAULT_REGION_OFFSET = 7'h 3c;
+  parameter logic [6:0] FLASH_CTRL_BANK_CFG_REGWEN_OFFSET = 7'h 40;
+  parameter logic [6:0] FLASH_CTRL_MP_BANK_CFG_OFFSET = 7'h 44;
+  parameter logic [6:0] FLASH_CTRL_OP_STATUS_OFFSET = 7'h 48;
+  parameter logic [6:0] FLASH_CTRL_STATUS_OFFSET = 7'h 4c;
+  parameter logic [6:0] FLASH_CTRL_SCRATCH_OFFSET = 7'h 50;
+  parameter logic [6:0] FLASH_CTRL_FIFO_LVL_OFFSET = 7'h 54;
+  parameter logic [6:0] FLASH_CTRL_FIFO_RST_OFFSET = 7'h 58;
 
   // Window parameter
-  parameter logic [6:0] FLASH_CTRL_PROG_FIFO_OFFSET = 7'h 54;
+  parameter logic [6:0] FLASH_CTRL_PROG_FIFO_OFFSET = 7'h 5c;
   parameter logic [6:0] FLASH_CTRL_PROG_FIFO_SIZE   = 7'h 4;
-  parameter logic [6:0] FLASH_CTRL_RD_FIFO_OFFSET = 7'h 58;
+  parameter logic [6:0] FLASH_CTRL_RD_FIFO_OFFSET = 7'h 60;
   parameter logic [6:0] FLASH_CTRL_RD_FIFO_SIZE   = 7'h 4;
 
   // Register Index
@@ -285,6 +300,7 @@
     FLASH_CTRL_INTR_STATE,
     FLASH_CTRL_INTR_ENABLE,
     FLASH_CTRL_INTR_TEST,
+    FLASH_CTRL_CTRL_REGWEN,
     FLASH_CTRL_CONTROL,
     FLASH_CTRL_ADDR,
     FLASH_CTRL_REGION_CFG_REGWEN,
@@ -302,32 +318,35 @@
     FLASH_CTRL_OP_STATUS,
     FLASH_CTRL_STATUS,
     FLASH_CTRL_SCRATCH,
-    FLASH_CTRL_FIFO_LVL
+    FLASH_CTRL_FIFO_LVL,
+    FLASH_CTRL_FIFO_RST
   } flash_ctrl_id_e;
 
   // Register width information to check illegal writes
-  parameter logic [3:0] FLASH_CTRL_PERMIT [21] = '{
+  parameter logic [3:0] FLASH_CTRL_PERMIT [23] = '{
     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
-    4'b 1111, // index[ 3] FLASH_CTRL_CONTROL
-    4'b 1111, // index[ 4] FLASH_CTRL_ADDR
-    4'b 0001, // index[ 5] FLASH_CTRL_REGION_CFG_REGWEN
-    4'b 1111, // index[ 6] FLASH_CTRL_MP_REGION_CFG0
-    4'b 1111, // index[ 7] FLASH_CTRL_MP_REGION_CFG1
-    4'b 1111, // index[ 8] FLASH_CTRL_MP_REGION_CFG2
-    4'b 1111, // index[ 9] FLASH_CTRL_MP_REGION_CFG3
-    4'b 1111, // index[10] FLASH_CTRL_MP_REGION_CFG4
-    4'b 1111, // index[11] FLASH_CTRL_MP_REGION_CFG5
-    4'b 1111, // index[12] FLASH_CTRL_MP_REGION_CFG6
-    4'b 1111, // index[13] FLASH_CTRL_MP_REGION_CFG7
-    4'b 0001, // index[14] FLASH_CTRL_DEFAULT_REGION
-    4'b 0001, // index[15] FLASH_CTRL_BANK_CFG_REGWEN
-    4'b 0001, // index[16] FLASH_CTRL_MP_BANK_CFG
-    4'b 0001, // index[17] FLASH_CTRL_OP_STATUS
-    4'b 0111, // index[18] FLASH_CTRL_STATUS
-    4'b 1111, // index[19] FLASH_CTRL_SCRATCH
-    4'b 0011  // index[20] FLASH_CTRL_FIFO_LVL
+    4'b 0001, // index[ 3] FLASH_CTRL_CTRL_REGWEN
+    4'b 1111, // index[ 4] FLASH_CTRL_CONTROL
+    4'b 1111, // index[ 5] FLASH_CTRL_ADDR
+    4'b 0001, // index[ 6] FLASH_CTRL_REGION_CFG_REGWEN
+    4'b 1111, // index[ 7] FLASH_CTRL_MP_REGION_CFG0
+    4'b 1111, // index[ 8] FLASH_CTRL_MP_REGION_CFG1
+    4'b 1111, // index[ 9] FLASH_CTRL_MP_REGION_CFG2
+    4'b 1111, // index[10] FLASH_CTRL_MP_REGION_CFG3
+    4'b 1111, // index[11] FLASH_CTRL_MP_REGION_CFG4
+    4'b 1111, // index[12] FLASH_CTRL_MP_REGION_CFG5
+    4'b 1111, // index[13] FLASH_CTRL_MP_REGION_CFG6
+    4'b 1111, // index[14] FLASH_CTRL_MP_REGION_CFG7
+    4'b 0001, // index[15] FLASH_CTRL_DEFAULT_REGION
+    4'b 0001, // index[16] FLASH_CTRL_BANK_CFG_REGWEN
+    4'b 0001, // index[17] FLASH_CTRL_MP_BANK_CFG
+    4'b 0001, // index[18] FLASH_CTRL_OP_STATUS
+    4'b 0111, // index[19] FLASH_CTRL_STATUS
+    4'b 1111, // index[20] FLASH_CTRL_SCRATCH
+    4'b 0011, // index[21] FLASH_CTRL_FIFO_LVL
+    4'b 0001  // index[22] FLASH_CTRL_FIFO_RST
   };
 endpackage
 
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_top.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_top.sv
index e8a4714..c076989 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_top.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_top.sv
@@ -88,10 +88,10 @@
     reg_steer = 2;       // Default set to register
 
     // TODO: Can below codes be unique case () inside ?
-    if (tl_i.a_address[AW-1:0] >= 84 && tl_i.a_address[AW-1:0] < 88) begin
+    if (tl_i.a_address[AW-1:0] >= 92 && tl_i.a_address[AW-1:0] < 96) begin
       reg_steer = 0;
     end
-    if (tl_i.a_address[AW-1:0] >= 88 && tl_i.a_address[AW-1:0] < 92) begin
+    if (tl_i.a_address[AW-1:0] >= 96 && tl_i.a_address[AW-1:0] < 100) begin
       reg_steer = 1;
     end
   end
@@ -169,6 +169,8 @@
   logic intr_test_op_done_we;
   logic intr_test_op_error_wd;
   logic intr_test_op_error_we;
+  logic ctrl_regwen_qs;
+  logic ctrl_regwen_re;
   logic control_start_qs;
   logic control_start_wd;
   logic control_start_we;
@@ -178,9 +180,9 @@
   logic control_erase_sel_qs;
   logic control_erase_sel_wd;
   logic control_erase_sel_we;
-  logic control_fifo_rst_qs;
-  logic control_fifo_rst_wd;
-  logic control_fifo_rst_we;
+  logic control_partition_sel_qs;
+  logic control_partition_sel_wd;
+  logic control_partition_sel_we;
   logic [11:0] control_num_qs;
   logic [11:0] control_num_wd;
   logic control_num_we;
@@ -208,6 +210,9 @@
   logic [8:0] mp_region_cfg0_size0_qs;
   logic [8:0] mp_region_cfg0_size0_wd;
   logic mp_region_cfg0_size0_we;
+  logic mp_region_cfg0_partition0_qs;
+  logic mp_region_cfg0_partition0_wd;
+  logic mp_region_cfg0_partition0_we;
   logic mp_region_cfg1_en1_qs;
   logic mp_region_cfg1_en1_wd;
   logic mp_region_cfg1_en1_we;
@@ -226,6 +231,9 @@
   logic [8:0] mp_region_cfg1_size1_qs;
   logic [8:0] mp_region_cfg1_size1_wd;
   logic mp_region_cfg1_size1_we;
+  logic mp_region_cfg1_partition1_qs;
+  logic mp_region_cfg1_partition1_wd;
+  logic mp_region_cfg1_partition1_we;
   logic mp_region_cfg2_en2_qs;
   logic mp_region_cfg2_en2_wd;
   logic mp_region_cfg2_en2_we;
@@ -244,6 +252,9 @@
   logic [8:0] mp_region_cfg2_size2_qs;
   logic [8:0] mp_region_cfg2_size2_wd;
   logic mp_region_cfg2_size2_we;
+  logic mp_region_cfg2_partition2_qs;
+  logic mp_region_cfg2_partition2_wd;
+  logic mp_region_cfg2_partition2_we;
   logic mp_region_cfg3_en3_qs;
   logic mp_region_cfg3_en3_wd;
   logic mp_region_cfg3_en3_we;
@@ -262,6 +273,9 @@
   logic [8:0] mp_region_cfg3_size3_qs;
   logic [8:0] mp_region_cfg3_size3_wd;
   logic mp_region_cfg3_size3_we;
+  logic mp_region_cfg3_partition3_qs;
+  logic mp_region_cfg3_partition3_wd;
+  logic mp_region_cfg3_partition3_we;
   logic mp_region_cfg4_en4_qs;
   logic mp_region_cfg4_en4_wd;
   logic mp_region_cfg4_en4_we;
@@ -280,6 +294,9 @@
   logic [8:0] mp_region_cfg4_size4_qs;
   logic [8:0] mp_region_cfg4_size4_wd;
   logic mp_region_cfg4_size4_we;
+  logic mp_region_cfg4_partition4_qs;
+  logic mp_region_cfg4_partition4_wd;
+  logic mp_region_cfg4_partition4_we;
   logic mp_region_cfg5_en5_qs;
   logic mp_region_cfg5_en5_wd;
   logic mp_region_cfg5_en5_we;
@@ -298,6 +315,9 @@
   logic [8:0] mp_region_cfg5_size5_qs;
   logic [8:0] mp_region_cfg5_size5_wd;
   logic mp_region_cfg5_size5_we;
+  logic mp_region_cfg5_partition5_qs;
+  logic mp_region_cfg5_partition5_wd;
+  logic mp_region_cfg5_partition5_we;
   logic mp_region_cfg6_en6_qs;
   logic mp_region_cfg6_en6_wd;
   logic mp_region_cfg6_en6_we;
@@ -316,6 +336,9 @@
   logic [8:0] mp_region_cfg6_size6_qs;
   logic [8:0] mp_region_cfg6_size6_wd;
   logic mp_region_cfg6_size6_we;
+  logic mp_region_cfg6_partition6_qs;
+  logic mp_region_cfg6_partition6_wd;
+  logic mp_region_cfg6_partition6_we;
   logic mp_region_cfg7_en7_qs;
   logic mp_region_cfg7_en7_wd;
   logic mp_region_cfg7_en7_we;
@@ -334,6 +357,9 @@
   logic [8:0] mp_region_cfg7_size7_qs;
   logic [8:0] mp_region_cfg7_size7_wd;
   logic mp_region_cfg7_size7_we;
+  logic mp_region_cfg7_partition7_qs;
+  logic mp_region_cfg7_partition7_wd;
+  logic mp_region_cfg7_partition7_we;
   logic default_region_rd_en_qs;
   logic default_region_rd_en_wd;
   logic default_region_rd_en_we;
@@ -381,6 +407,9 @@
   logic [4:0] fifo_lvl_rd_qs;
   logic [4:0] fifo_lvl_rd_wd;
   logic fifo_lvl_rd_we;
+  logic fifo_rst_qs;
+  logic fifo_rst_wd;
+  logic fifo_rst_we;
 
   // Register instances
   // R[intr_state]: V(False)
@@ -791,6 +820,22 @@
   );
 
 
+  // R[ctrl_regwen]: V(True)
+
+  prim_subreg_ext #(
+    .DW    (1)
+  ) u_ctrl_regwen (
+    .re     (ctrl_regwen_re),
+    .we     (1'b0),
+    .wd     ('0),
+    .d      (hw2reg.ctrl_regwen.d),
+    .qre    (),
+    .qe     (),
+    .q      (),
+    .qs     (ctrl_regwen_qs)
+  );
+
+
   // R[control]: V(False)
 
   //   F[start]: 0:0
@@ -802,8 +847,8 @@
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    // from register interface
-    .we     (control_start_we),
+    // from register interface (qualified with register enable)
+    .we     (control_start_we & ctrl_regwen_qs),
     .wd     (control_start_wd),
 
     // from internal hardware
@@ -828,8 +873,8 @@
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    // from register interface
-    .we     (control_op_we),
+    // from register interface (qualified with register enable)
+    .we     (control_op_we & ctrl_regwen_qs),
     .wd     (control_op_wd),
 
     // from internal hardware
@@ -854,8 +899,8 @@
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    // from register interface
-    .we     (control_erase_sel_we),
+    // from register interface (qualified with register enable)
+    .we     (control_erase_sel_we & ctrl_regwen_qs),
     .wd     (control_erase_sel_wd),
 
     // from internal hardware
@@ -871,18 +916,18 @@
   );
 
 
-  //   F[fifo_rst]: 7:7
+  //   F[partition_sel]: 7:7
   prim_subreg #(
     .DW      (1),
     .SWACCESS("RW"),
     .RESVAL  (1'h0)
-  ) u_control_fifo_rst (
+  ) u_control_partition_sel (
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    // from register interface
-    .we     (control_fifo_rst_we),
-    .wd     (control_fifo_rst_wd),
+    // from register interface (qualified with register enable)
+    .we     (control_partition_sel_we & ctrl_regwen_qs),
+    .wd     (control_partition_sel_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -890,10 +935,10 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.control.fifo_rst.q ),
+    .q      (reg2hw.control.partition_sel.q ),
 
     // to register interface (read)
-    .qs     (control_fifo_rst_qs)
+    .qs     (control_partition_sel_qs)
   );
 
 
@@ -906,8 +951,8 @@
     .clk_i   (clk_i    ),
     .rst_ni  (rst_ni  ),
 
-    // from register interface
-    .we     (control_num_we),
+    // from register interface (qualified with register enable)
+    .we     (control_num_we & ctrl_regwen_qs),
     .wd     (control_num_wd),
 
     // from internal hardware
@@ -1137,6 +1182,32 @@
   );
 
 
+  // F[partition0]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg0_partition0 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg0_partition0_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg0_partition0_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[0].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg0_partition0_qs)
+  );
+
+
   // Subregister 1 of Multireg mp_region_cfg
   // R[mp_region_cfg1]: V(False)
 
@@ -1296,6 +1367,32 @@
   );
 
 
+  // F[partition1]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg1_partition1 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg1_partition1_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg1_partition1_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[1].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg1_partition1_qs)
+  );
+
+
   // Subregister 2 of Multireg mp_region_cfg
   // R[mp_region_cfg2]: V(False)
 
@@ -1455,6 +1552,32 @@
   );
 
 
+  // F[partition2]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg2_partition2 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg2_partition2_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg2_partition2_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[2].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg2_partition2_qs)
+  );
+
+
   // Subregister 3 of Multireg mp_region_cfg
   // R[mp_region_cfg3]: V(False)
 
@@ -1614,6 +1737,32 @@
   );
 
 
+  // F[partition3]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg3_partition3 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg3_partition3_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg3_partition3_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[3].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg3_partition3_qs)
+  );
+
+
   // Subregister 4 of Multireg mp_region_cfg
   // R[mp_region_cfg4]: V(False)
 
@@ -1773,6 +1922,32 @@
   );
 
 
+  // F[partition4]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg4_partition4 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg4_partition4_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg4_partition4_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[4].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg4_partition4_qs)
+  );
+
+
   // Subregister 5 of Multireg mp_region_cfg
   // R[mp_region_cfg5]: V(False)
 
@@ -1932,6 +2107,32 @@
   );
 
 
+  // F[partition5]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg5_partition5 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg5_partition5_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg5_partition5_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[5].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg5_partition5_qs)
+  );
+
+
   // Subregister 6 of Multireg mp_region_cfg
   // R[mp_region_cfg6]: V(False)
 
@@ -2091,6 +2292,32 @@
   );
 
 
+  // F[partition6]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg6_partition6 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg6_partition6_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg6_partition6_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[6].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg6_partition6_qs)
+  );
+
+
   // Subregister 7 of Multireg mp_region_cfg
   // R[mp_region_cfg7]: V(False)
 
@@ -2250,6 +2477,32 @@
   );
 
 
+  // F[partition7]: 25:25
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_mp_region_cfg7_partition7 (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface (qualified with register enable)
+    .we     (mp_region_cfg7_partition7_we & region_cfg_regwen_qs),
+    .wd     (mp_region_cfg7_partition7_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.mp_region_cfg[7].partition.q ),
+
+    // to register interface (read)
+    .qs     (mp_region_cfg7_partition7_qs)
+  );
+
+
 
   // R[default_region]: V(False)
 
@@ -2657,32 +2910,61 @@
   );
 
 
+  // R[fifo_rst]: V(False)
+
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_fifo_rst (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (fifo_rst_we),
+    .wd     (fifo_rst_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.fifo_rst.q ),
+
+    // to register interface (read)
+    .qs     (fifo_rst_qs)
+  );
 
 
-  logic [20:0] addr_hit;
+
+
+  logic [22:0] addr_hit;
   always_comb begin
     addr_hit = '0;
     addr_hit[ 0] = (reg_addr == FLASH_CTRL_INTR_STATE_OFFSET);
     addr_hit[ 1] = (reg_addr == FLASH_CTRL_INTR_ENABLE_OFFSET);
     addr_hit[ 2] = (reg_addr == FLASH_CTRL_INTR_TEST_OFFSET);
-    addr_hit[ 3] = (reg_addr == FLASH_CTRL_CONTROL_OFFSET);
-    addr_hit[ 4] = (reg_addr == FLASH_CTRL_ADDR_OFFSET);
-    addr_hit[ 5] = (reg_addr == FLASH_CTRL_REGION_CFG_REGWEN_OFFSET);
-    addr_hit[ 6] = (reg_addr == FLASH_CTRL_MP_REGION_CFG0_OFFSET);
-    addr_hit[ 7] = (reg_addr == FLASH_CTRL_MP_REGION_CFG1_OFFSET);
-    addr_hit[ 8] = (reg_addr == FLASH_CTRL_MP_REGION_CFG2_OFFSET);
-    addr_hit[ 9] = (reg_addr == FLASH_CTRL_MP_REGION_CFG3_OFFSET);
-    addr_hit[10] = (reg_addr == FLASH_CTRL_MP_REGION_CFG4_OFFSET);
-    addr_hit[11] = (reg_addr == FLASH_CTRL_MP_REGION_CFG5_OFFSET);
-    addr_hit[12] = (reg_addr == FLASH_CTRL_MP_REGION_CFG6_OFFSET);
-    addr_hit[13] = (reg_addr == FLASH_CTRL_MP_REGION_CFG7_OFFSET);
-    addr_hit[14] = (reg_addr == FLASH_CTRL_DEFAULT_REGION_OFFSET);
-    addr_hit[15] = (reg_addr == FLASH_CTRL_BANK_CFG_REGWEN_OFFSET);
-    addr_hit[16] = (reg_addr == FLASH_CTRL_MP_BANK_CFG_OFFSET);
-    addr_hit[17] = (reg_addr == FLASH_CTRL_OP_STATUS_OFFSET);
-    addr_hit[18] = (reg_addr == FLASH_CTRL_STATUS_OFFSET);
-    addr_hit[19] = (reg_addr == FLASH_CTRL_SCRATCH_OFFSET);
-    addr_hit[20] = (reg_addr == FLASH_CTRL_FIFO_LVL_OFFSET);
+    addr_hit[ 3] = (reg_addr == FLASH_CTRL_CTRL_REGWEN_OFFSET);
+    addr_hit[ 4] = (reg_addr == FLASH_CTRL_CONTROL_OFFSET);
+    addr_hit[ 5] = (reg_addr == FLASH_CTRL_ADDR_OFFSET);
+    addr_hit[ 6] = (reg_addr == FLASH_CTRL_REGION_CFG_REGWEN_OFFSET);
+    addr_hit[ 7] = (reg_addr == FLASH_CTRL_MP_REGION_CFG0_OFFSET);
+    addr_hit[ 8] = (reg_addr == FLASH_CTRL_MP_REGION_CFG1_OFFSET);
+    addr_hit[ 9] = (reg_addr == FLASH_CTRL_MP_REGION_CFG2_OFFSET);
+    addr_hit[10] = (reg_addr == FLASH_CTRL_MP_REGION_CFG3_OFFSET);
+    addr_hit[11] = (reg_addr == FLASH_CTRL_MP_REGION_CFG4_OFFSET);
+    addr_hit[12] = (reg_addr == FLASH_CTRL_MP_REGION_CFG5_OFFSET);
+    addr_hit[13] = (reg_addr == FLASH_CTRL_MP_REGION_CFG6_OFFSET);
+    addr_hit[14] = (reg_addr == FLASH_CTRL_MP_REGION_CFG7_OFFSET);
+    addr_hit[15] = (reg_addr == FLASH_CTRL_DEFAULT_REGION_OFFSET);
+    addr_hit[16] = (reg_addr == FLASH_CTRL_BANK_CFG_REGWEN_OFFSET);
+    addr_hit[17] = (reg_addr == FLASH_CTRL_MP_BANK_CFG_OFFSET);
+    addr_hit[18] = (reg_addr == FLASH_CTRL_OP_STATUS_OFFSET);
+    addr_hit[19] = (reg_addr == FLASH_CTRL_STATUS_OFFSET);
+    addr_hit[20] = (reg_addr == FLASH_CTRL_SCRATCH_OFFSET);
+    addr_hit[21] = (reg_addr == FLASH_CTRL_FIFO_LVL_OFFSET);
+    addr_hit[22] = (reg_addr == FLASH_CTRL_FIFO_RST_OFFSET);
   end
 
   assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -2711,6 +2993,8 @@
     if (addr_hit[18] && reg_we && (FLASH_CTRL_PERMIT[18] != (FLASH_CTRL_PERMIT[18] & reg_be))) wr_err = 1'b1 ;
     if (addr_hit[19] && reg_we && (FLASH_CTRL_PERMIT[19] != (FLASH_CTRL_PERMIT[19] & reg_be))) wr_err = 1'b1 ;
     if (addr_hit[20] && reg_we && (FLASH_CTRL_PERMIT[20] != (FLASH_CTRL_PERMIT[20] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[21] && reg_we && (FLASH_CTRL_PERMIT[21] != (FLASH_CTRL_PERMIT[21] & reg_be))) wr_err = 1'b1 ;
+    if (addr_hit[22] && reg_we && (FLASH_CTRL_PERMIT[22] != (FLASH_CTRL_PERMIT[22] & reg_be))) wr_err = 1'b1 ;
   end
 
   assign intr_state_prog_empty_we = addr_hit[0] & reg_we & ~wr_err;
@@ -2767,218 +3051,247 @@
   assign intr_test_op_error_we = addr_hit[2] & reg_we & ~wr_err;
   assign intr_test_op_error_wd = reg_wdata[5];
 
-  assign control_start_we = addr_hit[3] & reg_we & ~wr_err;
+  assign ctrl_regwen_re = addr_hit[3] && reg_re;
+
+  assign control_start_we = addr_hit[4] & reg_we & ~wr_err;
   assign control_start_wd = reg_wdata[0];
 
-  assign control_op_we = addr_hit[3] & reg_we & ~wr_err;
+  assign control_op_we = addr_hit[4] & reg_we & ~wr_err;
   assign control_op_wd = reg_wdata[5:4];
 
-  assign control_erase_sel_we = addr_hit[3] & reg_we & ~wr_err;
+  assign control_erase_sel_we = addr_hit[4] & reg_we & ~wr_err;
   assign control_erase_sel_wd = reg_wdata[6];
 
-  assign control_fifo_rst_we = addr_hit[3] & reg_we & ~wr_err;
-  assign control_fifo_rst_wd = reg_wdata[7];
+  assign control_partition_sel_we = addr_hit[4] & reg_we & ~wr_err;
+  assign control_partition_sel_wd = reg_wdata[7];
 
-  assign control_num_we = addr_hit[3] & reg_we & ~wr_err;
+  assign control_num_we = addr_hit[4] & reg_we & ~wr_err;
   assign control_num_wd = reg_wdata[27:16];
 
-  assign addr_we = addr_hit[4] & reg_we & ~wr_err;
+  assign addr_we = addr_hit[5] & reg_we & ~wr_err;
   assign addr_wd = reg_wdata[31:0];
 
-  assign region_cfg_regwen_we = addr_hit[5] & reg_we & ~wr_err;
+  assign region_cfg_regwen_we = addr_hit[6] & reg_we & ~wr_err;
   assign region_cfg_regwen_wd = reg_wdata[0];
 
-  assign mp_region_cfg0_en0_we = addr_hit[6] & reg_we & ~wr_err;
+  assign mp_region_cfg0_en0_we = addr_hit[7] & reg_we & ~wr_err;
   assign mp_region_cfg0_en0_wd = reg_wdata[0];
 
-  assign mp_region_cfg0_rd_en0_we = addr_hit[6] & reg_we & ~wr_err;
+  assign mp_region_cfg0_rd_en0_we = addr_hit[7] & reg_we & ~wr_err;
   assign mp_region_cfg0_rd_en0_wd = reg_wdata[1];
 
-  assign mp_region_cfg0_prog_en0_we = addr_hit[6] & reg_we & ~wr_err;
+  assign mp_region_cfg0_prog_en0_we = addr_hit[7] & reg_we & ~wr_err;
   assign mp_region_cfg0_prog_en0_wd = reg_wdata[2];
 
-  assign mp_region_cfg0_erase_en0_we = addr_hit[6] & reg_we & ~wr_err;
+  assign mp_region_cfg0_erase_en0_we = addr_hit[7] & reg_we & ~wr_err;
   assign mp_region_cfg0_erase_en0_wd = reg_wdata[3];
 
-  assign mp_region_cfg0_base0_we = addr_hit[6] & reg_we & ~wr_err;
+  assign mp_region_cfg0_base0_we = addr_hit[7] & reg_we & ~wr_err;
   assign mp_region_cfg0_base0_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg0_size0_we = addr_hit[6] & reg_we & ~wr_err;
+  assign mp_region_cfg0_size0_we = addr_hit[7] & reg_we & ~wr_err;
   assign mp_region_cfg0_size0_wd = reg_wdata[24:16];
 
-  assign mp_region_cfg1_en1_we = addr_hit[7] & reg_we & ~wr_err;
+  assign mp_region_cfg0_partition0_we = addr_hit[7] & reg_we & ~wr_err;
+  assign mp_region_cfg0_partition0_wd = reg_wdata[25];
+
+  assign mp_region_cfg1_en1_we = addr_hit[8] & reg_we & ~wr_err;
   assign mp_region_cfg1_en1_wd = reg_wdata[0];
 
-  assign mp_region_cfg1_rd_en1_we = addr_hit[7] & reg_we & ~wr_err;
+  assign mp_region_cfg1_rd_en1_we = addr_hit[8] & reg_we & ~wr_err;
   assign mp_region_cfg1_rd_en1_wd = reg_wdata[1];
 
-  assign mp_region_cfg1_prog_en1_we = addr_hit[7] & reg_we & ~wr_err;
+  assign mp_region_cfg1_prog_en1_we = addr_hit[8] & reg_we & ~wr_err;
   assign mp_region_cfg1_prog_en1_wd = reg_wdata[2];
 
-  assign mp_region_cfg1_erase_en1_we = addr_hit[7] & reg_we & ~wr_err;
+  assign mp_region_cfg1_erase_en1_we = addr_hit[8] & reg_we & ~wr_err;
   assign mp_region_cfg1_erase_en1_wd = reg_wdata[3];
 
-  assign mp_region_cfg1_base1_we = addr_hit[7] & reg_we & ~wr_err;
+  assign mp_region_cfg1_base1_we = addr_hit[8] & reg_we & ~wr_err;
   assign mp_region_cfg1_base1_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg1_size1_we = addr_hit[7] & reg_we & ~wr_err;
+  assign mp_region_cfg1_size1_we = addr_hit[8] & reg_we & ~wr_err;
   assign mp_region_cfg1_size1_wd = reg_wdata[24:16];
 
-  assign mp_region_cfg2_en2_we = addr_hit[8] & reg_we & ~wr_err;
+  assign mp_region_cfg1_partition1_we = addr_hit[8] & reg_we & ~wr_err;
+  assign mp_region_cfg1_partition1_wd = reg_wdata[25];
+
+  assign mp_region_cfg2_en2_we = addr_hit[9] & reg_we & ~wr_err;
   assign mp_region_cfg2_en2_wd = reg_wdata[0];
 
-  assign mp_region_cfg2_rd_en2_we = addr_hit[8] & reg_we & ~wr_err;
+  assign mp_region_cfg2_rd_en2_we = addr_hit[9] & reg_we & ~wr_err;
   assign mp_region_cfg2_rd_en2_wd = reg_wdata[1];
 
-  assign mp_region_cfg2_prog_en2_we = addr_hit[8] & reg_we & ~wr_err;
+  assign mp_region_cfg2_prog_en2_we = addr_hit[9] & reg_we & ~wr_err;
   assign mp_region_cfg2_prog_en2_wd = reg_wdata[2];
 
-  assign mp_region_cfg2_erase_en2_we = addr_hit[8] & reg_we & ~wr_err;
+  assign mp_region_cfg2_erase_en2_we = addr_hit[9] & reg_we & ~wr_err;
   assign mp_region_cfg2_erase_en2_wd = reg_wdata[3];
 
-  assign mp_region_cfg2_base2_we = addr_hit[8] & reg_we & ~wr_err;
+  assign mp_region_cfg2_base2_we = addr_hit[9] & reg_we & ~wr_err;
   assign mp_region_cfg2_base2_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg2_size2_we = addr_hit[8] & reg_we & ~wr_err;
+  assign mp_region_cfg2_size2_we = addr_hit[9] & reg_we & ~wr_err;
   assign mp_region_cfg2_size2_wd = reg_wdata[24:16];
 
-  assign mp_region_cfg3_en3_we = addr_hit[9] & reg_we & ~wr_err;
+  assign mp_region_cfg2_partition2_we = addr_hit[9] & reg_we & ~wr_err;
+  assign mp_region_cfg2_partition2_wd = reg_wdata[25];
+
+  assign mp_region_cfg3_en3_we = addr_hit[10] & reg_we & ~wr_err;
   assign mp_region_cfg3_en3_wd = reg_wdata[0];
 
-  assign mp_region_cfg3_rd_en3_we = addr_hit[9] & reg_we & ~wr_err;
+  assign mp_region_cfg3_rd_en3_we = addr_hit[10] & reg_we & ~wr_err;
   assign mp_region_cfg3_rd_en3_wd = reg_wdata[1];
 
-  assign mp_region_cfg3_prog_en3_we = addr_hit[9] & reg_we & ~wr_err;
+  assign mp_region_cfg3_prog_en3_we = addr_hit[10] & reg_we & ~wr_err;
   assign mp_region_cfg3_prog_en3_wd = reg_wdata[2];
 
-  assign mp_region_cfg3_erase_en3_we = addr_hit[9] & reg_we & ~wr_err;
+  assign mp_region_cfg3_erase_en3_we = addr_hit[10] & reg_we & ~wr_err;
   assign mp_region_cfg3_erase_en3_wd = reg_wdata[3];
 
-  assign mp_region_cfg3_base3_we = addr_hit[9] & reg_we & ~wr_err;
+  assign mp_region_cfg3_base3_we = addr_hit[10] & reg_we & ~wr_err;
   assign mp_region_cfg3_base3_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg3_size3_we = addr_hit[9] & reg_we & ~wr_err;
+  assign mp_region_cfg3_size3_we = addr_hit[10] & reg_we & ~wr_err;
   assign mp_region_cfg3_size3_wd = reg_wdata[24:16];
 
-  assign mp_region_cfg4_en4_we = addr_hit[10] & reg_we & ~wr_err;
+  assign mp_region_cfg3_partition3_we = addr_hit[10] & reg_we & ~wr_err;
+  assign mp_region_cfg3_partition3_wd = reg_wdata[25];
+
+  assign mp_region_cfg4_en4_we = addr_hit[11] & reg_we & ~wr_err;
   assign mp_region_cfg4_en4_wd = reg_wdata[0];
 
-  assign mp_region_cfg4_rd_en4_we = addr_hit[10] & reg_we & ~wr_err;
+  assign mp_region_cfg4_rd_en4_we = addr_hit[11] & reg_we & ~wr_err;
   assign mp_region_cfg4_rd_en4_wd = reg_wdata[1];
 
-  assign mp_region_cfg4_prog_en4_we = addr_hit[10] & reg_we & ~wr_err;
+  assign mp_region_cfg4_prog_en4_we = addr_hit[11] & reg_we & ~wr_err;
   assign mp_region_cfg4_prog_en4_wd = reg_wdata[2];
 
-  assign mp_region_cfg4_erase_en4_we = addr_hit[10] & reg_we & ~wr_err;
+  assign mp_region_cfg4_erase_en4_we = addr_hit[11] & reg_we & ~wr_err;
   assign mp_region_cfg4_erase_en4_wd = reg_wdata[3];
 
-  assign mp_region_cfg4_base4_we = addr_hit[10] & reg_we & ~wr_err;
+  assign mp_region_cfg4_base4_we = addr_hit[11] & reg_we & ~wr_err;
   assign mp_region_cfg4_base4_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg4_size4_we = addr_hit[10] & reg_we & ~wr_err;
+  assign mp_region_cfg4_size4_we = addr_hit[11] & reg_we & ~wr_err;
   assign mp_region_cfg4_size4_wd = reg_wdata[24:16];
 
-  assign mp_region_cfg5_en5_we = addr_hit[11] & reg_we & ~wr_err;
+  assign mp_region_cfg4_partition4_we = addr_hit[11] & reg_we & ~wr_err;
+  assign mp_region_cfg4_partition4_wd = reg_wdata[25];
+
+  assign mp_region_cfg5_en5_we = addr_hit[12] & reg_we & ~wr_err;
   assign mp_region_cfg5_en5_wd = reg_wdata[0];
 
-  assign mp_region_cfg5_rd_en5_we = addr_hit[11] & reg_we & ~wr_err;
+  assign mp_region_cfg5_rd_en5_we = addr_hit[12] & reg_we & ~wr_err;
   assign mp_region_cfg5_rd_en5_wd = reg_wdata[1];
 
-  assign mp_region_cfg5_prog_en5_we = addr_hit[11] & reg_we & ~wr_err;
+  assign mp_region_cfg5_prog_en5_we = addr_hit[12] & reg_we & ~wr_err;
   assign mp_region_cfg5_prog_en5_wd = reg_wdata[2];
 
-  assign mp_region_cfg5_erase_en5_we = addr_hit[11] & reg_we & ~wr_err;
+  assign mp_region_cfg5_erase_en5_we = addr_hit[12] & reg_we & ~wr_err;
   assign mp_region_cfg5_erase_en5_wd = reg_wdata[3];
 
-  assign mp_region_cfg5_base5_we = addr_hit[11] & reg_we & ~wr_err;
+  assign mp_region_cfg5_base5_we = addr_hit[12] & reg_we & ~wr_err;
   assign mp_region_cfg5_base5_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg5_size5_we = addr_hit[11] & reg_we & ~wr_err;
+  assign mp_region_cfg5_size5_we = addr_hit[12] & reg_we & ~wr_err;
   assign mp_region_cfg5_size5_wd = reg_wdata[24:16];
 
-  assign mp_region_cfg6_en6_we = addr_hit[12] & reg_we & ~wr_err;
+  assign mp_region_cfg5_partition5_we = addr_hit[12] & reg_we & ~wr_err;
+  assign mp_region_cfg5_partition5_wd = reg_wdata[25];
+
+  assign mp_region_cfg6_en6_we = addr_hit[13] & reg_we & ~wr_err;
   assign mp_region_cfg6_en6_wd = reg_wdata[0];
 
-  assign mp_region_cfg6_rd_en6_we = addr_hit[12] & reg_we & ~wr_err;
+  assign mp_region_cfg6_rd_en6_we = addr_hit[13] & reg_we & ~wr_err;
   assign mp_region_cfg6_rd_en6_wd = reg_wdata[1];
 
-  assign mp_region_cfg6_prog_en6_we = addr_hit[12] & reg_we & ~wr_err;
+  assign mp_region_cfg6_prog_en6_we = addr_hit[13] & reg_we & ~wr_err;
   assign mp_region_cfg6_prog_en6_wd = reg_wdata[2];
 
-  assign mp_region_cfg6_erase_en6_we = addr_hit[12] & reg_we & ~wr_err;
+  assign mp_region_cfg6_erase_en6_we = addr_hit[13] & reg_we & ~wr_err;
   assign mp_region_cfg6_erase_en6_wd = reg_wdata[3];
 
-  assign mp_region_cfg6_base6_we = addr_hit[12] & reg_we & ~wr_err;
+  assign mp_region_cfg6_base6_we = addr_hit[13] & reg_we & ~wr_err;
   assign mp_region_cfg6_base6_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg6_size6_we = addr_hit[12] & reg_we & ~wr_err;
+  assign mp_region_cfg6_size6_we = addr_hit[13] & reg_we & ~wr_err;
   assign mp_region_cfg6_size6_wd = reg_wdata[24:16];
 
-  assign mp_region_cfg7_en7_we = addr_hit[13] & reg_we & ~wr_err;
+  assign mp_region_cfg6_partition6_we = addr_hit[13] & reg_we & ~wr_err;
+  assign mp_region_cfg6_partition6_wd = reg_wdata[25];
+
+  assign mp_region_cfg7_en7_we = addr_hit[14] & reg_we & ~wr_err;
   assign mp_region_cfg7_en7_wd = reg_wdata[0];
 
-  assign mp_region_cfg7_rd_en7_we = addr_hit[13] & reg_we & ~wr_err;
+  assign mp_region_cfg7_rd_en7_we = addr_hit[14] & reg_we & ~wr_err;
   assign mp_region_cfg7_rd_en7_wd = reg_wdata[1];
 
-  assign mp_region_cfg7_prog_en7_we = addr_hit[13] & reg_we & ~wr_err;
+  assign mp_region_cfg7_prog_en7_we = addr_hit[14] & reg_we & ~wr_err;
   assign mp_region_cfg7_prog_en7_wd = reg_wdata[2];
 
-  assign mp_region_cfg7_erase_en7_we = addr_hit[13] & reg_we & ~wr_err;
+  assign mp_region_cfg7_erase_en7_we = addr_hit[14] & reg_we & ~wr_err;
   assign mp_region_cfg7_erase_en7_wd = reg_wdata[3];
 
-  assign mp_region_cfg7_base7_we = addr_hit[13] & reg_we & ~wr_err;
+  assign mp_region_cfg7_base7_we = addr_hit[14] & reg_we & ~wr_err;
   assign mp_region_cfg7_base7_wd = reg_wdata[12:4];
 
-  assign mp_region_cfg7_size7_we = addr_hit[13] & reg_we & ~wr_err;
+  assign mp_region_cfg7_size7_we = addr_hit[14] & reg_we & ~wr_err;
   assign mp_region_cfg7_size7_wd = reg_wdata[24:16];
 
-  assign default_region_rd_en_we = addr_hit[14] & reg_we & ~wr_err;
+  assign mp_region_cfg7_partition7_we = addr_hit[14] & reg_we & ~wr_err;
+  assign mp_region_cfg7_partition7_wd = reg_wdata[25];
+
+  assign default_region_rd_en_we = addr_hit[15] & reg_we & ~wr_err;
   assign default_region_rd_en_wd = reg_wdata[0];
 
-  assign default_region_prog_en_we = addr_hit[14] & reg_we & ~wr_err;
+  assign default_region_prog_en_we = addr_hit[15] & reg_we & ~wr_err;
   assign default_region_prog_en_wd = reg_wdata[1];
 
-  assign default_region_erase_en_we = addr_hit[14] & reg_we & ~wr_err;
+  assign default_region_erase_en_we = addr_hit[15] & reg_we & ~wr_err;
   assign default_region_erase_en_wd = reg_wdata[2];
 
-  assign bank_cfg_regwen_we = addr_hit[15] & reg_we & ~wr_err;
+  assign bank_cfg_regwen_we = addr_hit[16] & reg_we & ~wr_err;
   assign bank_cfg_regwen_wd = reg_wdata[0];
 
-  assign mp_bank_cfg_erase_en0_we = addr_hit[16] & reg_we & ~wr_err;
+  assign mp_bank_cfg_erase_en0_we = addr_hit[17] & reg_we & ~wr_err;
   assign mp_bank_cfg_erase_en0_wd = reg_wdata[0];
 
-  assign mp_bank_cfg_erase_en1_we = addr_hit[16] & reg_we & ~wr_err;
+  assign mp_bank_cfg_erase_en1_we = addr_hit[17] & reg_we & ~wr_err;
   assign mp_bank_cfg_erase_en1_wd = reg_wdata[1];
 
-  assign op_status_done_we = addr_hit[17] & reg_we & ~wr_err;
+  assign op_status_done_we = addr_hit[18] & reg_we & ~wr_err;
   assign op_status_done_wd = reg_wdata[0];
 
-  assign op_status_err_we = addr_hit[17] & reg_we & ~wr_err;
+  assign op_status_err_we = addr_hit[18] & reg_we & ~wr_err;
   assign op_status_err_wd = reg_wdata[1];
 
-  assign status_rd_full_re = addr_hit[18] && reg_re;
+  assign status_rd_full_re = addr_hit[19] && reg_re;
 
-  assign status_rd_empty_re = addr_hit[18] && reg_re;
+  assign status_rd_empty_re = addr_hit[19] && reg_re;
 
-  assign status_prog_full_re = addr_hit[18] && reg_re;
+  assign status_prog_full_re = addr_hit[19] && reg_re;
 
-  assign status_prog_empty_re = addr_hit[18] && reg_re;
+  assign status_prog_empty_re = addr_hit[19] && reg_re;
 
-  assign status_init_wip_re = addr_hit[18] && reg_re;
+  assign status_init_wip_re = addr_hit[19] && reg_re;
 
-  assign status_error_page_re = addr_hit[18] && reg_re;
+  assign status_error_page_re = addr_hit[19] && reg_re;
 
-  assign status_error_bank_re = addr_hit[18] && reg_re;
+  assign status_error_bank_re = addr_hit[19] && reg_re;
 
-  assign scratch_we = addr_hit[19] & reg_we & ~wr_err;
+  assign scratch_we = addr_hit[20] & reg_we & ~wr_err;
   assign scratch_wd = reg_wdata[31:0];
 
-  assign fifo_lvl_prog_we = addr_hit[20] & reg_we & ~wr_err;
+  assign fifo_lvl_prog_we = addr_hit[21] & reg_we & ~wr_err;
   assign fifo_lvl_prog_wd = reg_wdata[4:0];
 
-  assign fifo_lvl_rd_we = addr_hit[20] & reg_we & ~wr_err;
+  assign fifo_lvl_rd_we = addr_hit[21] & reg_we & ~wr_err;
   assign fifo_lvl_rd_wd = reg_wdata[12:8];
 
+  assign fifo_rst_we = addr_hit[22] & reg_we & ~wr_err;
+  assign fifo_rst_wd = reg_wdata[0];
+
   // Read data return
   always_comb begin
     reg_rdata_next = '0;
@@ -3011,114 +3324,126 @@
       end
 
       addr_hit[3]: begin
-        reg_rdata_next[0] = control_start_qs;
-        reg_rdata_next[5:4] = control_op_qs;
-        reg_rdata_next[6] = control_erase_sel_qs;
-        reg_rdata_next[7] = control_fifo_rst_qs;
-        reg_rdata_next[27:16] = control_num_qs;
+        reg_rdata_next[0] = ctrl_regwen_qs;
       end
 
       addr_hit[4]: begin
-        reg_rdata_next[31:0] = addr_qs;
+        reg_rdata_next[0] = control_start_qs;
+        reg_rdata_next[5:4] = control_op_qs;
+        reg_rdata_next[6] = control_erase_sel_qs;
+        reg_rdata_next[7] = control_partition_sel_qs;
+        reg_rdata_next[27:16] = control_num_qs;
       end
 
       addr_hit[5]: begin
-        reg_rdata_next[0] = region_cfg_regwen_qs;
+        reg_rdata_next[31:0] = addr_qs;
       end
 
       addr_hit[6]: begin
+        reg_rdata_next[0] = region_cfg_regwen_qs;
+      end
+
+      addr_hit[7]: begin
         reg_rdata_next[0] = mp_region_cfg0_en0_qs;
         reg_rdata_next[1] = mp_region_cfg0_rd_en0_qs;
         reg_rdata_next[2] = mp_region_cfg0_prog_en0_qs;
         reg_rdata_next[3] = mp_region_cfg0_erase_en0_qs;
         reg_rdata_next[12:4] = mp_region_cfg0_base0_qs;
         reg_rdata_next[24:16] = mp_region_cfg0_size0_qs;
+        reg_rdata_next[25] = mp_region_cfg0_partition0_qs;
       end
 
-      addr_hit[7]: begin
+      addr_hit[8]: begin
         reg_rdata_next[0] = mp_region_cfg1_en1_qs;
         reg_rdata_next[1] = mp_region_cfg1_rd_en1_qs;
         reg_rdata_next[2] = mp_region_cfg1_prog_en1_qs;
         reg_rdata_next[3] = mp_region_cfg1_erase_en1_qs;
         reg_rdata_next[12:4] = mp_region_cfg1_base1_qs;
         reg_rdata_next[24:16] = mp_region_cfg1_size1_qs;
+        reg_rdata_next[25] = mp_region_cfg1_partition1_qs;
       end
 
-      addr_hit[8]: begin
+      addr_hit[9]: begin
         reg_rdata_next[0] = mp_region_cfg2_en2_qs;
         reg_rdata_next[1] = mp_region_cfg2_rd_en2_qs;
         reg_rdata_next[2] = mp_region_cfg2_prog_en2_qs;
         reg_rdata_next[3] = mp_region_cfg2_erase_en2_qs;
         reg_rdata_next[12:4] = mp_region_cfg2_base2_qs;
         reg_rdata_next[24:16] = mp_region_cfg2_size2_qs;
+        reg_rdata_next[25] = mp_region_cfg2_partition2_qs;
       end
 
-      addr_hit[9]: begin
+      addr_hit[10]: begin
         reg_rdata_next[0] = mp_region_cfg3_en3_qs;
         reg_rdata_next[1] = mp_region_cfg3_rd_en3_qs;
         reg_rdata_next[2] = mp_region_cfg3_prog_en3_qs;
         reg_rdata_next[3] = mp_region_cfg3_erase_en3_qs;
         reg_rdata_next[12:4] = mp_region_cfg3_base3_qs;
         reg_rdata_next[24:16] = mp_region_cfg3_size3_qs;
+        reg_rdata_next[25] = mp_region_cfg3_partition3_qs;
       end
 
-      addr_hit[10]: begin
+      addr_hit[11]: begin
         reg_rdata_next[0] = mp_region_cfg4_en4_qs;
         reg_rdata_next[1] = mp_region_cfg4_rd_en4_qs;
         reg_rdata_next[2] = mp_region_cfg4_prog_en4_qs;
         reg_rdata_next[3] = mp_region_cfg4_erase_en4_qs;
         reg_rdata_next[12:4] = mp_region_cfg4_base4_qs;
         reg_rdata_next[24:16] = mp_region_cfg4_size4_qs;
+        reg_rdata_next[25] = mp_region_cfg4_partition4_qs;
       end
 
-      addr_hit[11]: begin
+      addr_hit[12]: begin
         reg_rdata_next[0] = mp_region_cfg5_en5_qs;
         reg_rdata_next[1] = mp_region_cfg5_rd_en5_qs;
         reg_rdata_next[2] = mp_region_cfg5_prog_en5_qs;
         reg_rdata_next[3] = mp_region_cfg5_erase_en5_qs;
         reg_rdata_next[12:4] = mp_region_cfg5_base5_qs;
         reg_rdata_next[24:16] = mp_region_cfg5_size5_qs;
+        reg_rdata_next[25] = mp_region_cfg5_partition5_qs;
       end
 
-      addr_hit[12]: begin
+      addr_hit[13]: begin
         reg_rdata_next[0] = mp_region_cfg6_en6_qs;
         reg_rdata_next[1] = mp_region_cfg6_rd_en6_qs;
         reg_rdata_next[2] = mp_region_cfg6_prog_en6_qs;
         reg_rdata_next[3] = mp_region_cfg6_erase_en6_qs;
         reg_rdata_next[12:4] = mp_region_cfg6_base6_qs;
         reg_rdata_next[24:16] = mp_region_cfg6_size6_qs;
+        reg_rdata_next[25] = mp_region_cfg6_partition6_qs;
       end
 
-      addr_hit[13]: begin
+      addr_hit[14]: begin
         reg_rdata_next[0] = mp_region_cfg7_en7_qs;
         reg_rdata_next[1] = mp_region_cfg7_rd_en7_qs;
         reg_rdata_next[2] = mp_region_cfg7_prog_en7_qs;
         reg_rdata_next[3] = mp_region_cfg7_erase_en7_qs;
         reg_rdata_next[12:4] = mp_region_cfg7_base7_qs;
         reg_rdata_next[24:16] = mp_region_cfg7_size7_qs;
+        reg_rdata_next[25] = mp_region_cfg7_partition7_qs;
       end
 
-      addr_hit[14]: begin
+      addr_hit[15]: begin
         reg_rdata_next[0] = default_region_rd_en_qs;
         reg_rdata_next[1] = default_region_prog_en_qs;
         reg_rdata_next[2] = default_region_erase_en_qs;
       end
 
-      addr_hit[15]: begin
+      addr_hit[16]: begin
         reg_rdata_next[0] = bank_cfg_regwen_qs;
       end
 
-      addr_hit[16]: begin
+      addr_hit[17]: begin
         reg_rdata_next[0] = mp_bank_cfg_erase_en0_qs;
         reg_rdata_next[1] = mp_bank_cfg_erase_en1_qs;
       end
 
-      addr_hit[17]: begin
+      addr_hit[18]: begin
         reg_rdata_next[0] = op_status_done_qs;
         reg_rdata_next[1] = op_status_err_qs;
       end
 
-      addr_hit[18]: begin
+      addr_hit[19]: begin
         reg_rdata_next[0] = status_rd_full_qs;
         reg_rdata_next[1] = status_rd_empty_qs;
         reg_rdata_next[2] = status_prog_full_qs;
@@ -3128,15 +3453,19 @@
         reg_rdata_next[17] = status_error_bank_qs;
       end
 
-      addr_hit[19]: begin
+      addr_hit[20]: begin
         reg_rdata_next[31:0] = scratch_qs;
       end
 
-      addr_hit[20]: begin
+      addr_hit[21]: begin
         reg_rdata_next[4:0] = fifo_lvl_prog_qs;
         reg_rdata_next[12:8] = fifo_lvl_rd_qs;
       end
 
+      addr_hit[22]: begin
+        reg_rdata_next[0] = fifo_rst_qs;
+      end
+
       default: begin
         reg_rdata_next = '1;
       end
diff --git a/hw/ip/flash_ctrl/rtl/flash_mp.sv b/hw/ip/flash_ctrl/rtl/flash_mp.sv
index f226d8c..8c3e9c5 100644
--- a/hw/ip/flash_ctrl/rtl/flash_mp.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_mp.sv
@@ -7,7 +7,7 @@
 
 `include "prim_assert.sv"
 
-module flash_mp #(
+module flash_mp import flash_ctrl_pkg::*; import flash_ctrl_reg_pkg::*; #(
   parameter int MpRegions = 8,
   parameter int NumBanks = 2,
   parameter int AllPagesW = 16,
@@ -18,12 +18,13 @@
   input rst_ni,
 
   // configuration from sw
-  input flash_ctrl_reg_pkg::flash_ctrl_reg2hw_mp_region_cfg_mreg_t [TotalRegions-1:0] region_cfgs_i,
-  input flash_ctrl_reg_pkg::flash_ctrl_reg2hw_mp_bank_cfg_mreg_t [NumBanks-1:0] bank_cfgs_i,
+  input flash_ctrl_reg2hw_mp_region_cfg_mreg_t [TotalRegions-1:0] region_cfgs_i,
+  input flash_ctrl_reg2hw_mp_bank_cfg_mreg_t [NumBanks-1:0] bank_cfgs_i,
 
   // interface signals to/from *_ctrl
   input req_i,
   input [AllPagesW-1:0] req_addr_i,
+  input req_part_i,
   input addr_ovfl_i,
   input [BankW-1:0] req_bk_i,
   input rd_i,
@@ -48,7 +49,10 @@
   input erase_done_i
 
 );
-  import flash_ctrl_pkg::*;
+
+
+  // Address range checks
+  localparam int LastValidInfoPage = InfosPerBank - 1;
 
   // There could be multiple region matches due to region overlap
   logic [AllPagesW-1:0] region_end[TotalRegions];
@@ -73,8 +77,11 @@
   always_comb begin
     for (int unsigned i = 0; i < TotalRegions; i++) begin: region_comps
       region_end[i] = region_cfgs_i[i].base.q + region_cfgs_i[i].size.q;
+
+      // region matches if address within range and if the partition matches
       region_match[i] = req_addr_i >= region_cfgs_i[i].base.q &
                         req_addr_i <  region_end[i] &
+                        req_part_i == region_cfgs_i[i].partition.q &
                         req_i;
 
       rd_en[i] = region_cfgs_i[i].en.q & region_cfgs_i[i].rd_en.q & region_sel[i];
@@ -84,12 +91,29 @@
   end
 
   // check for bank erase
+  // bank erase allowed for only data partition
   always_comb begin
     for (int unsigned i = 0; i < NumBanks; i++) begin: bank_comps
-      bk_erase_en[i] = (req_bk_i == i) & bank_cfgs_i[i].q;
+      bk_erase_en[i] = (req_bk_i == i) & bank_cfgs_i[i].q &
+                       (req_part_i == DataPart);
     end
   end
 
+  logic invalid_info_access, invalid_info_erase, invalid_info_txn;
+
+  // invalid info page access
+  assign invalid_info_access = req_i &
+                               (req_part_i == InfoPart) &
+                               (rd_i | prog_i | pg_erase_i) &
+                               (req_addr_i[0 +: PageW] > LastValidInfoPage);
+
+  // invalid info page erase
+  assign invalid_info_erase  = req_i & bk_erase_i &
+                               (req_part_i == InfoPart);
+
+  assign invalid_info_txn    = invalid_info_access | invalid_info_erase;
+
+
   assign final_rd_en = rd_i & |rd_en;
   assign final_prog_en = prog_i & |prog_en;
   assign final_pg_erase_en = pg_erase_i & |pg_erase_en;
@@ -105,8 +129,8 @@
   logic txn_ens;
   logic no_allowed_txn;
   assign txn_ens = final_rd_en | final_prog_en | final_pg_erase_en | final_bk_erase_en;
-  // if incoming address overflowed or no transaction enbales, error back
-  assign no_allowed_txn = req_i & (addr_ovfl_i | ~txn_ens);
+  // if incoming address overflowed or is invalid or no transaction enables, error back
+  assign no_allowed_txn = req_i & (addr_ovfl_i | invalid_info_txn | ~txn_ens);
 
   // return done and error the next cycle
   always_ff @(posedge clk_i or negedge rst_ni) begin
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy.sv b/hw/ip/flash_ctrl/rtl/flash_phy.sv
index e794c68..a75e257 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy.sv
@@ -18,8 +18,8 @@
   output logic host_req_rdy_o,
   output logic host_req_done_o,
   output logic [BusWidth-1:0] host_rdata_o,
-  input flash_ctrl_pkg::flash_req_t flash_ctrl_i,
-  output flash_ctrl_pkg::flash_rsp_t flash_ctrl_o
+  input flash_req_t flash_ctrl_i,
+  output flash_rsp_t flash_ctrl_o
 );
 
   // Flash macro outstanding refers to how many reads we allow a macro to move ahead of an
@@ -130,6 +130,7 @@
       .prog_i(flash_ctrl_i.prog),
       .pg_erase_i(flash_ctrl_i.pg_erase),
       .bk_erase_i(flash_ctrl_i.bk_erase),
+      .part_i(flash_ctrl_i.part),
       .addr_i(flash_ctrl_i.addr[0 +: BankAddrW]),
       .prog_data_i(flash_ctrl_i.prog_data),
       .host_req_rdy_o(host_req_rdy[bank]),
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
index 9538023..a04ed41 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
@@ -12,24 +12,25 @@
 module flash_phy_core import flash_phy_pkg::*; #(
   parameter bit SkipInit     = 1   // this is an option to reset flash to all F's at reset
 ) (
-  input                        clk_i,
-  input                        rst_ni,
-  input                        host_req_i, // host request - read only
-  input [BankAddrW-1:0]        host_addr_i,
-  input                        req_i,      // controller request
-  input                        rd_i,
-  input                        prog_i,
-  input                        pg_erase_i,
-  input                        bk_erase_i,
-  input [BankAddrW-1:0]        addr_i,
-  input [BusWidth-1:0]         prog_data_i,
-  output logic                 host_req_rdy_o,
-  output logic                 host_req_done_o,
-  output logic                 rd_done_o,
-  output logic                 prog_done_o,
-  output logic                 erase_done_o,
-  output logic [BusWidth-1:0]  rd_data_o,
-  output logic                 init_busy_o
+  input                              clk_i,
+  input                              rst_ni,
+  input                              host_req_i, // host request - read only
+  input [BankAddrW-1:0]              host_addr_i,
+  input                              req_i,      // controller request
+  input                              rd_i,
+  input                              prog_i,
+  input                              pg_erase_i,
+  input                              bk_erase_i,
+  input flash_ctrl_pkg::flash_part_e part_i,
+  input [BankAddrW-1:0]              addr_i,
+  input [BusWidth-1:0]               prog_data_i,
+  output logic                       host_req_rdy_o,
+  output logic                       host_req_done_o,
+  output logic                       rd_done_o,
+  output logic                       prog_done_o,
+  output logic                       erase_done_o,
+  output logic [BusWidth-1:0]        rd_data_o,
+  output logic                       init_busy_o
 );
 
   typedef enum logic [1:0] {
@@ -58,6 +59,7 @@
 
   // interface with flash macro
   logic [BankAddrW-1:0] muxed_addr;
+  flash_ctrl_pkg::flash_part_e muxed_part;
 
   // entire read stage is idle, inclusive of all stages
   logic rd_stage_idle;
@@ -146,6 +148,7 @@
   end
 
   assign muxed_addr = host_sel ? host_addr_i : addr_i;
+  assign muxed_part = host_sel ? flash_ctrl_pkg::DataPart : part_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);
@@ -165,6 +168,7 @@
     .pg_erase_i(reqs[PhyPgErase]),
     .bk_erase_i(reqs[PhyBkErase]),
     .addr_i(muxed_addr),
+    .part_i(muxed_part),
     .rdy_o(rd_stage_rdy),
     .data_valid_o(rd_stage_data_valid),
     .data_o(rd_data_o),
@@ -211,6 +215,7 @@
   // The size of a page is fixed.  However, depending on the sizing of the word,
   // the number of words within a page will change.
   prim_flash #(
+    .InfosPerBank(InfosPerBank),
     .PagesPerBank(PagesPerBank),
     .WordsPerPage(WordsPerPage / WidthMultiple),
     .DataWidth(DataWidth),
@@ -224,6 +229,7 @@
     .bk_erase_i(reqs[PhyBkErase]),
     //.addr_i(muxed_addr[0 +: PageW + WordW]),
     .addr_i(muxed_addr[BankAddrW-1:LsbAddrBit]),
+    .part_i(muxed_part),
     .prog_data_i(prog_data),
     .ack_o(ack),
     .rd_data_o(flash_rdata),
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
index 2dd6fd8..1d2100e 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
@@ -7,6 +7,7 @@
 
 package flash_phy_pkg;
   parameter int NumBanks     = flash_ctrl_pkg::NumBanks;
+  parameter int InfosPerBank = flash_ctrl_pkg::InfosPerBank;
   parameter int PagesPerBank = flash_ctrl_pkg::PagesPerBank;
   parameter int WordsPerPage = flash_ctrl_pkg::WordsPerPage;
   parameter int BytesPerWord = flash_ctrl_pkg::BytesPerWord;
@@ -56,6 +57,7 @@
   typedef struct packed {
     logic [DataWidth-1:0] data;
     logic [PrimFlashAddrW-1:0] addr; // all address bits preserved to pick return portion
+    logic part;
     rd_buf_attr_e attr;
   } rd_buf_t;
 
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
index acb9127..b6016ce 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_rd.sv
@@ -23,6 +23,7 @@
   input pg_erase_i,
   input bk_erase_i,
   input [BankAddrW-1:0] addr_i,
+  input flash_ctrl_pkg::flash_part_e part_i,
   output logic rdy_o,
   output logic data_valid_o,
   output logic [BusWidth-1:0] data_o,
@@ -108,19 +109,32 @@
 
   // do not attempt to generate match unless the transaction is relevant
   for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_match
-    assign buf_match[i] = req_i & (buf_valid[i] | buf_wip[i]) &
-                          read_buf[i].addr == addr_i[BankAddrW-1:LsbAddrBit];
+    assign buf_match[i] = req_i &
+                          (buf_valid[i] | buf_wip[i]) &
+                          (read_buf[i].addr == addr_i[BankAddrW-1:LsbAddrBit]) &
+                          (read_buf[i].part == part_i);
 
     // A data hazard should never happen to a wip buffer because it implies
     // that a read is in progress, so a hazard operation cannot start.
     // If bank erase, all buffers must be flushed.
     // If page erase, only if the buffer lands in the same page.
     // If program, only if it's the same flash word.
+
+    logic part_match;
+    logic word_addr_match;
+    logic page_addr_match;
+
+    assign part_match      = read_buf[i].part == part_i;
+    assign word_addr_match = (read_buf[i].addr == addr_i[BankAddrW-1:LsbAddrBit]) &
+                             part_match;
+
+    assign page_addr_match = (read_buf[i].addr[FlashWordsW +: PageW] == addr_i[WordW +: PageW]) &
+                             part_match;
+
     assign data_hazard[i] = buf_valid[i] &
                             (bk_erase_i |
-                            (prog_i & read_buf[i].addr == addr_i[BankAddrW-1:LsbAddrBit]) |
-                            (pg_erase_i & read_buf[i].addr[FlashWordsW +: PageW] ==
-                            addr_i[WordW +: PageW]));
+                            (prog_i & word_addr_match) |
+                            (pg_erase_i & page_addr_match));
 
   end
 
@@ -141,6 +155,7 @@
       .update_i(update[i]),
       .wipe_i(data_hazard[i]),
       .addr_i(addr_i[BankAddrW-1:LsbAddrBit]),
+      .part_i(part_i),
       .data_i(data_i),
       .out_o(read_buf[i])
     );
@@ -247,7 +262,7 @@
   // match in flash response when allocated buffer is the same as top of response fifo
   assign flash_rsp_match = rsp_fifo_vld & rd_done & (rsp_fifo_rdata.buf_sel == alloc_q);
 
-  // match in buf response when there is a valie buffer that is the same as top of response fifo
+  // match in buf response when there is a valid buffer that is the same as top of response fifo
   for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_rsp_match
     assign buf_rsp_match[i] = rsp_fifo_vld & (rsp_fifo_rdata.buf_sel[i] & buf_valid[i]);
   end
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_rd_buffers.sv b/hw/ip/flash_ctrl/rtl/flash_phy_rd_buffers.sv
index ba53685..3c621a5 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_rd_buffers.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_rd_buffers.sv
@@ -26,6 +26,7 @@
   input update_i,
   input wipe_i,
   input [PrimFlashAddrW-1:0] addr_i,
+  input part_i,
   input [DataWidth-1:0] data_i,
   output rd_buf_t out_o
 );
@@ -34,11 +35,13 @@
     if (!rst_ni) begin
       out_o.data <= '0;
       out_o.addr <= '0;
+      out_o.part <= flash_ctrl_pkg::DataPart;
       out_o.attr <= Invalid;
     end else if (wipe_i) begin
       out_o.attr <= Invalid;
     end else if (alloc_i) begin
       out_o.addr <= addr_i;
+      out_o.part <= part_i;
       out_o.attr <= Wip;
     end else if (update_i) begin
       out_o.data <= data_i;
diff --git a/hw/ip/prim_generic/prim_generic_flash.core b/hw/ip/prim_generic/prim_generic_flash.core
index 9e9f741..5d2d0b9 100644
--- a/hw/ip/prim_generic/prim_generic_flash.core
+++ b/hw/ip/prim_generic/prim_generic_flash.core
@@ -9,6 +9,7 @@
   files_rtl:
     depend:
       - lowrisc:prim:ram_1p
+      - lowrisc:ip:flash_ctrl_pkg
     files:
       - rtl/prim_generic_flash.sv
     file_type: systemVerilogSource
diff --git a/hw/ip/prim_generic/rtl/prim_generic_flash.sv b/hw/ip/prim_generic/rtl/prim_generic_flash.sv
index 682729c..1edbe8d 100644
--- a/hw/ip/prim_generic/rtl/prim_generic_flash.sv
+++ b/hw/ip/prim_generic/rtl/prim_generic_flash.sv
@@ -6,7 +6,8 @@
 //
 
 module prim_generic_flash #(
-  parameter int PagesPerBank = 256, // pages per bank
+  parameter int InfosPerBank = 1,   // info pages per bank
+  parameter int PagesPerBank = 256, // data pages per bank
   parameter int WordsPerPage = 256, // words per page
   parameter int DataWidth   = 32,   // bits per word
   parameter bit SkipInit = 1,       // this is an option to reset flash to all F's at reset
@@ -16,17 +17,18 @@
   localparam int WordW = $clog2(WordsPerPage),
   localparam int AddrW = PageW + WordW
 ) (
-  input                        clk_i,
-  input                        rst_ni,
-  input                        rd_i,
-  input                        prog_i,
-  input                        pg_erase_i,
-  input                        bk_erase_i,
-  input [AddrW-1:0]            addr_i,
-  input [DataWidth-1:0]        prog_data_i,
-  output logic                 ack_o,
-  output logic [DataWidth-1:0] rd_data_o,
-  output logic                 init_busy_o
+  input                              clk_i,
+  input                              rst_ni,
+  input                              rd_i,
+  input                              prog_i,
+  input                              pg_erase_i,
+  input                              bk_erase_i,
+  input [AddrW-1:0]                  addr_i,
+  input flash_ctrl_pkg::flash_part_e part_i,
+  input [DataWidth-1:0]              prog_data_i,
+  output logic                       ack_o,
+  output logic [DataWidth-1:0]       rd_data_o,
+  output logic                       init_busy_o
 );
 
   // Emulated flash macro values
@@ -37,6 +39,8 @@
 
   // Locally derived values
   localparam int WordsPerBank  = PagesPerBank * WordsPerPage;
+  localparam int WordsPerInfoBank = InfosPerBank * WordsPerPage;
+  localparam int InfoAddrW = $clog2(WordsPerInfoBank);
 
   typedef enum logic [2:0] {
     StReset    = 'h0,
@@ -59,18 +63,21 @@
   logic                     mem_req;
   logic                     mem_wr;
   logic [AddrW-1:0]         mem_addr;
+  flash_ctrl_pkg::flash_part_e mem_part;
   logic [DataWidth-1:0]     held_rdata;
   logic [DataWidth-1:0]     held_wdata;
   logic [DataWidth-1:0]     mem_wdata;
   logic                     hold_cmd;
   logic [AddrW-1:0]         held_addr;
+  flash_ctrl_pkg::flash_part_e held_part;
 
   // insert a fifo here to break the large fanout from inputs to memories on reads
   logic rd_q;
   logic [AddrW-1:0] addr_q;
+  flash_ctrl_pkg::flash_part_e part_q;
 
   prim_fifo_sync #(
-      .Width  (AddrW),
+      .Width  (AddrW + $bits(flash_ctrl_pkg::flash_part_e)),
       .Pass   (0),
       .Depth  (2)
   ) i_slice (
@@ -79,11 +86,11 @@
     .clr_i  (1'b0),
     .wvalid (rd_i),
     .wready (),
-    .wdata  (addr_i),
+    .wdata  ({part_i, addr_i}),
     .depth  (),
     .rvalid (rd_q),
     .rready (hold_cmd), //whenver command is held, pop
-    .rdata  (addr_q)
+    .rdata  ({part_q, addr_q})
   );
 
 
@@ -98,6 +105,7 @@
       held_wdata <= '0;
     end else if (hold_cmd) begin
       held_addr <= rd_q ? addr_q : addr_i;
+      held_part <= rd_q ? part_q : part_i;
       held_wdata <= prog_data_i;
     end
   end
@@ -146,6 +154,7 @@
     mem_req          = 'h0;
     mem_wr           = 'h0;
     mem_addr         = 'h0;
+    mem_part         = flash_ctrl_pkg::DataPart;
     mem_wdata        = 'h0;
     time_cnt_inc     = 1'h0;
     time_cnt_clr     = 1'h0;
@@ -185,6 +194,7 @@
           // reads begin immediately
           hold_cmd = 1'b1;
           mem_addr = addr_q;
+          mem_part = part_q;
           mem_req = 1'b1;
           time_cnt_inc = 1'b1;
           st_d = StRead;
@@ -206,6 +216,7 @@
       end
       StRead: begin
         mem_addr = held_addr;
+        mem_part = held_part;
         if (time_cnt < ReadCycles) begin
           mem_req = 1'b1;
           time_cnt_inc = 1'b1;
@@ -216,6 +227,7 @@
           if (rd_q) begin
             hold_cmd = 1'b1;
             mem_addr = addr_q;
+            mem_part = part_q;
             mem_req = 1'b1;
             time_cnt_set1 = 1'b1;
             st_d = StRead;
@@ -232,6 +244,7 @@
       end
       StProg: begin
         mem_addr = held_addr;
+        mem_part = held_part;
 
         // if data is already 0, cannot program to 1 without erase
         mem_wdata = held_wdata & held_rdata;
@@ -253,6 +266,7 @@
           mem_wdata = {DataWidth{1'b1}};
 
           mem_addr = held_addr + index_cnt[AddrW-1:0];
+          mem_part = held_part;
           time_cnt_inc = (time_cnt < time_limit_q);
           index_cnt_inc = (index_cnt < index_limit_q);
         end else begin
@@ -268,18 +282,36 @@
     endcase // unique case (st_q)
   end // always_comb
 
+  logic [DataWidth-1:0] rd_data_main, rd_data_info;
+
   prim_ram_1p #(
     .Width(DataWidth),
     .Depth(WordsPerBank),
     .DataBitsPerMask(DataWidth)
   ) u_mem (
     .clk_i,
-    .req_i    (mem_req),
+    .req_i    (mem_req & (mem_part == flash_ctrl_pkg::DataPart)),
     .write_i  (mem_wr),
     .addr_i   (mem_addr),
     .wdata_i  (mem_wdata),
     .wmask_i  ({DataWidth{1'b1}}),
-    .rdata_o  (rd_data_o)
+    .rdata_o  (rd_data_main)
   );
 
+  prim_ram_1p #(
+    .Width(DataWidth),
+    .Depth(WordsPerInfoBank),
+    .DataBitsPerMask(DataWidth)
+  ) u_info_mem (
+    .clk_i,
+    .req_i    (mem_req & (mem_part == flash_ctrl_pkg::InfoPart)),
+    .write_i  (mem_wr),
+    .addr_i   (mem_addr[0 +: InfoAddrW]),
+    .wdata_i  (mem_wdata),
+    .wmask_i  ({DataWidth{1'b1}}),
+    .rdata_o  (rd_data_info)
+  );
+
+  assign rd_data_o = held_part == flash_ctrl_pkg::DataPart ? rd_data_main : rd_data_info;
+
 endmodule // prim_generic_flash
diff --git a/hw/top_earlgrey/rtl/top_pkg.sv b/hw/top_earlgrey/rtl/top_pkg.sv
index a3e06ef..9a29ed7 100644
--- a/hw/top_earlgrey/rtl/top_pkg.sv
+++ b/hw/top_earlgrey/rtl/top_pkg.sv
@@ -15,6 +15,8 @@
 localparam int FLASH_BANKS=2;
 localparam int FLASH_PAGES_PER_BANK=256;
 localparam int FLASH_WORDS_PER_PAGE=256;
-localparam int FLASH_BYTES_PER_WORD=4;
+localparam int FLASH_BYTES_PER_WORD=TL_DBW;
+localparam int FLASH_INFO_PER_BANK=4;
+localparam int FLASH_DATA_WIDTH=64;
 
 endpackage