[spi_device] Define JEDEC ID CSR

This commit implements `Read JEDEC ID` command process logic. It follows
the datapath of Read Status command logic.

The logic latches JEDEC_ID CSR when CSb is asserted by the host system.
Then uses the latched value along the SPI transaction. The return order
is Manufacturer ID (JEDEC_ID[23:16]) then Byte 1 of JEDEC ID , then byte
0.

If the host system keeps asserting CSb and toggles the SCK, the logic
sends all 0 following the last byte of JEDEC ID.

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 e8c2e94..ffe4cee 100644
--- a/hw/ip/spi_device/data/spi_device.hjson
+++ b/hw/ip/spi_device/data/spi_device.hjson
@@ -429,6 +429,23 @@
         } // f: status
       ]
     } // R: FLASH_STATUS
+    {
+      name: "JEDEC_ID"
+      desc: '''JEDEC ID register.
+        '''
+      swaccess: "rw"
+      hwaccess:  "hro"
+      fields: [
+        { bits: "23:16"
+          name: "mf"
+          desc: "Manufacturer ID"
+        } // f: manufacturer id
+        { bits: "15:0"
+          name: "id"
+          desc: "Device ID"
+        } // f: device id
+      ]
+    } // R: JEDEC_ID
     { multireg: {
         cname: "SPI_DEVICE"
         name:  "CMD_FILTER"
diff --git a/hw/ip/spi_device/lint/spi_device.waiver b/hw/ip/spi_device/lint/spi_device.waiver
index a3ba357..d211764 100644
--- a/hw/ip/spi_device/lint/spi_device.waiver
+++ b/hw/ip/spi_device/lint/spi_device.waiver
@@ -87,6 +87,9 @@
 waive -rules TERMINAL_STATE -location {spi_readcmd.sv} \
       -regexp {Terminal state 'Main(Output|Error)' is detected} \
       -comment "Intentional dead-end. CSb will reset"
+waive -rules TERMINAL_STATE -location {spid_jedec.sv} \
+      -regexp {Terminal state 'StActive' is detected} \
+      -comment "Intentional dead-end. CSb will reset"
 
 # async resets
 waive -rules RESET_DRIVER -location {spi_device.sv} \
diff --git a/hw/ip/spi_device/rtl/spi_device.sv b/hw/ip/spi_device/rtl/spi_device.sv
index ee95687..01f1e1c 100644
--- a/hw/ip/spi_device/rtl/spi_device.sv
+++ b/hw/ip/spi_device/rtl/spi_device.sv
@@ -202,6 +202,9 @@
   logic status_busy_set; // set by HW (upload)
   logic status_busy_broadcast; // from spid_status
 
+  // Jedec ID
+  logic [23:0] jedec_id;
+
   //////////////////////////////////////////////////////////////////////
   // Connect phase (between control signals above and register module //
   //////////////////////////////////////////////////////////////////////
@@ -384,6 +387,9 @@
     end
   end
 
+  // Jedec ID
+  assign jedec_id = {reg2hw.jedec_id.mf.q, reg2hw.jedec_id.id.q};
+
   // Passthrough config: value shall be stable while SPI transaction is active
   //assign cmd_filter = reg2hw.cmd_filter.q;
   always_comb begin
@@ -576,6 +582,24 @@
 
   assign csb_deasserted_busclk = !csb_sync_q && csb_sync;
 
+  // CSb pulse
+  logic csb_sckin_sync_d, csb_sckin_sync_q, csb_asserted_pulse_sckin;
+  prim_flop_2sync #(
+    .Width      (1),
+    .ResetValue (1'b 1)
+  ) u_csb_sckin_sync (
+    .clk_i (clk_spi_in_buf),
+    .rst_ni(rst_spi_n), //Use CSb as a reset
+    .d_i (1'b 0),
+    .q_o (csb_sckin_sync_d)
+  );
+  always_ff @(posedge clk_spi_in_buf or negedge rst_spi_n) begin
+    if (!rst_spi_n) csb_sckin_sync_q <= 1'b 1;
+    else            csb_sckin_sync_q <= csb_sckin_sync_d;
+  end
+
+  assign csb_asserted_pulse_sckin = csb_sckin_sync_q && !csb_sckin_sync_d;
+
   //////////////////////////////
   // SPI_DEVICE mode selector //
   //////////////////////////////
@@ -672,7 +696,14 @@
 
             // default memory (tied)
           end
-          // DpReadSFDP:
+
+          DpReadSFDP: begin
+            io_mode = sub_iomode[IoModeJedec];
+
+            p2s_valid = sub_p2s_valid[IoModeJedec];
+            p2s_data  = sub_p2s_data[IoModeJedec];
+            sub_p2s_sent[IoModeJedec] = p2s_sent;
+          end
           // DpReadJEDEC:
           // DpUpload:
           // DpUnknown:
@@ -901,7 +932,6 @@
     .read_watermark_o ()
   );
 
-
   // Begin: Read Status ==============================================
   logic readstatus_qe;
   logic [23:0] readstatus_q;
@@ -952,15 +982,16 @@
   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],
-                              sub_sram_rvalid[IoModeStatus],
-                              sub_sram_rdata [IoModeStatus],
-                              sub_sram_rerror[IoModeStatus]
-                            };
+  logic unused_sub_sram_status;
+  assign unused_sub_sram_status = ^{
+    sub_sram_req   [IoModeStatus],
+    sub_sram_write [IoModeStatus],
+    sub_sram_addr  [IoModeStatus],
+    sub_sram_wdata [IoModeStatus],
+    sub_sram_rvalid[IoModeStatus],
+    sub_sram_rdata [IoModeStatus],
+    sub_sram_rerror[IoModeStatus]
+  };
   assign sub_sram_req[IoModeStatus]   = 1'b 0;
   assign sub_sram_write[IoModeStatus] = 1'b 0;
   assign sub_sram_addr[IoModeStatus]  = '0;
