[spi_device] Read Status CSR

Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/ip/spi_device/data/spi_device.hjson b/hw/ip/spi_device/data/spi_device.hjson
index dbde25b..e8c2e94 100644
--- a/hw/ip/spi_device/data/spi_device.hjson
+++ b/hw/ip/spi_device/data/spi_device.hjson
@@ -372,6 +372,63 @@
         }
       ]
     } // R: LAST_READ_ADDR
+    { name: "FLASH_STATUS"
+      desc: '''SPI Flash Status register.
+
+        This register emulates the SPI Flash Status 3, 2, 1 registers.
+        bit [7:0] is for Status register, bit [15:8] is for Status-2 register,
+        and bit [23:16] is for Status-3 register. It is SW responsibility to
+        maintain this register value up to date.
+
+        The HW latches the value when SPI Flash transaction begins. Any updates
+        during the transaction will be updated after the transaction is
+        completed.
+        '''
+      swaccess: "rw"
+      hwaccess: "hrw"
+      hwext: true
+      hwqe: true
+      fields: [
+        { bits: "0"
+          name: "busy"
+          desc: "BUSY"
+          swaccess: "rw0c"
+          hwaccess: "hrw"
+          tags: [
+            // STATUS[0] is updated by HW when CSb is de-asserted.
+            // So excluded from CSR automation test.
+            "excl:CsrNonInitTests:CsrExclWrite"
+          ]
+        } // f: busy
+        { bits: "23:1"
+          name: "status"
+          desc: '''Rest of the status register.
+
+            Fields other than the bit 0 (BUSY) field are SW-maintained fields.
+            HW just reads and returns to the host system.
+
+            [ 1]: WEL
+            [ 2]: BP0
+            [ 3]: BP1
+            [ 4]: BP2
+            [ 5]: TB
+            [ 6]: SEC
+            [ 7]: SRP0
+            [ 8]: SRP1
+            [ 9]: QE
+            [11]: LB1
+            [12]: LB2
+            [13]: LB3
+            [14]: CMP
+            [15]: SUS
+            [18]: WPS
+            [21]: DRV0
+            [22]: DRV1
+            [23]: HOLD /RST
+            '''
+        } // f: status
+      ]
+    } // R: FLASH_STATUS
     { multireg: {
         cname: "SPI_DEVICE"
         name:  "CMD_FILTER"
diff --git a/hw/ip/spi_device/rtl/spi_device.sv b/hw/ip/spi_device/rtl/spi_device.sv
index f4a52e3..0835c6f 100644
--- a/hw/ip/spi_device/rtl/spi_device.sv
+++ b/hw/ip/spi_device/rtl/spi_device.sv
@@ -198,6 +198,10 @@
   // domain variables into the bus clock domain.
   logic csb_deasserted_busclk;
 
+  // Read Status input and broadcast
+  logic status_busy_set; // set by HW (upload)
+  logic status_busy_broadcast; // from spid_status
+
   //////////////////////////////////////////////////////////////////////
   // Connect phase (between control signals above and register module //
   //////////////////////////////////////////////////////////////////////
@@ -659,7 +663,15 @@
             sub_sram_rdata  [IoModeReadCmd] = mem_b_rdata;
             sub_sram_rerror [IoModeReadCmd] = mem_b_rerror;
           end
-          // DpReadStatus:
+          DpReadStatus: begin
+            io_mode = sub_iomode[IoModeStatus];
+
+            p2s_valid = sub_p2s_valid[IoModeStatus];
+            p2s_data  = sub_p2s_data[IoModeStatus];
+            sub_p2s_sent[IoModeStatus] = p2s_sent;
+
+            // default memory (tied)
+          end
           // DpReadSFDP:
           // DpReadJEDEC:
           // DpUpload:
@@ -889,6 +901,64 @@
     .read_watermark_o ()
   );
 
+
+  // Begin: Read Status ==============================================
+  logic readstatus_qe;
+  logic [23:0] readstatus_q;
+  logic [23:0] readstatus_d;
+
+  assign readstatus_qe =  reg2hw.flash_status.busy.qe
+                       && reg2hw.flash_status.status.qe;
+  assign readstatus_q = { reg2hw.flash_status.status.q,
+                          reg2hw.flash_status.busy.q
+                        };
+  assign hw2reg.flash_status.busy.d   = readstatus_d[0];
+  assign hw2reg.flash_status.status.d = readstatus_d[23:1];
+
+  spid_status u_spid_status (
+    .clk_i  (clk_spi_in_buf),
+    .rst_ni (rst_spi_n),
+
+    .sys_clk_i  (clk_i),
+    .sys_rst_ni (rst_ni),
+
+    .csb_i (cio_csb_i),
+
+    .sys_status_we_i (readstatus_qe),
+    .sys_status_i    (readstatus_q),
+    .sys_status_o    (readstatus_d),
+
+    .sel_dp_i       (cmd_dp_sel),
+    .cmd_info_i     (cmd_info_broadcast),
+    .cmd_info_idx_i (cmd_info_idx_broadcast),
+
+    .outclk_p2s_valid_o (sub_p2s_valid[IoModeStatus]),
+    .outclk_p2s_byte_o  (sub_p2s_data[IoModeStatus]),
+    .outclk_p2s_sent_i  (sub_p2s_sent[IoModeStatus]),
+
+    .io_mode_o   (sub_iomode[IoModeStatus]),
+
+    .inclk_busy_set_i  (status_busy_set), // SCK domain
+
+    .inclk_busy_broadcast_o (status_busy_broadcast) // SCK domain
+  );
+
+  // Temporary:
+  logic unused_busy;
+  assign unused_busy = status_busy_broadcast;
+  // TODO: replace to the output of upload module
+  assign status_busy_set = 1'b 0;
+
+  // Tie unused
+  logic unused_sub_sram;
+  assign unused_sub_sram = ^{ sub_sram_req  [IoModeStatus],
+                              sub_sram_write[IoModeStatus],
+                              sub_sram_addr [IoModeStatus],
+                              sub_sram_wdata[IoModeStatus]
+                            };
+
+  // End: Read Status ------------------------------------------------
+
   /////////////////////
   // SPI Passthrough //
   /////////////////////
diff --git a/hw/ip/spi_device/rtl/spi_device_pkg.sv b/hw/ip/spi_device/rtl/spi_device_pkg.sv
index dbd7765..48dc399 100644
--- a/hw/ip/spi_device/rtl/spi_device_pkg.sv
+++ b/hw/ip/spi_device/rtl/spi_device_pkg.sv
@@ -204,7 +204,8 @@
     IoModeFw       = 0,
     IoModeCmdParse = 1,
     IoModeReadCmd  = 2,
-    IoModeEnd      = 3 // Indicate of Length
+    IoModeStatus   = 3,
+    IoModeEnd      = 4 // Indicate of Length
   } sub_io_mode_e;
 
   // SPI Line Mode (Mode0 <-> Mode3)
diff --git a/hw/ip/spi_device/rtl/spi_device_reg_pkg.sv b/hw/ip/spi_device/rtl/spi_device_reg_pkg.sv
index 2086047..755b28b 100644
--- a/hw/ip/spi_device/rtl/spi_device_reg_pkg.sv
+++ b/hw/ip/spi_device/rtl/spi_device_reg_pkg.sv
@@ -171,6 +171,17 @@
   } spi_device_reg2hw_txf_addr_reg_t;
 
   typedef struct packed {
+    struct packed {
+      logic        q;
+      logic        qe;
+    } busy;
+    struct packed {
+      logic [22:0] q;
+      logic        qe;
+    } status;
+  } spi_device_reg2hw_flash_status_reg_t;
+
+  typedef struct packed {
     logic        q;
   } spi_device_reg2hw_cmd_filter_mreg_t;
 
