[spi_device] Extract serial-to-parallel from fwmode

As spi_s2p module is introduced, Removed rx handler from FwMode module.
fwmode module handed over rx valid and data from s2p to async FIFO and
detects the overflow error only.

Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/ip/spi_device/rtl/spi_device.sv b/hw/ip/spi_device/rtl/spi_device.sv
index ffb8ee6..62555c5 100644
--- a/hw/ip/spi_device/rtl/spi_device.sv
+++ b/hw/ip/spi_device/rtl/spi_device.sv
@@ -141,6 +141,13 @@
 
   logic [AsFifoDepthW-1:0] as_txfifo_depth, as_rxfifo_depth;
 
+  // SPI S2P signals
+  // io_mode: Determine s2p/p2s behavior. As of now, only fwmode exists.
+  // TODO: Add FlashMode IO, passthrough IO
+  io_mode_e    io_mode, fw_io_mode;
+  logic        s2p_data_valid;
+  spi_byte_t   s2p_data;
+  logic [11:0] s2p_bitcnt;
 
   //////////////////////////////////////////////////////////////////////
   // Connect phase (between control signals above and register module //
@@ -333,6 +340,65 @@
   assign rst_rxfifo_n = (scanmode_i) ? rst_ni : rst_ni & ~rst_rxfifo_reg;
 
 