@@ -968,6 +999,42 @@
 
   // End: Read Status ------------------------------------------------
 
+  spid_jedec u_jedec (
+    .clk_i  (clk_spi_in_buf),
+    .rst_ni (rst_spi_n),
+
+    .clk_out_i (clk_spi_out_buf),
+
+    .inclk_csb_asserted_pulse_i (csb_asserted_pulse_sckin),
+
+    .sys_jedec_i (jedec_id),
+
+    .io_mode_o (sub_iomode[IoModeJedec]),
+
+    .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[IoModeJedec]),
+    .outclk_p2s_byte_o  (sub_p2s_data[IoModeJedec]),
+    .outclk_p2s_sent_i  (sub_p2s_sent[IoModeJedec])
+  );
+  // Tie unused
+  logic unused_sub_sram_jedec;
+  assign unused_sub_sram_jedec = ^{
+    sub_sram_req   [IoModeJedec],
+    sub_sram_write [IoModeJedec],
+    sub_sram_addr  [IoModeJedec],
+    sub_sram_wdata [IoModeJedec],
+    sub_sram_rvalid[IoModeJedec],
+    sub_sram_rdata [IoModeJedec],
+    sub_sram_rerror[IoModeJedec]
+  };
+  assign sub_sram_req[IoModeJedec]   = 1'b 0;
+  assign sub_sram_write[IoModeJedec] = 1'b 0;
+  assign sub_sram_addr[IoModeJedec]  = '0;
+  assign sub_sram_wdata[IoModeJedec] = '0;
+
   /////////////////////
   // 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 48dc399..5c1def4 100644
--- a/hw/ip/spi_device/rtl/spi_device_pkg.sv
+++ b/hw/ip/spi_device/rtl/spi_device_pkg.sv
@@ -205,7 +205,8 @@
     IoModeCmdParse = 1,
     IoModeReadCmd  = 2,
     IoModeStatus   = 3,
-    IoModeEnd      = 4 // Indicate of Length
+    IoModeJedec    = 4,
+    IoModeEnd      = 5 // 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 755b28b..6f32f7f 100644
--- a/hw/ip/spi_device/rtl/spi_device_reg_pkg.sv
+++ b/hw/ip/spi_device/rtl/spi_device_reg_pkg.sv
@@ -182,6 +182,15 @@
   } spi_device_reg2hw_flash_status_reg_t;
 
   typedef struct packed {
+    struct packed {
+      logic [15:0] q;
+    } id;
+    struct packed {
+      logic [7:0]  q;
+    } mf;
+  } spi_device_reg2hw_jedec_id_reg_t;
+
+  typedef struct packed {
     logic        q;
   } spi_device_reg2hw_cmd_filter_mreg_t;
 