@@ -287,19 +298,29 @@
     logic [31:0] d;
   } spi_device_hw2reg_last_read_addr_reg_t;
 
+  typedef struct packed {
+    struct packed {
+      logic        d;
+    } busy;
+    struct packed {
+      logic [22:0] d;
+    } status;
+  } spi_device_hw2reg_flash_status_reg_t;
+
   // Register -> HW type
   typedef struct packed {
-    spi_device_reg2hw_intr_state_reg_t intr_state; // [828:823]
-    spi_device_reg2hw_intr_enable_reg_t intr_enable; // [822:817]
-    spi_device_reg2hw_intr_test_reg_t intr_test; // [816:805]
-    spi_device_reg2hw_alert_test_reg_t alert_test; // [804:803]
-    spi_device_reg2hw_control_reg_t control; // [802:797]
-    spi_device_reg2hw_cfg_reg_t cfg; // [796:784]
-    spi_device_reg2hw_fifo_level_reg_t fifo_level; // [783:752]
-    spi_device_reg2hw_rxf_ptr_reg_t rxf_ptr; // [751:736]
-    spi_device_reg2hw_txf_ptr_reg_t txf_ptr; // [735:720]
-    spi_device_reg2hw_rxf_addr_reg_t rxf_addr; // [719:688]
-    spi_device_reg2hw_txf_addr_reg_t txf_addr; // [687:656]
+    spi_device_reg2hw_intr_state_reg_t intr_state; // [854:849]
+    spi_device_reg2hw_intr_enable_reg_t intr_enable; // [848:843]
+    spi_device_reg2hw_intr_test_reg_t intr_test; // [842:831]
+    spi_device_reg2hw_alert_test_reg_t alert_test; // [830:829]
+    spi_device_reg2hw_control_reg_t control; // [828:823]
+    spi_device_reg2hw_cfg_reg_t cfg; // [822:810]
+    spi_device_reg2hw_fifo_level_reg_t fifo_level; // [809:778]
+    spi_device_reg2hw_rxf_ptr_reg_t rxf_ptr; // [777:762]
+    spi_device_reg2hw_txf_ptr_reg_t txf_ptr; // [761:746]
+    spi_device_reg2hw_rxf_addr_reg_t rxf_addr; // [745:714]
+    spi_device_reg2hw_txf_addr_reg_t txf_addr; // [713:682]
+    spi_device_reg2hw_flash_status_reg_t flash_status; // [681:656]
     spi_device_reg2hw_cmd_filter_mreg_t [255:0] cmd_filter; // [655:400]
     spi_device_reg2hw_addr_swap_mask_reg_t addr_swap_mask; // [399:368]
     spi_device_reg2hw_addr_swap_data_reg_t addr_swap_data; // [367:336]
@@ -308,12 +329,13 @@
 
   // HW -> register type
   typedef struct packed {
-    spi_device_hw2reg_intr_state_reg_t intr_state; // [99:88]
-    spi_device_hw2reg_async_fifo_level_reg_t async_fifo_level; // [87:72]
-    spi_device_hw2reg_status_reg_t status; // [71:66]
-    spi_device_hw2reg_rxf_ptr_reg_t rxf_ptr; // [65:49]
-    spi_device_hw2reg_txf_ptr_reg_t txf_ptr; // [48:32]
-    spi_device_hw2reg_last_read_addr_reg_t last_read_addr; // [31:0]
+    spi_device_hw2reg_intr_state_reg_t intr_state; // [123:112]
+    spi_device_hw2reg_async_fifo_level_reg_t async_fifo_level; // [111:96]
+    spi_device_hw2reg_status_reg_t status; // [95:90]
+    spi_device_hw2reg_rxf_ptr_reg_t rxf_ptr; // [89:73]
+    spi_device_hw2reg_txf_ptr_reg_t txf_ptr; // [72:56]
+    spi_device_hw2reg_last_read_addr_reg_t last_read_addr; // [55:24]
+    spi_device_hw2reg_flash_status_reg_t flash_status; // [23:0]
   } spi_device_hw2reg_t;
 
   // Register offsets
@@ -331,32 +353,33 @@
   parameter logic [BlockAw-1:0] SPI_DEVICE_RXF_ADDR_OFFSET = 13'h 2c;
   parameter logic [BlockAw-1:0] SPI_DEVICE_TXF_ADDR_OFFSET = 13'h 30;
   parameter logic [BlockAw-1:0] SPI_DEVICE_LAST_READ_ADDR_OFFSET = 13'h 34;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_0_OFFSET = 13'h 38;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_1_OFFSET = 13'h 3c;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_2_OFFSET = 13'h 40;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_3_OFFSET = 13'h 44;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_4_OFFSET = 13'h 48;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_5_OFFSET = 13'h 4c;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_6_OFFSET = 13'h 50;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_7_OFFSET = 13'h 54;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_ADDR_SWAP_MASK_OFFSET = 13'h 58;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_ADDR_SWAP_DATA_OFFSET = 13'h 5c;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_0_OFFSET = 13'h 60;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_1_OFFSET = 13'h 64;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_2_OFFSET = 13'h 68;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_3_OFFSET = 13'h 6c;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_4_OFFSET = 13'h 70;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_5_OFFSET = 13'h 74;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_6_OFFSET = 13'h 78;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_7_OFFSET = 13'h 7c;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_8_OFFSET = 13'h 80;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_9_OFFSET = 13'h 84;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_10_OFFSET = 13'h 88;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_11_OFFSET = 13'h 8c;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_12_OFFSET = 13'h 90;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_13_OFFSET = 13'h 94;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_14_OFFSET = 13'h 98;
-  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_15_OFFSET = 13'h 9c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_FLASH_STATUS_OFFSET = 13'h 38;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_0_OFFSET = 13'h 3c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_1_OFFSET = 13'h 40;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_2_OFFSET = 13'h 44;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_3_OFFSET = 13'h 48;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_4_OFFSET = 13'h 4c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_5_OFFSET = 13'h 50;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_6_OFFSET = 13'h 54;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_7_OFFSET = 13'h 58;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_ADDR_SWAP_MASK_OFFSET = 13'h 5c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_ADDR_SWAP_DATA_OFFSET = 13'h 60;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_0_OFFSET = 13'h 64;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_1_OFFSET = 13'h 68;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_2_OFFSET = 13'h 6c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_3_OFFSET = 13'h 70;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_4_OFFSET = 13'h 74;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_5_OFFSET = 13'h 78;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_6_OFFSET = 13'h 7c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_7_OFFSET = 13'h 80;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_8_OFFSET = 13'h 84;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_9_OFFSET = 13'h 88;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_10_OFFSET = 13'h 8c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_11_OFFSET = 13'h 90;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_12_OFFSET = 13'h 94;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_13_OFFSET = 13'h 98;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_14_OFFSET = 13'h 9c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_15_OFFSET = 13'h a0;
 
   // Reset values for hwext registers and their fields
   parameter logic [5:0] SPI_DEVICE_INTR_TEST_RESVAL = 6'h 0;
@@ -375,6 +398,7 @@
   parameter logic [0:0] SPI_DEVICE_STATUS_ABORT_DONE_RESVAL = 1'h 1;
   parameter logic [0:0] SPI_DEVICE_STATUS_CSB_RESVAL = 1'h 1;
   parameter logic [31:0] SPI_DEVICE_LAST_READ_ADDR_RESVAL = 32'h 0;
+  parameter logic [23:0] SPI_DEVICE_FLASH_STATUS_RESVAL = 24'h 0;
 
   // Window parameters
   parameter logic [BlockAw-1:0] SPI_DEVICE_BUFFER_OFFSET = 13'h 1000;
@@ -396,6 +420,7 @@
     SPI_DEVICE_RXF_ADDR,
     SPI_DEVICE_TXF_ADDR,
     SPI_DEVICE_LAST_READ_ADDR,
+    SPI_DEVICE_FLASH_STATUS,
     SPI_DEVICE_CMD_FILTER_0,
     SPI_DEVICE_CMD_FILTER_1,
     SPI_DEVICE_CMD_FILTER_2,
@@ -425,7 +450,7 @@
   } spi_device_id_e;
 
   // Register width information to check illegal writes