+  //////////////////////////////
+  // SPI_DEVICE mode selector //
+  //////////////////////////////
+  // This logic chooses appropriate signals based on input SPI_DEVICE mode.
+  // e.g) If FwMode is selected. all data connected to spi_fwmode logic
+
+  // Assume spi_mode does not change dynamically
+
+  // io_mode to spi_s2p
+  always_comb begin
+    io_mode = SingleIO;
+
+    unique case (spi_mode)
+      FwMode: begin
+        io_mode = fw_io_mode;
+      end
+
+      FlashMode: begin
+        // TODO: Revise when implementing FlashMode
+        io_mode = SingleIO;
+      end
+
+      PassThrough: begin
+        // TODO: Revise when implementing PassThrough
+        io_mode = SingleIO;
+      end
+
+      default: begin
+        io_mode = SingleIO;
+      end
+    endcase
+  end
+  `ASSERT_KNOWN(SpiModeKnown_A, spi_mode)
+
+
+
+  ////////////////////////////
+  // SPI Serial to Parallel //
+  ////////////////////////////
+  // TODO: Make full SPI interface
+  // Currently only one line is connected
+  logic [3:0] s2p_si;
+  assign s2p_si = {3'b 0, cio_sdi_i};
+  spi_s2p u_s2p (
+    .clk_i        (clk_spi_in_buf),
+    .rst_ni       (rst_spi_n),
+
+    // SPI interface
+    .s_i          (s2p_si),
+
+    .data_valid_o (s2p_data_valid),
+    .data_o       (s2p_data      ),
+    .bitcnt_o     (s2p_bitcnt    ),
+
+    // Config (changed dynamically)
+    .order_i      (rxorder),
+    .io_mode_i    (io_mode)
+  );
+
   /////////////
   // FW Mode //
   /////////////
@@ -344,7 +410,7 @@
     .rst_out_ni   (rst_spi_n),
 
     .cpha_i        (cpha),
-    .cfg_rxorder_i (rxorder),
+    //.cfg_rxorder_i (rxorder),
     .cfg_txorder_i (txorder),
 
     .mode_i        (spi_mode),
@@ -360,6 +426,13 @@
     .rx_overflow_o  (rxf_overflow),
     .tx_underflow_o (txf_underflow),
 
+    // Input from S2P
+    .rx_data_valid_i (s2p_data_valid),
+    .rx_data_i       (s2p_data),
+
+    // Output to S2P (mode select)
+    .io_mode_o       (fw_io_mode),
+
     // SPI signal
     .csb_i         (cio_csb_i),
     .sdi_i         (cio_sdi_i),
diff --git a/hw/ip/spi_device/rtl/spi_device_pkg.sv b/hw/ip/spi_device/rtl/spi_device_pkg.sv
index b15626c..a4c2b9a 100644
--- a/hw/ip/spi_device/rtl/spi_device_pkg.sv
+++ b/hw/ip/spi_device/rtl/spi_device_pkg.sv
@@ -10,7 +10,7 @@
   // SPI Operation mode
   typedef enum logic [1:0] {
     FwMode      = 'h0,
-    EepromRam   = 'h1,
+    FlashMode   = 'h1,
     PassThrough = 'h2
   } spi_mode_e;
 
diff --git a/hw/ip/spi_device/rtl/spi_fwmode.sv b/hw/ip/spi_device/rtl/spi_fwmode.sv
index a81c04c..4d01eaa 100644
--- a/hw/ip/spi_device/rtl/spi_fwmode.sv
+++ b/hw/ip/spi_device/rtl/spi_fwmode.sv
@@ -5,7 +5,9 @@
 // SPI FW Mode: Intention of this mode is to download FW image. Doesn't parse Commands
 //
 
-module spi_fwmode (
+module spi_fwmode
+  import spi_device_pkg::*;
+(
   // SDI
   input clk_in_i,
   input rst_in_ni,
@@ -16,22 +18,26 @@
 
   // Configurations
   // No sync logic. Configuration should be static when SPI operating
-  input                             cpha_i,
-  input                             cfg_rxorder_i, // 1: 0->7 , 0:7->0
-  input                             cfg_txorder_i, // 1: 0->7 , 0:7->0
-  input  spi_device_pkg::spi_mode_e mode_i, // Only works at mode_i == FwMode
+  input             cpha_i,
+  input             cfg_txorder_i, // 1: 0->7 , 0:7->0
+  input  spi_mode_e mode_i, // Only works at mode_i == FwMode
 
   // RX, TX FIFO interface
-  output logic                      rx_wvalid_o,
-  input                             rx_wready_i,
-  output spi_device_pkg::spi_byte_t rx_data_o,
+  output logic      rx_wvalid_o,
+  input             rx_wready_i,
+  output spi_byte_t rx_data_o,
 
-  input                             tx_rvalid_i,
-  output logic                      tx_rready_o,
-  input  spi_device_pkg::spi_byte_t tx_data_i,
+  input             tx_rvalid_i,
+  output logic      tx_rready_o,
+  input  spi_byte_t tx_data_i,
 
-  output logic                      rx_overflow_o,
-  output logic                      tx_underflow_o,
+  output logic      rx_overflow_o,
+  output logic      tx_underflow_o,
+
+  // Serial to Parallel
+  input             rx_data_valid_i,
+  input  spi_byte_t rx_data_i,
+  output io_mode_e  io_mode_o,
 
   // SPI Interface: clock is given (ckl_in_i, clk_out_i)
   input        csb_i,
@@ -53,41 +59,11 @@
   } tx_state_e;
   tx_state_e tx_state;   // Only for handling CPHA
 
-  spi_byte_t rx_data_d, rx_data_q;
+  assign rx_wvalid_o = rx_data_valid_i;
+  assign rx_data_o   = rx_data_i;
 
-  // Serial to Parallel
-  always_comb begin
-    if (cfg_rxorder_i) begin
-      rx_data_d = {sdi_i, rx_data_q[BITS-1:1]};
-    end else begin
-      rx_data_d = {rx_data_q[BITS-2:0], sdi_i};
-    end
-  end
-
-  always_ff @(posedge clk_in_i) begin
-    rx_data_q <= rx_data_d;
-  end
-
-  // As SCK shut off right after bytes are transferred,
-  // HW should give current SDI and latched version of rx_data
-  // if not, FIFO request should be generated next cycle but it cannot be (as no clock exist)
-  // It means RX_FIFO should latch the write request at negedge of clk_in_i
-  assign rx_data_o = rx_data_d;
-
-  // Counter to generate write signal
-  always_ff @(posedge clk_in_i or negedge rst_in_ni) begin
-    if (!rst_in_ni) begin
-      rx_bitcount <= BITWIDTH'(BITS-1);
-    end else begin
-      if (rx_bitcount == '0) begin
-        rx_bitcount <= BITWIDTH'(BITS-1);
-      end else begin
-        rx_bitcount <= rx_bitcount -1;
-      end
-    end
-  end
-
-  assign rx_wvalid_o = (rx_bitcount == '0);
+  // Generic Mode only uses SingleIO. s_i[0] is MOSI, s_o[1] is MISO.
+  assign io_mode_o = SingleIO;
 
   // TX Serialize
   logic [BITWIDTH-1:0] tx_bitcount;
diff --git a/hw/ip/spi_device/spi_device.core b/hw/ip/spi_device/spi_device.core
index 2540317..5180029 100644
--- a/hw/ip/spi_device/spi_device.core
+++ b/hw/ip/spi_device/spi_device.core
@@ -21,6 +21,7 @@
       - rtl/spi_fwm_rxf_ctrl.sv
       - rtl/spi_fwm_txf_ctrl.sv
       - rtl/spi_fwmode.sv
+      - rtl/spi_s2p.sv
       - rtl/spi_device.sv
     file_type: systemVerilogSource