@@ -309,18 +318,19 @@
 
   // Register -> HW type
   typedef struct packed {
-    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_intr_state_reg_t intr_state; // [878:873]
+    spi_device_reg2hw_intr_enable_reg_t intr_enable; // [872:867]
+    spi_device_reg2hw_intr_test_reg_t intr_test; // [866:855]
+    spi_device_reg2hw_alert_test_reg_t alert_test; // [854:853]
+    spi_device_reg2hw_control_reg_t control; // [852:847]
+    spi_device_reg2hw_cfg_reg_t cfg; // [846:834]
+    spi_device_reg2hw_fifo_level_reg_t fifo_level; // [833:802]
+    spi_device_reg2hw_rxf_ptr_reg_t rxf_ptr; // [801:786]
+    spi_device_reg2hw_txf_ptr_reg_t txf_ptr; // [785:770]
+    spi_device_reg2hw_rxf_addr_reg_t rxf_addr; // [769:738]
+    spi_device_reg2hw_txf_addr_reg_t txf_addr; // [737:706]
+    spi_device_reg2hw_flash_status_reg_t flash_status; // [705:680]
+    spi_device_reg2hw_jedec_id_reg_t jedec_id; // [679: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]
@@ -354,32 +364,33 @@
   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_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;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_JEDEC_ID_OFFSET = 13'h 3c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_0_OFFSET = 13'h 40;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_1_OFFSET = 13'h 44;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_2_OFFSET = 13'h 48;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_3_OFFSET = 13'h 4c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_4_OFFSET = 13'h 50;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_5_OFFSET = 13'h 54;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_6_OFFSET = 13'h 58;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_FILTER_7_OFFSET = 13'h 5c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_ADDR_SWAP_MASK_OFFSET = 13'h 60;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_ADDR_SWAP_DATA_OFFSET = 13'h 64;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_0_OFFSET = 13'h 68;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_1_OFFSET = 13'h 6c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_2_OFFSET = 13'h 70;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_3_OFFSET = 13'h 74;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_4_OFFSET = 13'h 78;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_5_OFFSET = 13'h 7c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_6_OFFSET = 13'h 80;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_7_OFFSET = 13'h 84;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_8_OFFSET = 13'h 88;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_9_OFFSET = 13'h 8c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_10_OFFSET = 13'h 90;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_11_OFFSET = 13'h 94;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_12_OFFSET = 13'h 98;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_13_OFFSET = 13'h 9c;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_14_OFFSET = 13'h a0;
+  parameter logic [BlockAw-1:0] SPI_DEVICE_CMD_INFO_15_OFFSET = 13'h a4;
 
   // Reset values for hwext registers and their fields
   parameter logic [5:0] SPI_DEVICE_INTR_TEST_RESVAL = 6'h 0;
@@ -421,6 +432,7 @@
     SPI_DEVICE_TXF_ADDR,
     SPI_DEVICE_LAST_READ_ADDR,
     SPI_DEVICE_FLASH_STATUS,
+    SPI_DEVICE_JEDEC_ID,
     SPI_DEVICE_CMD_FILTER_0,
     SPI_DEVICE_CMD_FILTER_1,
     SPI_DEVICE_CMD_FILTER_2,
@@ -450,7 +462,7 @@
   } spi_device_id_e;
 
   // Register width information to check illegal writes
-  parameter logic [3:0] SPI_DEVICE_PERMIT [41] = '{
+  parameter logic [3:0] SPI_DEVICE_PERMIT [42] = '{
     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
@@ -466,32 +478,33 @@
     4'b 1111, // index[12] SPI_DEVICE_TXF_ADDR
     4'b 1111, // index[13] SPI_DEVICE_LAST_READ_ADDR
     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
+    4'b 0111, // index[15] SPI_DEVICE_JEDEC_ID
+    4'b 1111, // index[16] SPI_DEVICE_CMD_FILTER_0
+    4'b 1111, // index[17] SPI_DEVICE_CMD_FILTER_1
+    4'b 1111, // index[18] SPI_DEVICE_CMD_FILTER_2
+    4'b 1111, // index[19] SPI_DEVICE_CMD_FILTER_3
+    4'b 1111, // index[20] SPI_DEVICE_CMD_FILTER_4
+    4'b 1111, // index[21] SPI_DEVICE_CMD_FILTER_5
+    4'b 1111, // index[22] SPI_DEVICE_CMD_FILTER_6
+    4'b 1111, // index[23] SPI_DEVICE_CMD_FILTER_7
+    4'b 1111, // index[24] SPI_DEVICE_ADDR_SWAP_MASK
+    4'b 1111, // index[25] SPI_DEVICE_ADDR_SWAP_DATA
+    4'b 0111, // index[26] SPI_DEVICE_CMD_INFO_0
+    4'b 0111, // index[27] SPI_DEVICE_CMD_INFO_1
+    4'b 0111, // index[28] SPI_DEVICE_CMD_INFO_2
+    4'b 0111, // index[29] SPI_DEVICE_CMD_INFO_3
+    4'b 0111, // index[30] SPI_DEVICE_CMD_INFO_4
+    4'b 0111, // index[31] SPI_DEVICE_CMD_INFO_5
+    4'b 0111, // index[32] SPI_DEVICE_CMD_INFO_6
+    4'b 0111, // index[33] SPI_DEVICE_CMD_INFO_7
+    4'b 0111, // index[34] SPI_DEVICE_CMD_INFO_8
+    4'b 0111, // index[35] SPI_DEVICE_CMD_INFO_9
+    4'b 0111, // index[36] SPI_DEVICE_CMD_INFO_10
+    4'b 0111, // index[37] SPI_DEVICE_CMD_INFO_11
+    4'b 0111, // index[38] SPI_DEVICE_CMD_INFO_12
+    4'b 0111, // index[39] SPI_DEVICE_CMD_INFO_13
+    4'b 0111, // index[40] SPI_DEVICE_CMD_INFO_14
+    4'b 0111  // index[41] 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 e3e0836..7c4d712 100644
--- a/hw/ip/spi_device/rtl/spi_device_reg_top.sv
+++ b/hw/ip/spi_device/rtl/spi_device_reg_top.sv
@@ -257,6 +257,11 @@
   logic flash_status_busy_wd;
   logic [22:0] flash_status_status_qs;
   logic [22:0] flash_status_status_wd;