-  parameter logic [3:0] SPI_DEVICE_PERMIT [40] = '{
+  parameter logic [3:0] SPI_DEVICE_PERMIT [41] = '{
     4'b 0001, // index[ 0] SPI_DEVICE_INTR_STATE
     4'b 0001, // index[ 1] SPI_DEVICE_INTR_ENABLE
     4'b 0001, // index[ 2] SPI_DEVICE_INTR_TEST
@@ -440,32 +465,33 @@
     4'b 1111, // index[11] SPI_DEVICE_RXF_ADDR
     4'b 1111, // index[12] SPI_DEVICE_TXF_ADDR
     4'b 1111, // index[13] SPI_DEVICE_LAST_READ_ADDR
-    4'b 1111, // index[14] SPI_DEVICE_CMD_FILTER_0
-    4'b 1111, // index[15] SPI_DEVICE_CMD_FILTER_1
-    4'b 1111, // index[16] SPI_DEVICE_CMD_FILTER_2
-    4'b 1111, // index[17] SPI_DEVICE_CMD_FILTER_3
-    4'b 1111, // index[18] SPI_DEVICE_CMD_FILTER_4
-    4'b 1111, // index[19] SPI_DEVICE_CMD_FILTER_5
-    4'b 1111, // index[20] SPI_DEVICE_CMD_FILTER_6
-    4'b 1111, // index[21] SPI_DEVICE_CMD_FILTER_7
-    4'b 1111, // index[22] SPI_DEVICE_ADDR_SWAP_MASK
-    4'b 1111, // index[23] SPI_DEVICE_ADDR_SWAP_DATA
-    4'b 0111, // index[24] SPI_DEVICE_CMD_INFO_0
-    4'b 0111, // index[25] SPI_DEVICE_CMD_INFO_1
-    4'b 0111, // index[26] SPI_DEVICE_CMD_INFO_2
-    4'b 0111, // index[27] SPI_DEVICE_CMD_INFO_3
-    4'b 0111, // index[28] SPI_DEVICE_CMD_INFO_4
-    4'b 0111, // index[29] SPI_DEVICE_CMD_INFO_5
-    4'b 0111, // index[30] SPI_DEVICE_CMD_INFO_6
-    4'b 0111, // index[31] SPI_DEVICE_CMD_INFO_7
-    4'b 0111, // index[32] SPI_DEVICE_CMD_INFO_8
-    4'b 0111, // index[33] SPI_DEVICE_CMD_INFO_9
-    4'b 0111, // index[34] SPI_DEVICE_CMD_INFO_10
-    4'b 0111, // index[35] SPI_DEVICE_CMD_INFO_11
-    4'b 0111, // index[36] SPI_DEVICE_CMD_INFO_12
-    4'b 0111, // index[37] SPI_DEVICE_CMD_INFO_13
-    4'b 0111, // index[38] SPI_DEVICE_CMD_INFO_14
-    4'b 0111  // index[39] SPI_DEVICE_CMD_INFO_15
+    4'b 0111, // index[14] SPI_DEVICE_FLASH_STATUS
+    4'b 1111, // index[15] SPI_DEVICE_CMD_FILTER_0
+    4'b 1111, // index[16] SPI_DEVICE_CMD_FILTER_1
+    4'b 1111, // index[17] SPI_DEVICE_CMD_FILTER_2
+    4'b 1111, // index[18] SPI_DEVICE_CMD_FILTER_3
+    4'b 1111, // index[19] SPI_DEVICE_CMD_FILTER_4
+    4'b 1111, // index[20] SPI_DEVICE_CMD_FILTER_5
+    4'b 1111, // index[21] SPI_DEVICE_CMD_FILTER_6
+    4'b 1111, // index[22] SPI_DEVICE_CMD_FILTER_7
+    4'b 1111, // index[23] SPI_DEVICE_ADDR_SWAP_MASK
+    4'b 1111, // index[24] SPI_DEVICE_ADDR_SWAP_DATA
+    4'b 0111, // index[25] SPI_DEVICE_CMD_INFO_0
+    4'b 0111, // index[26] SPI_DEVICE_CMD_INFO_1
+    4'b 0111, // index[27] SPI_DEVICE_CMD_INFO_2
+    4'b 0111, // index[28] SPI_DEVICE_CMD_INFO_3
+    4'b 0111, // index[29] SPI_DEVICE_CMD_INFO_4
+    4'b 0111, // index[30] SPI_DEVICE_CMD_INFO_5
+    4'b 0111, // index[31] SPI_DEVICE_CMD_INFO_6
+    4'b 0111, // index[32] SPI_DEVICE_CMD_INFO_7
+    4'b 0111, // index[33] SPI_DEVICE_CMD_INFO_8
+    4'b 0111, // index[34] SPI_DEVICE_CMD_INFO_9
+    4'b 0111, // index[35] SPI_DEVICE_CMD_INFO_10
+    4'b 0111, // index[36] SPI_DEVICE_CMD_INFO_11
+    4'b 0111, // index[37] SPI_DEVICE_CMD_INFO_12
+    4'b 0111, // index[38] SPI_DEVICE_CMD_INFO_13
+    4'b 0111, // index[39] SPI_DEVICE_CMD_INFO_14
+    4'b 0111  // index[40] SPI_DEVICE_CMD_INFO_15
   };
 
 endpackage
diff --git a/hw/ip/spi_device/rtl/spi_device_reg_top.sv b/hw/ip/spi_device/rtl/spi_device_reg_top.sv
index cbd9063..e3e0836 100644
--- a/hw/ip/spi_device/rtl/spi_device_reg_top.sv
+++ b/hw/ip/spi_device/rtl/spi_device_reg_top.sv
@@ -251,6 +251,12 @@
   logic [15:0] txf_addr_limit_wd;
   logic last_read_addr_re;
   logic [31:0] last_read_addr_qs;
+  logic flash_status_re;
+  logic flash_status_we;
+  logic flash_status_busy_qs;
+  logic flash_status_busy_wd;
+  logic [22:0] flash_status_status_qs;
+  logic [22:0] flash_status_status_wd;
   logic cmd_filter_0_we;
   logic cmd_filter_0_filter_0_qs;
   logic cmd_filter_0_filter_0_wd;
@@ -2207,6 +2213,38 @@
   );
 
 
+  // R[flash_status]: V(True)
+
+  //   F[busy]: 0:0
+  prim_subreg_ext #(
+    .DW    (1)
+  ) u_flash_status_busy (
+    .re     (flash_status_re),
+    .we     (flash_status_we),
+    .wd     (flash_status_busy_wd),
+    .d      (hw2reg.flash_status.busy.d),
+    .qre    (),
+    .qe     (reg2hw.flash_status.busy.qe),
+    .q      (reg2hw.flash_status.busy.q),
+    .qs     (flash_status_busy_qs)
+  );
+
+
+  //   F[status]: 23:1
+  prim_subreg_ext #(
+    .DW    (23)
+  ) u_flash_status_status (
+    .re     (flash_status_re),
+    .we     (flash_status_we),
+    .wd     (flash_status_status_wd),
+    .d      (hw2reg.flash_status.status.d),
+    .qre    (),
+    .qe     (reg2hw.flash_status.status.qe),
+    .q      (reg2hw.flash_status.status.q),
+    .qs     (flash_status_status_qs)
+  );
+
+
 
   // Subregister 0 of Multireg cmd_filter
   // R[cmd_filter_0]: V(False)
@@ -12739,7 +12777,7 @@
 
 
 
-  logic [39:0] addr_hit;
+  logic [40:0] addr_hit;
   always_comb begin
     addr_hit = '0;
     addr_hit[ 0] = (reg_addr == SPI_DEVICE_INTR_STATE_OFFSET);
@@ -12756,32 +12794,33 @@
     addr_hit[11] = (reg_addr == SPI_DEVICE_RXF_ADDR_OFFSET);
     addr_hit[12] = (reg_addr == SPI_DEVICE_TXF_ADDR_OFFSET);
     addr_hit[13] = (reg_addr == SPI_DEVICE_LAST_READ_ADDR_OFFSET);
-    addr_hit[14] = (reg_addr == SPI_DEVICE_CMD_FILTER_0_OFFSET);
-    addr_hit[15] = (reg_addr == SPI_DEVICE_CMD_FILTER_1_OFFSET);
-    addr_hit[16] = (reg_addr == SPI_DEVICE_CMD_FILTER_2_OFFSET);
-    addr_hit[17] = (reg_addr == SPI_DEVICE_CMD_FILTER_3_OFFSET);
-    addr_hit[18] = (reg_addr == SPI_DEVICE_CMD_FILTER_4_OFFSET);
-    addr_hit[19] = (reg_addr == SPI_DEVICE_CMD_FILTER_5_OFFSET);
-    addr_hit[20] = (reg_addr == SPI_DEVICE_CMD_FILTER_6_OFFSET);
-    addr_hit[21] = (reg_addr == SPI_DEVICE_CMD_FILTER_7_OFFSET);
-    addr_hit[22] = (reg_addr == SPI_DEVICE_ADDR_SWAP_MASK_OFFSET);
-    addr_hit[23] = (reg_addr == SPI_DEVICE_ADDR_SWAP_DATA_OFFSET);
-    addr_hit[24] = (reg_addr == SPI_DEVICE_CMD_INFO_0_OFFSET);
-    addr_hit[25] = (reg_addr == SPI_DEVICE_CMD_INFO_1_OFFSET);
-    addr_hit[26] = (reg_addr == SPI_DEVICE_CMD_INFO_2_OFFSET);
-    addr_hit[27] = (reg_addr == SPI_DEVICE_CMD_INFO_3_OFFSET);
-    addr_hit[28] = (reg_addr == SPI_DEVICE_CMD_INFO_4_OFFSET);
-    addr_hit[29] = (reg_addr == SPI_DEVICE_CMD_INFO_5_OFFSET);
-    addr_hit[30] = (reg_addr == SPI_DEVICE_CMD_INFO_6_OFFSET);
-    addr_hit[31] = (reg_addr == SPI_DEVICE_CMD_INFO_7_OFFSET);
-    addr_hit[32] = (reg_addr == SPI_DEVICE_CMD_INFO_8_OFFSET);
-    addr_hit[33] = (reg_addr == SPI_DEVICE_CMD_INFO_9_OFFSET);
-    addr_hit[34] = (reg_addr == SPI_DEVICE_CMD_INFO_10_OFFSET);
-    addr_hit[35] = (reg_addr == SPI_DEVICE_CMD_INFO_11_OFFSET);
-    addr_hit[36] = (reg_addr == SPI_DEVICE_CMD_INFO_12_OFFSET);
-    addr_hit[37] = (reg_addr == SPI_DEVICE_CMD_INFO_13_OFFSET);
-    addr_hit[38] = (reg_addr == SPI_DEVICE_CMD_INFO_14_OFFSET);
-    addr_hit[39] = (reg_addr == SPI_DEVICE_CMD_INFO_15_OFFSET);
+    addr_hit[14] = (reg_addr == SPI_DEVICE_FLASH_STATUS_OFFSET);
+    addr_hit[15] = (reg_addr == SPI_DEVICE_CMD_FILTER_0_OFFSET);
+    addr_hit[16] = (reg_addr == SPI_DEVICE_CMD_FILTER_1_OFFSET);
+    addr_hit[17] = (reg_addr == SPI_DEVICE_CMD_FILTER_2_OFFSET);
+    addr_hit[18] = (reg_addr == SPI_DEVICE_CMD_FILTER_3_OFFSET);
+    addr_hit[19] = (reg_addr == SPI_DEVICE_CMD_FILTER_4_OFFSET);
+    addr_hit[20] = (reg_addr == SPI_DEVICE_CMD_FILTER_5_OFFSET);
+    addr_hit[21] = (reg_addr == SPI_DEVICE_CMD_FILTER_6_OFFSET);
+    addr_hit[22] = (reg_addr == SPI_DEVICE_CMD_FILTER_7_OFFSET);
+    addr_hit[23] = (reg_addr == SPI_DEVICE_ADDR_SWAP_MASK_OFFSET);
+    addr_hit[24] = (reg_addr == SPI_DEVICE_ADDR_SWAP_DATA_OFFSET);
+    addr_hit[25] = (reg_addr == SPI_DEVICE_CMD_INFO_0_OFFSET);
+    addr_hit[26] = (reg_addr == SPI_DEVICE_CMD_INFO_1_OFFSET);
+    addr_hit[27] = (reg_addr == SPI_DEVICE_CMD_INFO_2_OFFSET);
+    addr_hit[28] = (reg_addr == SPI_DEVICE_CMD_INFO_3_OFFSET);
+    addr_hit[29] = (reg_addr == SPI_DEVICE_CMD_INFO_4_OFFSET);
+    addr_hit[30] = (reg_addr == SPI_DEVICE_CMD_INFO_5_OFFSET);
+    addr_hit[31] = (reg_addr == SPI_DEVICE_CMD_INFO_6_OFFSET);
+    addr_hit[32] = (reg_addr == SPI_DEVICE_CMD_INFO_7_OFFSET);
+    addr_hit[33] = (reg_addr == SPI_DEVICE_CMD_INFO_8_OFFSET);
+    addr_hit[34] = (reg_addr == SPI_DEVICE_CMD_INFO_9_OFFSET);
+    addr_hit[35] = (reg_addr == SPI_DEVICE_CMD_INFO_10_OFFSET);
+    addr_hit[36] = (reg_addr == SPI_DEVICE_CMD_INFO_11_OFFSET);
+    addr_hit[37] = (reg_addr == SPI_DEVICE_CMD_INFO_12_OFFSET);
+    addr_hit[38] = (reg_addr == SPI_DEVICE_CMD_INFO_13_OFFSET);
+    addr_hit[39] = (reg_addr == SPI_DEVICE_CMD_INFO_14_OFFSET);
+    addr_hit[40] = (reg_addr == SPI_DEVICE_CMD_INFO_15_OFFSET);
   end
 
   assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -12828,7 +12867,8 @@
                (addr_hit[36] & (|(SPI_DEVICE_PERMIT[36] & ~reg_be))) |
                (addr_hit[37] & (|(SPI_DEVICE_PERMIT[37] & ~reg_be))) |
                (addr_hit[38] & (|(SPI_DEVICE_PERMIT[38] & ~reg_be))) |
-               (addr_hit[39] & (|(SPI_DEVICE_PERMIT[39] & ~reg_be)))));
+               (addr_hit[39] & (|(SPI_DEVICE_PERMIT[39] & ~reg_be))) |
+               (addr_hit[40] & (|(SPI_DEVICE_PERMIT[40] & ~reg_be)))));
   end
   assign intr_state_we = addr_hit[0] & reg_we & !reg_error;
 
@@ -12920,7 +12960,13 @@
 
   assign txf_addr_limit_wd = reg_wdata[31:16];
   assign last_read_addr_re = addr_hit[13] & reg_re & !reg_error;