+  logic jedec_id_we;
+  logic [15:0] jedec_id_id_qs;
+  logic [15:0] jedec_id_id_wd;
+  logic [7:0] jedec_id_mf_qs;
+  logic [7:0] jedec_id_mf_wd;
   logic cmd_filter_0_we;
   logic cmd_filter_0_filter_0_qs;
   logic cmd_filter_0_filter_0_wd;
@@ -2245,6 +2250,60 @@
   );
 
 
+  // R[jedec_id]: V(False)
+
+  //   F[id]: 15:0
+  prim_subreg #(
+    .DW      (16),
+    .SwAccess(prim_subreg_pkg::SwAccessRW),
+    .RESVAL  (16'h0)
+  ) u_jedec_id_id (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (jedec_id_we),
+    .wd     (jedec_id_id_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.jedec_id.id.q),
+
+    // to register interface (read)
+    .qs     (jedec_id_id_qs)
+  );
+
+
+  //   F[mf]: 23:16
+  prim_subreg #(
+    .DW      (8),
+    .SwAccess(prim_subreg_pkg::SwAccessRW),
+    .RESVAL  (8'h0)
+  ) u_jedec_id_mf (
+    .clk_i   (clk_i),
+    .rst_ni  (rst_ni),
+
+    // from register interface
+    .we     (jedec_id_we),
+    .wd     (jedec_id_mf_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.jedec_id.mf.q),
+
+    // to register interface (read)
+    .qs     (jedec_id_mf_qs)
+  );
+
+
 
   // Subregister 0 of Multireg cmd_filter
   // R[cmd_filter_0]: V(False)
@@ -12777,7 +12836,7 @@
 
 
 
-  logic [40:0] addr_hit;
+  logic [41:0] addr_hit;
   always_comb begin
     addr_hit = '0;
     addr_hit[ 0] = (reg_addr == SPI_DEVICE_INTR_STATE_OFFSET);
@@ -12795,32 +12854,33 @@
     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_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);
+    addr_hit[15] = (reg_addr == SPI_DEVICE_JEDEC_ID_OFFSET);
+    addr_hit[16] = (reg_addr == SPI_DEVICE_CMD_FILTER_0_OFFSET);
+    addr_hit[17] = (reg_addr == SPI_DEVICE_CMD_FILTER_1_OFFSET);
+    addr_hit[18] = (reg_addr == SPI_DEVICE_CMD_FILTER_2_OFFSET);
+    addr_hit[19] = (reg_addr == SPI_DEVICE_CMD_FILTER_3_OFFSET);
+    addr_hit[20] = (reg_addr == SPI_DEVICE_CMD_FILTER_4_OFFSET);
+    addr_hit[21] = (reg_addr == SPI_DEVICE_CMD_FILTER_5_OFFSET);
+    addr_hit[22] = (reg_addr == SPI_DEVICE_CMD_FILTER_6_OFFSET);
+    addr_hit[23] = (reg_addr == SPI_DEVICE_CMD_FILTER_7_OFFSET);
+    addr_hit[24] = (reg_addr == SPI_DEVICE_ADDR_SWAP_MASK_OFFSET);
+    addr_hit[25] = (reg_addr == SPI_DEVICE_ADDR_SWAP_DATA_OFFSET);
+    addr_hit[26] = (reg_addr == SPI_DEVICE_CMD_INFO_0_OFFSET);
+    addr_hit[27] = (reg_addr == SPI_DEVICE_CMD_INFO_1_OFFSET);
+    addr_hit[28] = (reg_addr == SPI_DEVICE_CMD_INFO_2_OFFSET);
+    addr_hit[29] = (reg_addr == SPI_DEVICE_CMD_INFO_3_OFFSET);
+    addr_hit[30] = (reg_addr == SPI_DEVICE_CMD_INFO_4_OFFSET);
+    addr_hit[31] = (reg_addr == SPI_DEVICE_CMD_INFO_5_OFFSET);
+    addr_hit[32] = (reg_addr == SPI_DEVICE_CMD_INFO_6_OFFSET);
+    addr_hit[33] = (reg_addr == SPI_DEVICE_CMD_INFO_7_OFFSET);
+    addr_hit[34] = (reg_addr == SPI_DEVICE_CMD_INFO_8_OFFSET);
+    addr_hit[35] = (reg_addr == SPI_DEVICE_CMD_INFO_9_OFFSET);
+    addr_hit[36] = (reg_addr == SPI_DEVICE_CMD_INFO_10_OFFSET);
+    addr_hit[37] = (reg_addr == SPI_DEVICE_CMD_INFO_11_OFFSET);
+    addr_hit[38] = (reg_addr == SPI_DEVICE_CMD_INFO_12_OFFSET);
+    addr_hit[39] = (reg_addr == SPI_DEVICE_CMD_INFO_13_OFFSET);
+    addr_hit[40] = (reg_addr == SPI_DEVICE_CMD_INFO_14_OFFSET);
+    addr_hit[41] = (reg_addr == SPI_DEVICE_CMD_INFO_15_OFFSET);
   end
 
   assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -12868,7 +12928,8 @@
                (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[40] & (|(SPI_DEVICE_PERMIT[40] & ~reg_be)))));