-  assign cmd_filter_0_we = addr_hit[14] & reg_we & !reg_error;
+  assign flash_status_re = addr_hit[14] & reg_re & !reg_error;
+  assign flash_status_we = addr_hit[14] & reg_we & !reg_error;
+
+  assign flash_status_busy_wd = reg_wdata[0];
+
+  assign flash_status_status_wd = reg_wdata[23:1];
+  assign cmd_filter_0_we = addr_hit[15] & reg_we & !reg_error;
 
   assign cmd_filter_0_filter_0_wd = reg_wdata[0];
 
@@ -12985,7 +13031,7 @@
   assign cmd_filter_0_filter_30_wd = reg_wdata[30];
 
   assign cmd_filter_0_filter_31_wd = reg_wdata[31];
-  assign cmd_filter_1_we = addr_hit[15] & reg_we & !reg_error;
+  assign cmd_filter_1_we = addr_hit[16] & reg_we & !reg_error;
 
   assign cmd_filter_1_filter_32_wd = reg_wdata[0];
 
@@ -13050,7 +13096,7 @@
   assign cmd_filter_1_filter_62_wd = reg_wdata[30];
 
   assign cmd_filter_1_filter_63_wd = reg_wdata[31];
-  assign cmd_filter_2_we = addr_hit[16] & reg_we & !reg_error;
+  assign cmd_filter_2_we = addr_hit[17] & reg_we & !reg_error;
 
   assign cmd_filter_2_filter_64_wd = reg_wdata[0];
 
@@ -13115,7 +13161,7 @@
   assign cmd_filter_2_filter_94_wd = reg_wdata[30];
 
   assign cmd_filter_2_filter_95_wd = reg_wdata[31];
-  assign cmd_filter_3_we = addr_hit[17] & reg_we & !reg_error;
+  assign cmd_filter_3_we = addr_hit[18] & reg_we & !reg_error;
 
   assign cmd_filter_3_filter_96_wd = reg_wdata[0];
 
@@ -13180,7 +13226,7 @@
   assign cmd_filter_3_filter_126_wd = reg_wdata[30];
 
   assign cmd_filter_3_filter_127_wd = reg_wdata[31];
-  assign cmd_filter_4_we = addr_hit[18] & reg_we & !reg_error;
+  assign cmd_filter_4_we = addr_hit[19] & reg_we & !reg_error;
 
   assign cmd_filter_4_filter_128_wd = reg_wdata[0];
 
@@ -13245,7 +13291,7 @@
   assign cmd_filter_4_filter_158_wd = reg_wdata[30];
 
   assign cmd_filter_4_filter_159_wd = reg_wdata[31];
-  assign cmd_filter_5_we = addr_hit[19] & reg_we & !reg_error;
+  assign cmd_filter_5_we = addr_hit[20] & reg_we & !reg_error;
 
   assign cmd_filter_5_filter_160_wd = reg_wdata[0];
 
@@ -13310,7 +13356,7 @@
   assign cmd_filter_5_filter_190_wd = reg_wdata[30];
 
   assign cmd_filter_5_filter_191_wd = reg_wdata[31];
-  assign cmd_filter_6_we = addr_hit[20] & reg_we & !reg_error;
+  assign cmd_filter_6_we = addr_hit[21] & reg_we & !reg_error;
 
   assign cmd_filter_6_filter_192_wd = reg_wdata[0];
 
@@ -13375,7 +13421,7 @@
   assign cmd_filter_6_filter_222_wd = reg_wdata[30];
 
   assign cmd_filter_6_filter_223_wd = reg_wdata[31];
-  assign cmd_filter_7_we = addr_hit[21] & reg_we & !reg_error;
+  assign cmd_filter_7_we = addr_hit[22] & reg_we & !reg_error;
 
   assign cmd_filter_7_filter_224_wd = reg_wdata[0];
 
@@ -13440,13 +13486,13 @@
   assign cmd_filter_7_filter_254_wd = reg_wdata[30];
 
   assign cmd_filter_7_filter_255_wd = reg_wdata[31];
-  assign addr_swap_mask_we = addr_hit[22] & reg_we & !reg_error;
+  assign addr_swap_mask_we = addr_hit[23] & reg_we & !reg_error;
 
   assign addr_swap_mask_wd = reg_wdata[31:0];
-  assign addr_swap_data_we = addr_hit[23] & reg_we & !reg_error;
+  assign addr_swap_data_we = addr_hit[24] & reg_we & !reg_error;
 
   assign addr_swap_data_wd = reg_wdata[31:0];
-  assign cmd_info_0_we = addr_hit[24] & reg_we & !reg_error;
+  assign cmd_info_0_we = addr_hit[25] & reg_we & !reg_error;
 
   assign cmd_info_0_opcode_0_wd = reg_wdata[7:0];
 
@@ -13465,7 +13511,7 @@
   assign cmd_info_0_payload_en_0_wd = reg_wdata[19:16];
 
   assign cmd_info_0_payload_dir_0_wd = reg_wdata[20];
-  assign cmd_info_1_we = addr_hit[25] & reg_we & !reg_error;
+  assign cmd_info_1_we = addr_hit[26] & reg_we & !reg_error;
 
   assign cmd_info_1_opcode_1_wd = reg_wdata[7:0];
 
@@ -13484,7 +13530,7 @@
   assign cmd_info_1_payload_en_1_wd = reg_wdata[19:16];
 
   assign cmd_info_1_payload_dir_1_wd = reg_wdata[20];
-  assign cmd_info_2_we = addr_hit[26] & reg_we & !reg_error;
+  assign cmd_info_2_we = addr_hit[27] & reg_we & !reg_error;
 
   assign cmd_info_2_opcode_2_wd = reg_wdata[7:0];
 
@@ -13503,7 +13549,7 @@
   assign cmd_info_2_payload_en_2_wd = reg_wdata[19:16];
 
   assign cmd_info_2_payload_dir_2_wd = reg_wdata[20];
-  assign cmd_info_3_we = addr_hit[27] & reg_we & !reg_error;
+  assign cmd_info_3_we = addr_hit[28] & reg_we & !reg_error;
 
   assign cmd_info_3_opcode_3_wd = reg_wdata[7:0];
 
@@ -13522,7 +13568,7 @@
   assign cmd_info_3_payload_en_3_wd = reg_wdata[19:16];
 
   assign cmd_info_3_payload_dir_3_wd = reg_wdata[20];
-  assign cmd_info_4_we = addr_hit[28] & reg_we & !reg_error;
+  assign cmd_info_4_we = addr_hit[29] & reg_we & !reg_error;
 
   assign cmd_info_4_opcode_4_wd = reg_wdata[7:0];
 
@@ -13541,7 +13587,7 @@
   assign cmd_info_4_payload_en_4_wd = reg_wdata[19:16];
 
   assign cmd_info_4_payload_dir_4_wd = reg_wdata[20];
-  assign cmd_info_5_we = addr_hit[29] & reg_we & !reg_error;
+  assign cmd_info_5_we = addr_hit[30] & reg_we & !reg_error;
 
   assign cmd_info_5_opcode_5_wd = reg_wdata[7:0];
 
@@ -13560,7 +13606,7 @@
   assign cmd_info_5_payload_en_5_wd = reg_wdata[19:16];
 
   assign cmd_info_5_payload_dir_5_wd = reg_wdata[20];
-  assign cmd_info_6_we = addr_hit[30] & reg_we & !reg_error;
+  assign cmd_info_6_we = addr_hit[31] & reg_we & !reg_error;
 
   assign cmd_info_6_opcode_6_wd = reg_wdata[7:0];
 
@@ -13579,7 +13625,7 @@
   assign cmd_info_6_payload_en_6_wd = reg_wdata[19:16];
 
   assign cmd_info_6_payload_dir_6_wd = reg_wdata[20];