+               (addr_hit[40] & (|(SPI_DEVICE_PERMIT[40] & ~reg_be))) |
+               (addr_hit[41] & (|(SPI_DEVICE_PERMIT[41] & ~reg_be)))));
   end
   assign intr_state_we = addr_hit[0] & reg_we & !reg_error;
 
@@ -12966,7 +13027,12 @@
   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 jedec_id_we = addr_hit[15] & reg_we & !reg_error;
+
+  assign jedec_id_id_wd = reg_wdata[15:0];
+
+  assign jedec_id_mf_wd = reg_wdata[23:16];
+  assign cmd_filter_0_we = addr_hit[16] & reg_we & !reg_error;
 
   assign cmd_filter_0_filter_0_wd = reg_wdata[0];
 
@@ -13031,7 +13097,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[16] & reg_we & !reg_error;
+  assign cmd_filter_1_we = addr_hit[17] & reg_we & !reg_error;
 
   assign cmd_filter_1_filter_32_wd = reg_wdata[0];
 
@@ -13096,7 +13162,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[17] & reg_we & !reg_error;
+  assign cmd_filter_2_we = addr_hit[18] & reg_we & !reg_error;
 
   assign cmd_filter_2_filter_64_wd = reg_wdata[0];
 
@@ -13161,7 +13227,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[18] & reg_we & !reg_error;
+  assign cmd_filter_3_we = addr_hit[19] & reg_we & !reg_error;
 
   assign cmd_filter_3_filter_96_wd = reg_wdata[0];
 
@@ -13226,7 +13292,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[19] & reg_we & !reg_error;
+  assign cmd_filter_4_we = addr_hit[20] & reg_we & !reg_error;
 
   assign cmd_filter_4_filter_128_wd = reg_wdata[0];
 
@@ -13291,7 +13357,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[20] & reg_we & !reg_error;
+  assign cmd_filter_5_we = addr_hit[21] & reg_we & !reg_error;
 
   assign cmd_filter_5_filter_160_wd = reg_wdata[0];
 
@@ -13356,7 +13422,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[21] & reg_we & !reg_error;
+  assign cmd_filter_6_we = addr_hit[22] & reg_we & !reg_error;
 
   assign cmd_filter_6_filter_192_wd = reg_wdata[0];
 
@@ -13421,7 +13487,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[22] & reg_we & !reg_error;
+  assign cmd_filter_7_we = addr_hit[23] & reg_we & !reg_error;
 
   assign cmd_filter_7_filter_224_wd = reg_wdata[0];
 
@@ -13486,13 +13552,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[23] & reg_we & !reg_error;
+  assign addr_swap_mask_we = addr_hit[24] & reg_we & !reg_error;
 
   assign addr_swap_mask_wd = reg_wdata[31:0];
-  assign addr_swap_data_we = addr_hit[24] & reg_we & !reg_error;
+  assign addr_swap_data_we = addr_hit[25] & reg_we & !reg_error;
 
   assign addr_swap_data_wd = reg_wdata[31:0];
-  assign cmd_info_0_we = addr_hit[25] & reg_we & !reg_error;
+  assign cmd_info_0_we = addr_hit[26] & reg_we & !reg_error;
 
   assign cmd_info_0_opcode_0_wd = reg_wdata[7:0];
 
@@ -13511,7 +13577,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[26] & reg_we & !reg_error;
+  assign cmd_info_1_we = addr_hit[27] & reg_we & !reg_error;
 
   assign cmd_info_1_opcode_1_wd = reg_wdata[7:0];
 
@@ -13530,7 +13596,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[27] & reg_we & !reg_error;
+  assign cmd_info_2_we = addr_hit[28] & reg_we & !reg_error;
 
   assign cmd_info_2_opcode_2_wd = reg_wdata[7:0];
 
@@ -13549,7 +13615,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[28] & reg_we & !reg_error;
+  assign cmd_info_3_we = addr_hit[29] & reg_we & !reg_error;
 
   assign cmd_info_3_opcode_3_wd = reg_wdata[7:0];
 
@@ -13568,7 +13634,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[29] & reg_we & !reg_error;
+  assign cmd_info_4_we = addr_hit[30] & reg_we & !reg_error;
 
   assign cmd_info_4_opcode_4_wd = reg_wdata[7:0];
 
@@ -13587,7 +13653,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[30] & reg_we & !reg_error;
+  assign cmd_info_5_we = addr_hit[31] & reg_we & !reg_error;
 
   assign cmd_info_5_opcode_5_wd = reg_wdata[7:0];
 
@@ -13606,7 +13672,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[31] & reg_we & !reg_error;
+  assign cmd_info_6_we = addr_hit[32] & reg_we & !reg_error;
 
   assign cmd_info_6_opcode_6_wd = reg_wdata[7:0];
 
@@ -13625,7 +13691,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[32] & reg_we & !reg_error;
+  assign cmd_info_7_we = addr_hit[33] & reg_we & !reg_error;
 
   assign cmd_info_7_opcode_7_wd = reg_wdata[7:0];
 
@@ -13644,7 +13710,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[33] & reg_we & !reg_error;
+  assign cmd_info_8_we = addr_hit[34] & reg_we & !reg_error;
 
   assign cmd_info_8_opcode_8_wd = reg_wdata[7:0];
 
@@ -13663,7 +13729,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[34] & reg_we & !reg_error;
+  assign cmd_info_9_we = addr_hit[35] & reg_we & !reg_error;
 
   assign cmd_info_9_opcode_9_wd = reg_wdata[7:0];
 
@@ -13682,7 +13748,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[35] & reg_we & !reg_error;
+  assign cmd_info_10_we = addr_hit[36] & reg_we & !reg_error;
 
   assign cmd_info_10_opcode_10_wd = reg_wdata[7:0];
 
@@ -13701,7 +13767,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[36] & reg_we & !reg_error;
+  assign cmd_info_11_we = addr_hit[37] & reg_we & !reg_error;
 
   assign cmd_info_11_opcode_11_wd = reg_wdata[7:0];
 
@@ -13720,7 +13786,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[37] & reg_we & !reg_error;
+  assign cmd_info_12_we = addr_hit[38] & reg_we & !reg_error;
 
   assign cmd_info_12_opcode_12_wd = reg_wdata[7:0];
 
@@ -13739,7 +13805,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[38] & reg_we & !reg_error;
+  assign cmd_info_13_we = addr_hit[39] & reg_we & !reg_error;
 
   assign cmd_info_13_opcode_13_wd = reg_wdata[7:0];
 
@@ -13758,7 +13824,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[39] & reg_we & !reg_error;
+  assign cmd_info_14_we = addr_hit[40] & reg_we & !reg_error;
 
   assign cmd_info_14_opcode_14_wd = reg_wdata[7:0];
 
@@ -13777,7 +13843,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[40] & reg_we & !reg_error;
+  assign cmd_info_15_we = addr_hit[41] & reg_we & !reg_error;
 
   assign cmd_info_15_opcode_15_wd = reg_wdata[7:0];
 
@@ -13898,6 +13964,11 @@
       end
 
       addr_hit[15]: begin
+        reg_rdata_next[15:0] = jedec_id_id_qs;
+        reg_rdata_next[23:16] = jedec_id_mf_qs;
+      end
+
+      addr_hit[16]: 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;
@@ -13932,7 +14003,7 @@
         reg_rdata_next[31] = cmd_filter_0_filter_31_qs;
       end
 
-      addr_hit[16]: begin
+      addr_hit[17]: 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;
@@ -13967,7 +14038,7 @@
         reg_rdata_next[31] = cmd_filter_1_filter_63_qs;
       end
 