-  assign cmd_info_7_we = addr_hit[31] & reg_we & !reg_error;
+  assign cmd_info_7_we = addr_hit[32] & reg_we & !reg_error;
 
   assign cmd_info_7_opcode_7_wd = reg_wdata[7:0];
 
@@ -13598,7 +13644,7 @@
   assign cmd_info_7_payload_en_7_wd = reg_wdata[19:16];
 
   assign cmd_info_7_payload_dir_7_wd = reg_wdata[20];
-  assign cmd_info_8_we = addr_hit[32] & reg_we & !reg_error;
+  assign cmd_info_8_we = addr_hit[33] & reg_we & !reg_error;
 
   assign cmd_info_8_opcode_8_wd = reg_wdata[7:0];
 
@@ -13617,7 +13663,7 @@
   assign cmd_info_8_payload_en_8_wd = reg_wdata[19:16];
 
   assign cmd_info_8_payload_dir_8_wd = reg_wdata[20];
-  assign cmd_info_9_we = addr_hit[33] & reg_we & !reg_error;
+  assign cmd_info_9_we = addr_hit[34] & reg_we & !reg_error;
 
   assign cmd_info_9_opcode_9_wd = reg_wdata[7:0];
 
@@ -13636,7 +13682,7 @@
   assign cmd_info_9_payload_en_9_wd = reg_wdata[19:16];
 
   assign cmd_info_9_payload_dir_9_wd = reg_wdata[20];
-  assign cmd_info_10_we = addr_hit[34] & reg_we & !reg_error;
+  assign cmd_info_10_we = addr_hit[35] & reg_we & !reg_error;
 
   assign cmd_info_10_opcode_10_wd = reg_wdata[7:0];
 
@@ -13655,7 +13701,7 @@
   assign cmd_info_10_payload_en_10_wd = reg_wdata[19:16];
 
   assign cmd_info_10_payload_dir_10_wd = reg_wdata[20];
-  assign cmd_info_11_we = addr_hit[35] & reg_we & !reg_error;
+  assign cmd_info_11_we = addr_hit[36] & reg_we & !reg_error;
 
   assign cmd_info_11_opcode_11_wd = reg_wdata[7:0];
 
@@ -13674,7 +13720,7 @@
   assign cmd_info_11_payload_en_11_wd = reg_wdata[19:16];
 
   assign cmd_info_11_payload_dir_11_wd = reg_wdata[20];
-  assign cmd_info_12_we = addr_hit[36] & reg_we & !reg_error;
+  assign cmd_info_12_we = addr_hit[37] & reg_we & !reg_error;
 
   assign cmd_info_12_opcode_12_wd = reg_wdata[7:0];
 
@@ -13693,7 +13739,7 @@
   assign cmd_info_12_payload_en_12_wd = reg_wdata[19:16];
 
   assign cmd_info_12_payload_dir_12_wd = reg_wdata[20];
-  assign cmd_info_13_we = addr_hit[37] & reg_we & !reg_error;
+  assign cmd_info_13_we = addr_hit[38] & reg_we & !reg_error;
 
   assign cmd_info_13_opcode_13_wd = reg_wdata[7:0];
 
@@ -13712,7 +13758,7 @@
   assign cmd_info_13_payload_en_13_wd = reg_wdata[19:16];
 
   assign cmd_info_13_payload_dir_13_wd = reg_wdata[20];
-  assign cmd_info_14_we = addr_hit[38] & reg_we & !reg_error;
+  assign cmd_info_14_we = addr_hit[39] & reg_we & !reg_error;
 
   assign cmd_info_14_opcode_14_wd = reg_wdata[7:0];
 
@@ -13731,7 +13777,7 @@
   assign cmd_info_14_payload_en_14_wd = reg_wdata[19:16];
 
   assign cmd_info_14_payload_dir_14_wd = reg_wdata[20];
-  assign cmd_info_15_we = addr_hit[39] & reg_we & !reg_error;
+  assign cmd_info_15_we = addr_hit[40] & reg_we & !reg_error;
 
   assign cmd_info_15_opcode_15_wd = reg_wdata[7:0];
 
@@ -13847,6 +13893,11 @@
       end
 
       addr_hit[14]: begin
+        reg_rdata_next[0] = flash_status_busy_qs;
+        reg_rdata_next[23:1] = flash_status_status_qs;
+      end
+
+      addr_hit[15]: begin
         reg_rdata_next[0] = cmd_filter_0_filter_0_qs;
         reg_rdata_next[1] = cmd_filter_0_filter_1_qs;
         reg_rdata_next[2] = cmd_filter_0_filter_2_qs;
@@ -13881,7 +13932,7 @@
         reg_rdata_next[31] = cmd_filter_0_filter_31_qs;
       end
 
-      addr_hit[15]: begin
+      addr_hit[16]: begin
         reg_rdata_next[0] = cmd_filter_1_filter_32_qs;
         reg_rdata_next[1] = cmd_filter_1_filter_33_qs;
         reg_rdata_next[2] = cmd_filter_1_filter_34_qs;
@@ -13916,7 +13967,7 @@
         reg_rdata_next[31] = cmd_filter_1_filter_63_qs;
       end
 
-      addr_hit[16]: begin
+      addr_hit[17]: begin
         reg_rdata_next[0] = cmd_filter_2_filter_64_qs;
         reg_rdata_next[1] = cmd_filter_2_filter_65_qs;
         reg_rdata_next[2] = cmd_filter_2_filter_66_qs;
@@ -13951,7 +14002,7 @@
         reg_rdata_next[31] = cmd_filter_2_filter_95_qs;
       end
 
-      addr_hit[17]: begin
+      addr_hit[18]: begin
         reg_rdata_next[0] = cmd_filter_3_filter_96_qs;
         reg_rdata_next[1] = cmd_filter_3_filter_97_qs;
         reg_rdata_next[2] = cmd_filter_3_filter_98_qs;
@@ -13986,7 +14037,7 @@
         reg_rdata_next[31] = cmd_filter_3_filter_127_qs;
       end
 
-      addr_hit[18]: begin
+      addr_hit[19]: begin
         reg_rdata_next[0] = cmd_filter_4_filter_128_qs;
         reg_rdata_next[1] = cmd_filter_4_filter_129_qs;
         reg_rdata_next[2] = cmd_filter_4_filter_130_qs;
@@ -14021,7 +14072,7 @@
         reg_rdata_next[31] = cmd_filter_4_filter_159_qs;
       end
 
-      addr_hit[19]: begin
+      addr_hit[20]: begin
         reg_rdata_next[0] = cmd_filter_5_filter_160_qs;
         reg_rdata_next[1] = cmd_filter_5_filter_161_qs;
         reg_rdata_next[2] = cmd_filter_5_filter_162_qs;
@@ -14056,7 +14107,7 @@
         reg_rdata_next[31] = cmd_filter_5_filter_191_qs;
       end
 
-      addr_hit[20]: begin
+      addr_hit[21]: begin
         reg_rdata_next[0] = cmd_filter_6_filter_192_qs;
         reg_rdata_next[1] = cmd_filter_6_filter_193_qs;
         reg_rdata_next[2] = cmd_filter_6_filter_194_qs;
@@ -14091,7 +14142,7 @@
         reg_rdata_next[31] = cmd_filter_6_filter_223_qs;
       end
 
-      addr_hit[21]: begin
+      addr_hit[22]: begin
         reg_rdata_next[0] = cmd_filter_7_filter_224_qs;
         reg_rdata_next[1] = cmd_filter_7_filter_225_qs;
         reg_rdata_next[2] = cmd_filter_7_filter_226_qs;
@@ -14126,15 +14177,15 @@
         reg_rdata_next[31] = cmd_filter_7_filter_255_qs;
       end
 
-      addr_hit[22]: begin
+      addr_hit[23]: begin
         reg_rdata_next[31:0] = addr_swap_mask_qs;
       end
 