-      addr_hit[17]: begin
+      addr_hit[18]: 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;
@@ -14002,7 +14073,7 @@
         reg_rdata_next[31] = cmd_filter_2_filter_95_qs;
       end
 
-      addr_hit[18]: begin
+      addr_hit[19]: 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;
@@ -14037,7 +14108,7 @@
         reg_rdata_next[31] = cmd_filter_3_filter_127_qs;
       end
 
-      addr_hit[19]: begin
+      addr_hit[20]: 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;
@@ -14072,7 +14143,7 @@
         reg_rdata_next[31] = cmd_filter_4_filter_159_qs;
       end
 
-      addr_hit[20]: begin
+      addr_hit[21]: 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;
@@ -14107,7 +14178,7 @@
         reg_rdata_next[31] = cmd_filter_5_filter_191_qs;
       end
 
-      addr_hit[21]: begin
+      addr_hit[22]: 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;
@@ -14142,7 +14213,7 @@
         reg_rdata_next[31] = cmd_filter_6_filter_223_qs;
       end
 
-      addr_hit[22]: begin
+      addr_hit[23]: 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;
@@ -14177,15 +14248,15 @@
         reg_rdata_next[31] = cmd_filter_7_filter_255_qs;
       end
 
-      addr_hit[23]: begin
+      addr_hit[24]: begin
         reg_rdata_next[31:0] = addr_swap_mask_qs;
       end
 
-      addr_hit[24]: begin
+      addr_hit[25]: begin
         reg_rdata_next[31:0] = addr_swap_data_qs;
       end
 
-      addr_hit[25]: begin
+      addr_hit[26]: 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;
@@ -14197,7 +14268,7 @@
         reg_rdata_next[20] = cmd_info_0_payload_dir_0_qs;
       end
 
-      addr_hit[26]: begin
+      addr_hit[27]: 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;
@@ -14209,7 +14280,7 @@
         reg_rdata_next[20] = cmd_info_1_payload_dir_1_qs;
       end
 
-      addr_hit[27]: begin
+      addr_hit[28]: 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;
@@ -14221,7 +14292,7 @@
         reg_rdata_next[20] = cmd_info_2_payload_dir_2_qs;
       end
 
-      addr_hit[28]: begin
+      addr_hit[29]: 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;
@@ -14233,7 +14304,7 @@
         reg_rdata_next[20] = cmd_info_3_payload_dir_3_qs;
       end
 
-      addr_hit[29]: begin
+      addr_hit[30]: 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;
@@ -14245,7 +14316,7 @@
         reg_rdata_next[20] = cmd_info_4_payload_dir_4_qs;
       end
 
-      addr_hit[30]: begin
+      addr_hit[31]: 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;
@@ -14257,7 +14328,7 @@
         reg_rdata_next[20] = cmd_info_5_payload_dir_5_qs;
       end
 
-      addr_hit[31]: begin
+      addr_hit[32]: 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;
@@ -14269,7 +14340,7 @@
         reg_rdata_next[20] = cmd_info_6_payload_dir_6_qs;
       end
 
-      addr_hit[32]: begin
+      addr_hit[33]: 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;
@@ -14281,7 +14352,7 @@
         reg_rdata_next[20] = cmd_info_7_payload_dir_7_qs;
       end
 
-      addr_hit[33]: begin
+      addr_hit[34]: 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;
@@ -14293,7 +14364,7 @@
         reg_rdata_next[20] = cmd_info_8_payload_dir_8_qs;
       end
 
-      addr_hit[34]: begin
+      addr_hit[35]: 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;
@@ -14305,7 +14376,7 @@
         reg_rdata_next[20] = cmd_info_9_payload_dir_9_qs;
       end
 
-      addr_hit[35]: begin
+      addr_hit[36]: 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;
@@ -14317,7 +14388,7 @@
         reg_rdata_next[20] = cmd_info_10_payload_dir_10_qs;
       end
 
-      addr_hit[36]: begin
+      addr_hit[37]: 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;
@@ -14329,7 +14400,7 @@
         reg_rdata_next[20] = cmd_info_11_payload_dir_11_qs;
       end
 
-      addr_hit[37]: begin
+      addr_hit[38]: 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;
@@ -14341,7 +14412,7 @@
         reg_rdata_next[20] = cmd_info_12_payload_dir_12_qs;
       end
 
-      addr_hit[38]: begin
+      addr_hit[39]: 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;
@@ -14353,7 +14424,7 @@
         reg_rdata_next[20] = cmd_info_13_payload_dir_13_qs;
       end
 
-      addr_hit[39]: begin
+      addr_hit[40]: 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;
@@ -14365,7 +14436,7 @@
         reg_rdata_next[20] = cmd_info_14_payload_dir_14_qs;
       end
 
-      addr_hit[40]: begin
+      addr_hit[41]: 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_jedec.sv b/hw/ip/spi_device/rtl/spid_jedec.sv
new file mode 100644
index 0000000..c13585d
--- /dev/null
+++ b/hw/ip/spi_device/rtl/spid_jedec.sv
@@ -0,0 +1,142 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// SPI Flash Read JEDEC ID handler
+
+`include "prim_assert.sv"
+
+module spid_jedec
+  import spi_device_pkg::*;
+(
+  input clk_i,
+  input rst_ni,
+
+  input clk_out_i, // Output clock (inverted SCK)
+
+  input inclk_csb_asserted_pulse_i,
+
+  input logic [23:0] sys_jedec_i, // from CSR
+
+  output io_mode_e io_mode_o,
+
+  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
+);
+
+  typedef enum logic {
+    StIdle,
+    StActive
+  } st_e;
+  st_e st_q, st_d;
+
+  ////////////
+  // Signal //
+  ////////////
+
+  assign io_mode_o = SingleIO;
+
+  logic [23:0] jedec;
+
+  logic      p2s_valid;
+  spi_byte_t p2s_byte;
+
+  logic next_byte;
+  logic [1:0] byte_sel_q, byte_sel_d;
+
+  // Unused
+  logic unused_cmd_info;
+  assign unused_cmd_info = ^{cmd_info_i , cmd_info_idx_i};
+
+  //////////////
+  // Datapath //
+  //////////////
+
+  // Jedec latch
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni)                         jedec <= 24'h 0;
+    else if (inclk_csb_asserted_pulse_i) jedec <= sys_jedec_i;
+  end
+
+  // Output to Parallel-to-Serial
+  always_ff @(posedge clk_out_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      outclk_p2s_valid_o <= 1'b 0;
+      outclk_p2s_byte_o  <= 8'h 0;
+    end else begin
+      outclk_p2s_valid_o <= p2s_valid;
+      outclk_p2s_byte_o  <= p2s_byte;
+    end
+  end
+
+  always_comb begin : p2s_byte_logic
+    p2s_byte = 8'h 0;
+
+    if (st_q == StIdle) begin
+      // Manufacturer ID always
+      p2s_byte = jedec[23:16];
+    end else if (byte_sel_q == 2'h 3) begin
+      // End of the transfer but host keep toggles SCK. Sending out 0 always
+      p2s_byte = 8'h 0;
+    end else begin
+      // based on byte_sel_q
+      p2s_byte = jedec[8*byte_sel_q+:8];
+    end
+  end : p2s_byte_logic
+
+  // Byte selection
+  always_ff @(posedge clk_i or negedge rst_ni) begin : byte_sel_latch
+    if (!rst_ni)        byte_sel_q <= 8'h 2; // select manufacturer id
+    else if (next_byte) byte_sel_q <= byte_sel_d;
+  end : byte_sel_latch
+
+  assign byte_sel_d = (byte_sel_q == 2'b 11) ? 2'b 11 : byte_sel_q - 1'b 1;
+
+  ///////////
+  // State //
+  ///////////
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin : state_latch
+    if (!rst_ni) st_q <= StIdle;
+    else         st_q <= st_d;
+  end : state_latch
+
+  always_comb begin : next_state_logic
+    st_d = st_q;
+
+    p2s_valid = 1'b 0;
+    next_byte = 1'b 0;
+
+    unique case (st_q)
+      StIdle: begin
+        if (sel_dp_i == DpReadJEDEC) begin
+          st_d = StActive;
+
+          // Send out the dat
+          p2s_valid = 1'b 1;
+        end
+      end
+
+      StActive: begin
+        // TERMINAL_STATE
+
+        // Sends data
+        p2s_valid = 1'b 1;
+
+        if (outclk_p2s_sent_i) begin
+          next_byte = 1'b 1;
+        end
+      end
+
+      default: begin
+        st_d = StIdle;
+      end
+    endcase
+  end : next_state_logic
+
+endmodule : spid_jedec
diff --git a/hw/ip/spi_device/spi_device.core b/hw/ip/spi_device/spi_device.core
index 74d7053..20a22de 100644
--- a/hw/ip/spi_device/spi_device.core
+++ b/hw/ip/spi_device/spi_device.core
@@ -27,6 +27,7 @@
       - rtl/spi_readcmd.sv
       - rtl/spi_passthrough.sv
       - rtl/spid_status.sv
+      - rtl/spid_jedec.sv
       - rtl/spi_s2p.sv
       - rtl/spi_p2s.sv
       - rtl/spi_device.sv