-      addr_hit[23]: begin
+      addr_hit[24]: begin
         reg_rdata_next[31:0] = addr_swap_data_qs;
       end
 
-      addr_hit[24]: begin
+      addr_hit[25]: begin
         reg_rdata_next[7:0] = cmd_info_0_opcode_0_qs;
         reg_rdata_next[8] = cmd_info_0_addr_en_0_qs;
         reg_rdata_next[9] = cmd_info_0_addr_swap_en_0_qs;
@@ -14146,7 +14197,7 @@
         reg_rdata_next[20] = cmd_info_0_payload_dir_0_qs;
       end
 
-      addr_hit[25]: begin
+      addr_hit[26]: begin
         reg_rdata_next[7:0] = cmd_info_1_opcode_1_qs;
         reg_rdata_next[8] = cmd_info_1_addr_en_1_qs;
         reg_rdata_next[9] = cmd_info_1_addr_swap_en_1_qs;
@@ -14158,7 +14209,7 @@
         reg_rdata_next[20] = cmd_info_1_payload_dir_1_qs;
       end
 
-      addr_hit[26]: begin
+      addr_hit[27]: begin
         reg_rdata_next[7:0] = cmd_info_2_opcode_2_qs;
         reg_rdata_next[8] = cmd_info_2_addr_en_2_qs;
         reg_rdata_next[9] = cmd_info_2_addr_swap_en_2_qs;
@@ -14170,7 +14221,7 @@
         reg_rdata_next[20] = cmd_info_2_payload_dir_2_qs;
       end
 
-      addr_hit[27]: begin
+      addr_hit[28]: begin
         reg_rdata_next[7:0] = cmd_info_3_opcode_3_qs;
         reg_rdata_next[8] = cmd_info_3_addr_en_3_qs;
         reg_rdata_next[9] = cmd_info_3_addr_swap_en_3_qs;
@@ -14182,7 +14233,7 @@
         reg_rdata_next[20] = cmd_info_3_payload_dir_3_qs;
       end
 
-      addr_hit[28]: begin
+      addr_hit[29]: begin
         reg_rdata_next[7:0] = cmd_info_4_opcode_4_qs;
         reg_rdata_next[8] = cmd_info_4_addr_en_4_qs;
         reg_rdata_next[9] = cmd_info_4_addr_swap_en_4_qs;
@@ -14194,7 +14245,7 @@
         reg_rdata_next[20] = cmd_info_4_payload_dir_4_qs;
       end
 
-      addr_hit[29]: begin
+      addr_hit[30]: begin
         reg_rdata_next[7:0] = cmd_info_5_opcode_5_qs;
         reg_rdata_next[8] = cmd_info_5_addr_en_5_qs;
         reg_rdata_next[9] = cmd_info_5_addr_swap_en_5_qs;
@@ -14206,7 +14257,7 @@
         reg_rdata_next[20] = cmd_info_5_payload_dir_5_qs;
       end
 
-      addr_hit[30]: begin
+      addr_hit[31]: begin
         reg_rdata_next[7:0] = cmd_info_6_opcode_6_qs;
         reg_rdata_next[8] = cmd_info_6_addr_en_6_qs;
         reg_rdata_next[9] = cmd_info_6_addr_swap_en_6_qs;
@@ -14218,7 +14269,7 @@
         reg_rdata_next[20] = cmd_info_6_payload_dir_6_qs;
       end
 
-      addr_hit[31]: begin
+      addr_hit[32]: begin
         reg_rdata_next[7:0] = cmd_info_7_opcode_7_qs;
         reg_rdata_next[8] = cmd_info_7_addr_en_7_qs;
         reg_rdata_next[9] = cmd_info_7_addr_swap_en_7_qs;
@@ -14230,7 +14281,7 @@
         reg_rdata_next[20] = cmd_info_7_payload_dir_7_qs;
       end
 
-      addr_hit[32]: begin
+      addr_hit[33]: begin
         reg_rdata_next[7:0] = cmd_info_8_opcode_8_qs;
         reg_rdata_next[8] = cmd_info_8_addr_en_8_qs;
         reg_rdata_next[9] = cmd_info_8_addr_swap_en_8_qs;
@@ -14242,7 +14293,7 @@
         reg_rdata_next[20] = cmd_info_8_payload_dir_8_qs;
       end
 
-      addr_hit[33]: begin
+      addr_hit[34]: begin
         reg_rdata_next[7:0] = cmd_info_9_opcode_9_qs;
         reg_rdata_next[8] = cmd_info_9_addr_en_9_qs;
         reg_rdata_next[9] = cmd_info_9_addr_swap_en_9_qs;
@@ -14254,7 +14305,7 @@
         reg_rdata_next[20] = cmd_info_9_payload_dir_9_qs;
       end
 
-      addr_hit[34]: begin
+      addr_hit[35]: begin
         reg_rdata_next[7:0] = cmd_info_10_opcode_10_qs;
         reg_rdata_next[8] = cmd_info_10_addr_en_10_qs;
         reg_rdata_next[9] = cmd_info_10_addr_swap_en_10_qs;
@@ -14266,7 +14317,7 @@
         reg_rdata_next[20] = cmd_info_10_payload_dir_10_qs;
       end
 
-      addr_hit[35]: begin
+      addr_hit[36]: begin
         reg_rdata_next[7:0] = cmd_info_11_opcode_11_qs;
         reg_rdata_next[8] = cmd_info_11_addr_en_11_qs;
         reg_rdata_next[9] = cmd_info_11_addr_swap_en_11_qs;
@@ -14278,7 +14329,7 @@
         reg_rdata_next[20] = cmd_info_11_payload_dir_11_qs;
       end
 
-      addr_hit[36]: begin
+      addr_hit[37]: begin
         reg_rdata_next[7:0] = cmd_info_12_opcode_12_qs;
         reg_rdata_next[8] = cmd_info_12_addr_en_12_qs;
         reg_rdata_next[9] = cmd_info_12_addr_swap_en_12_qs;
@@ -14290,7 +14341,7 @@
         reg_rdata_next[20] = cmd_info_12_payload_dir_12_qs;
       end
 
-      addr_hit[37]: begin
+      addr_hit[38]: begin
         reg_rdata_next[7:0] = cmd_info_13_opcode_13_qs;
         reg_rdata_next[8] = cmd_info_13_addr_en_13_qs;
         reg_rdata_next[9] = cmd_info_13_addr_swap_en_13_qs;
@@ -14302,7 +14353,7 @@
         reg_rdata_next[20] = cmd_info_13_payload_dir_13_qs;
       end
 
-      addr_hit[38]: begin
+      addr_hit[39]: begin
         reg_rdata_next[7:0] = cmd_info_14_opcode_14_qs;
         reg_rdata_next[8] = cmd_info_14_addr_en_14_qs;
         reg_rdata_next[9] = cmd_info_14_addr_swap_en_14_qs;
@@ -14314,7 +14365,7 @@
         reg_rdata_next[20] = cmd_info_14_payload_dir_14_qs;
       end
 
-      addr_hit[39]: begin
+      addr_hit[40]: begin
         reg_rdata_next[7:0] = cmd_info_15_opcode_15_qs;
         reg_rdata_next[8] = cmd_info_15_addr_en_15_qs;
         reg_rdata_next[9] = cmd_info_15_addr_swap_en_15_qs;
diff --git a/hw/ip/spi_device/rtl/spid_status.sv b/hw/ip/spi_device/rtl/spid_status.sv
new file mode 100644
index 0000000..5561232
--- /dev/null
+++ b/hw/ip/spi_device/rtl/spid_status.sv
@@ -0,0 +1,201 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// SPI Flash Read Status handler
+/*
+*/
+
+`include "prim_assert.sv"
+
+module spid_status
+  import spi_device_pkg::*;
+#(
+  // Read Status module recognizes the command by the cmd_info_idx from the
+  // cmdparse logic as the Opcode of the command could vary. Use the index and
+  // determines the return order of the status register.
+  parameter int unsigned StatusCmdIdx[3] = '{
+    spi_device_pkg::CmdInfoReadStatus1,
+    spi_device_pkg::CmdInfoReadStatus2,
+    spi_device_pkg::CmdInfoReadStatus3
+  },
+  parameter int unsigned CmdInfoIdxW = spi_device_pkg::CmdInfoIdxW
+) (
+  input clk_i,
+  input rst_ni,
+
+  input sys_clk_i, // Handling STATUS CSR (ext type)
+  input sys_rst_ni,
+
+  input csb_i, // CSb as a signal (not as a reset)
+
+  // status register from CSR: sys_clk domain
+  // bit [   0]: RW0C by SW / W1S by HW
+  // bit [23:1]: RW
+  input               sys_status_we_i,
+  input  logic [23:0] sys_status_i,
+  output logic [23:0] sys_status_o, // sys_clk domain
+
+  // from cmdparse
+  input sel_datapath_e          sel_dp_i,
+  input cmd_info_t              cmd_info_i,
+  input logic [CmdInfoIdxW-1:0] cmd_info_idx_i,
+
+  output logic      outclk_p2s_valid_o,
+  output spi_byte_t outclk_p2s_byte_o,
+  input  logic      outclk_p2s_sent_i,
+
+  output io_mode_e io_mode_o,
+
+  // receives the busy from other HW
+  input inclk_busy_set_i, // SCK domain
+
+  // indicator of busy for other HW. Mainly to block passthrough
+  output logic inclk_busy_broadcast_o // SCK domain
+);
+
+  ///////////////
+  // Temporary //
+  ///////////////
+  sel_datapath_e unused_dp;
+  assign unused_dp = sel_dp_i;
+
+  logic unused_cmd_info;
+  assign unused_cmd_info = ^{cmd_info_i, cmd_info_idx_i};
+
+  logic unused_p2s_sent;
+  assign unused_p2s_sent = outclk_p2s_sent_i;
+
+  assign outclk_p2s_valid_o = 1'b 0;
+  assign outclk_p2s_byte_o  = '0;
+
+  assign io_mode_o = SingleIO;
+
+  ////////////
+  // Signal //
+  ////////////
+  logic [23:0] status_sck;
+
+  logic unused_status_sck;
+  assign unused_status_sck = ^status_sck;
+
+
+  ////////////////////////////
+  // Status CSR (incl. CDC) //
+  ////////////////////////////
+  //
+  // Flash mode STATUS register is implemented in this module rather than
+  // relying on the regtool. The reason is that the STATUS read by the SPI
+  // host system. The value should be propagated into SCK domain. Due to the
+  // lack of SCK while CSb is de-asserted, it needs special cares to safely
+  // used in SCK.
+  //
+  // Before returning the STATUS register value to the host system
+  // corresponding to the Read Status commands (05h, 35h, 15h), the logic can
+  // get 8 SCK clock edges. The logic synchronizes CSb into SCK domain first.
+  // Then create a pulse to latch the STATUS register in SCK domain.
+  //
+  // If a command is uploaded (handled by spid_upload), it sets BUSY bit to 1.
+  // The value is latched in the SCK domain first. Then, when CSb is
+  // de-asserted, the logic synchronizes CSb into the bus clock domain to
+  // create a pulse signal. That pulse signal will latch the STATUS register
+  // from SCK domain into the bus clock domain.
+  //
+  // The STATUS register in the bus clock domain can be updated only when CSb
+  // is not asserted in order to prevent any CDC issue. The safest way is to
+  // hand the busclock synched CSb signal over to SCK clock domain again but
+  // it may not be possible to latch the register within the 8th posedge of
+  // the SCK if the bus clock is slow.
+  //
+  // BUSY is set by HW. The value is not directly broadcasted to the
+  // passthrough module. It is, first, applied into the bus clock domain. Then
+  // the signal is broadcasted to Passthrough to filter-out the following
+  // commands until the BUSY signal is released.
+
+  logic reg_en; // If 1, register in bus clock domain can be updated by SW
+  logic reg_update; // indicator of HW update (when CSb is de-asserted)
+
+  // Register interface update in bus clock domain
+  logic [23:0] status;
+  //  BUSY
+  always_ff @(posedge sys_clk_i or negedge sys_rst_ni) begin
+    if (!sys_rst_ni) begin
+      status[0] <= 1'b 0;
+    end else if (reg_en && sys_status_we_i && (1'b0 == sys_status_i[0])) begin
+      status[0] <= 1'b 0;
+    end else if (reg_update) begin
+      // TODO: Latch HW value to here
+      status[0] <= status_sck[0];
+    end
+  end
+  //  rest of STATUS
+  always_ff @(posedge sys_clk_i or negedge sys_rst_ni) begin
+    if (!sys_rst_ni) begin
+      status[23:1] <= '0;
+    end else if (reg_en && sys_status_we_i) begin
+      status[23:1] <= sys_status_i[23:1];
+    end
+  end
+
+  assign sys_status_o = status;
+
+  // busy_broadcast
+  prim_flop_2sync #(
+    .Width      (1),
+    .ResetValue (1'b 0)
+  ) u_busy_sync (
+    .clk_i,
+    .rst_ni,
+    .d_i (status[0]),
+    .q_o (inclk_busy_broadcast_o)
+  );
+
+  // CSb pulse
+  logic csb_sync_d, csb_sync_q, csb_asserted_pulse;
+  prim_flop_2sync #(
+    .Width      (1),
+    .ResetValue (1'b 1)
+  ) u_csb_sync (
+    .clk_i,
+    .rst_ni, //Use CSb as a reset
+    .d_i (1'b 0),
+    .q_o (csb_sync_d)
+  );
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) csb_sync_q <= 1'b 1;
+    else         csb_sync_q <= csb_sync_d;
+  end
+
+  assign csb_asserted_pulse = csb_sync_q && !csb_sync_d;
+
+  // CSb de-asserted pulse is used as reg_update.
+  // TODO: merge this to the top then receive the signal through the module
+  // port?
+  logic reg_en_q;
+  prim_flop_2sync #(
+    .Width      (1),
+    .ResetValue (1'b 1)
+  ) u_csb_sync_sysclk (
+    .clk_i  (sys_clk_i),
+    .rst_ni (sys_rst_ni),
+    .d_i    (csb_i),
+    .q_o    (reg_en)
+  );
+  always_ff @(posedge sys_clk_i or negedge sys_rst_ni) begin
+    if (!sys_rst_ni) reg_en_q <= 1'b 1;
+    else             reg_en_q <= reg_en;
+  end
+  assign reg_update = !reg_en_q && reg_en;
+
+  // Status in SCK
+  always_ff @(posedge clk_i or negedge sys_rst_ni) begin
+    if (!sys_rst_ni) begin
+      status_sck <= 24'h 0;
+    end else if (csb_asserted_pulse) begin
+      status_sck <= status;
+    end else if (inclk_busy_set_i) begin
+      status_sck[0] <= 1'b 1;
+    end
+  end
+
+endmodule : spid_status
diff --git a/hw/ip/spi_device/spi_device.core b/hw/ip/spi_device/spi_device.core
index 3cd7197..74d7053 100644
--- a/hw/ip/spi_device/spi_device.core
+++ b/hw/ip/spi_device/spi_device.core
@@ -26,6 +26,7 @@
       - rtl/spid_readsram.sv
       - rtl/spi_readcmd.sv
       - rtl/spi_passthrough.sv
+      - rtl/spid_status.sv
       - rtl/spi_s2p.sv
       - rtl/spi_p2s.sv
       - rtl/spi_device.sv