[ spi_host, rtl ] Split DATA memory window into separate RO and WO windows

- Creates two new windows TXDATA and RXDATA
- RXDATA is RO, TXDATA is WO
  - Fixes #5484
- Signals an error back to TLUL if the RXDATA is written or TXDATA is read

Signed-off-by: Martin Lueker-Boden <martin.lueker-boden@wdc.com>
diff --git a/hw/ip/spi_host/data/spi_host.hjson b/hw/ip/spi_host/data/spi_host.hjson
index 7c7cca3..b0c5611 100644
--- a/hw/ip/spi_host/data/spi_host.hjson
+++ b/hw/ip/spi_host/data/spi_host.hjson
@@ -354,14 +354,37 @@
       ]
     },
     { window: {
-        name: "DATA",
+        name: "RXDATA",
+        items: "1",
+        validbits: "32",
+        desc: '''SPI Receive Data.
+
+                 Reads from this window pull data from the RXFIFO.
+
+                 The serial order of bit transmission
+                 is chosen to match SPI flash devices. Individual bytes
+                 are always transmitted with the most significant bit first.
+                 Only four-bute reads are supported. If ByteOrder = 0,
+                 the first byte received is packed in the MSB of !!RXDATA.
+                 For some processor architectures, this could lead to shuffling
+                 of flash data as compared to how it is written in memory.
+                 In which case, choosing ByteOrder = 1 can reverse the
+                 byte-order of each data read, causing the first byte
+                 received to be packed into the LSB of !!RXDATA. (Though within
+                 each byte the most significant bit is always pulled
+                 from the bus first.)
+                 '''
+        swaccess: "ro",
+      }
+    },
+    { window: {
+        name: "TXDATA",
         items: "1",
         validbits: "32",
         byte-write: "true",
-        desc: '''SPI Transmit and Receive Data.
+        desc: '''SPI Transmit Data.
 
-                 Write data to this window to place it in the TXFIFO.
-                 Reads from this register pull data from the RXFIFO.
+                 Data written to this window is placed into the TXFIFO.
                  Byte-enables are supported for writes.
 
                  The serial order of bit transmission
diff --git a/hw/ip/spi_host/rtl/spi_host.sv b/hw/ip/spi_host/rtl/spi_host.sv
index 325fb5a..4ed838e 100644
--- a/hw/ip/spi_host/rtl/spi_host.sv
+++ b/hw/ip/spi_host/rtl/spi_host.sv
@@ -49,8 +49,8 @@
   spi_host_reg2hw_t reg2hw;
   spi_host_hw2reg_t hw2reg;
 
-  tlul_pkg::tl_h2d_t fifo_win_h2d;
-  tlul_pkg::tl_d2h_t fifo_win_d2h;
+  tlul_pkg::tl_h2d_t fifo_win_h2d [2];
+  tlul_pkg::tl_d2h_t fifo_win_d2h [2];
 
   // Register module
   logic [NumAlerts-1:0] alert_test, alerts;
@@ -297,8 +297,10 @@
   spi_host_window u_window (
     .clk_i,
     .rst_ni,
-    .win_i      (fifo_win_h2d),
-    .win_o      (fifo_win_d2h),
+    .rx_win_i   (fifo_win_h2d[0]),
+    .rx_win_o   (fifo_win_d2h[0]),
+    .tx_win_i   (fifo_win_h2d[1]),
+    .tx_win_o   (fifo_win_d2h[1]),
     .tx_data_o  (tx_data),
     .tx_be_o    (tx_be),
     .tx_valid_o (tx_valid),
diff --git a/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv b/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv
index 95334bc..f5d606d 100644
--- a/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv
+++ b/hw/ip/spi_host/rtl/spi_host_reg_pkg.sv
@@ -294,9 +294,9 @@
   parameter logic [BlockAw-1:0] SPI_HOST_CONFIGOPTS_OFFSET = 6'h 18;
   parameter logic [BlockAw-1:0] SPI_HOST_CSID_OFFSET = 6'h 1c;
   parameter logic [BlockAw-1:0] SPI_HOST_COMMAND_OFFSET = 6'h 20;
-  parameter logic [BlockAw-1:0] SPI_HOST_ERROR_ENABLE_OFFSET = 6'h 28;
-  parameter logic [BlockAw-1:0] SPI_HOST_ERROR_STATUS_OFFSET = 6'h 2c;
-  parameter logic [BlockAw-1:0] SPI_HOST_EVENT_ENABLE_OFFSET = 6'h 30;
+  parameter logic [BlockAw-1:0] SPI_HOST_ERROR_ENABLE_OFFSET = 6'h 2c;
+  parameter logic [BlockAw-1:0] SPI_HOST_ERROR_STATUS_OFFSET = 6'h 30;
+  parameter logic [BlockAw-1:0] SPI_HOST_EVENT_ENABLE_OFFSET = 6'h 34;
 
   // Reset values for hwext registers and their fields
   parameter logic [1:0] SPI_HOST_INTR_TEST_RESVAL = 2'h 0;
@@ -311,8 +311,10 @@
   parameter logic [1:0] SPI_HOST_COMMAND_DIRECTION_RESVAL = 2'h 0;
 
   // Window parameters
-  parameter logic [BlockAw-1:0] SPI_HOST_DATA_OFFSET = 6'h 24;
-  parameter int unsigned        SPI_HOST_DATA_SIZE   = 'h 4;
+  parameter logic [BlockAw-1:0] SPI_HOST_RXDATA_OFFSET = 6'h 24;
+  parameter int unsigned        SPI_HOST_RXDATA_SIZE   = 'h 4;
+  parameter logic [BlockAw-1:0] SPI_HOST_TXDATA_OFFSET = 6'h 28;
+  parameter int unsigned        SPI_HOST_TXDATA_SIZE   = 'h 4;
 
   // Register index
   typedef enum int {
diff --git a/hw/ip/spi_host/rtl/spi_host_reg_top.sv b/hw/ip/spi_host/rtl/spi_host_reg_top.sv
index 26df29a..75dc0bc 100644
--- a/hw/ip/spi_host/rtl/spi_host_reg_top.sv
+++ b/hw/ip/spi_host/rtl/spi_host_reg_top.sv
@@ -13,8 +13,8 @@
   output tlul_pkg::tl_d2h_t tl_o,
 
   // Output port for window
-  output tlul_pkg::tl_h2d_t tl_win_o,
-  input  tlul_pkg::tl_d2h_t tl_win_i,
+  output tlul_pkg::tl_h2d_t tl_win_o  [2],
+  input  tlul_pkg::tl_d2h_t tl_win_i  [2],
 
   // To HW
   output spi_host_reg_pkg::spi_host_reg2hw_t reg2hw, // Write
@@ -81,29 +81,31 @@
     .tl_o(tl_o)
   );
 
-  tlul_pkg::tl_h2d_t tl_socket_h2d [2];
-  tlul_pkg::tl_d2h_t tl_socket_d2h [2];
+  tlul_pkg::tl_h2d_t tl_socket_h2d [3];
+  tlul_pkg::tl_d2h_t tl_socket_d2h [3];
 
   logic [1:0] reg_steer;
 
   // socket_1n connection
-  assign tl_reg_h2d = tl_socket_h2d[1];
-  assign tl_socket_d2h[1] = tl_reg_d2h;
+  assign tl_reg_h2d = tl_socket_h2d[2];
+  assign tl_socket_d2h[2] = tl_reg_d2h;
 
-  assign tl_win_o = tl_socket_h2d[0];
-  assign tl_socket_d2h[0] = tl_win_i;
+  assign tl_win_o[0] = tl_socket_h2d[0];
+  assign tl_socket_d2h[0] = tl_win_i[0];
+  assign tl_win_o[1] = tl_socket_h2d[1];
+  assign tl_socket_d2h[1] = tl_win_i[1];
 
   // Create Socket_1n
   tlul_socket_1n #(
-    .N          (2),
+    .N          (3),
     .HReqPass   (1'b1),
     .HRspPass   (1'b1),
-    .DReqPass   ({2{1'b1}}),
-    .DRspPass   ({2{1'b1}}),
+    .DReqPass   ({3{1'b1}}),
+    .DRspPass   ({3{1'b1}}),
     .HReqDepth  (4'h0),
     .HRspDepth  (4'h0),
-    .DReqDepth  ({2{4'h0}}),
-    .DRspDepth  ({2{4'h0}})
+    .DReqDepth  ({3{4'h0}}),
+    .DRspDepth  ({3{4'h0}})
   ) u_socket (
     .clk_i  (clk_i),
     .rst_ni (rst_ni),
@@ -116,15 +118,18 @@
 
   // Create steering logic
   always_comb begin
-    reg_steer = 1;       // Default set to register
+    reg_steer = 2;       // Default set to register
 
     // TODO: Can below codes be unique case () inside ?
     if (tl_i.a_address[AW-1:0] >= 36 && tl_i.a_address[AW-1:0] < 40) begin
       reg_steer = 0;
     end
-    if (intg_err) begin
+    if (tl_i.a_address[AW-1:0] >= 40 && tl_i.a_address[AW-1:0] < 44) begin
       reg_steer = 1;
     end
+    if (intg_err) begin
+      reg_steer = 2;
+    end
   end
 
   tlul_adapter_reg #(
diff --git a/hw/ip/spi_host/rtl/spi_host_window.sv b/hw/ip/spi_host/rtl/spi_host_window.sv
index 2af9cda..6cf0d61 100644
--- a/hw/ip/spi_host/rtl/spi_host_window.sv
+++ b/hw/ip/spi_host/rtl/spi_host_window.sv
@@ -8,41 +8,64 @@
 module spi_host_window (
   input  clk_i,
   input  rst_ni,
-  input  tlul_pkg::tl_h2d_t win_i,
-  output tlul_pkg::tl_d2h_t win_o,
+  input  tlul_pkg::tl_h2d_t rx_win_i,
+  output tlul_pkg::tl_d2h_t rx_win_o,
+  input  tlul_pkg::tl_h2d_t tx_win_i,
+  output tlul_pkg::tl_d2h_t tx_win_o,
   output logic [31:0]       tx_data_o,
   output logic [3:0]        tx_be_o,
   output logic              tx_valid_o,
   input        [31:0]       rx_data_i,
-  output                    rx_ready_o
+  output logic              rx_ready_o
 );
 
-  localparam int AW=spi_host_reg_pkg::BlockAw;
-  localparam int DW=32;
+  localparam int AW = spi_host_reg_pkg::BlockAw;
+  localparam int DW = 32;
 
-  logic [AW-1:0] addr;
+  logic rx_we, tx_re;
 
-  // Only support reads/writes to the data fifo window
-  logic win_error;
-  assign win_error = (tx_valid_o || rx_ready_o) &&
-                     (addr != spi_host_reg_pkg::SPI_HOST_DATA_OFFSET);
+  // Only support reads from the data RX fifo window
+  logic  rx_access_error;
+  assign rx_access_error = rx_we;
 
   tlul_adapter_reg #(
-    .RegAw(AW),
-    .RegDw(DW)
-  ) u_adapter (
+    .RegAw (AW),
+    .RegDw (DW)
+  ) u_adapter_rx (
     .clk_i,
     .rst_ni,
-    .tl_i      (win_i),
-    .tl_o      (win_o),
-    .we_o      (tx_valid_o),
-    .re_o      (rx_ready_o),
-    .addr_o    (addr),
-    .wdata_o   (tx_data_o),
-    .be_o      (tx_be_o),
-    .busy_i    ('0),
-    .rdata_i   (rx_data_i),
-    .error_i   (win_error)
+    .tl_i    (rx_win_i),
+    .tl_o    (rx_win_o),
+    .we_o    (rx_we),
+    .re_o    (rx_ready_o),
+    .addr_o  (),
+    .wdata_o (),
+    .be_o    (),
+    .rdata_i (rx_data_i),
+    .error_i (rx_access_error),
+    .busy_i  ('0)
+  );
+
+  // Only support writes to the data TX fifo window
+  logic  tx_access_error;
+  assign tx_access_error = tx_re;
+
+  tlul_adapter_reg #(
+    .RegAw (AW),
+    .RegDw (DW)
+  ) u_adapter_tx (
+    .clk_i,
+    .rst_ni,
+    .tl_i    (tx_win_i),
+    .tl_o    (tx_win_o),
+    .we_o    (tx_valid_o),
+    .re_o    (tx_re),
+    .addr_o  (),
+    .wdata_o (tx_data_o),
+    .be_o    (tx_be_o),
+    .rdata_i ({DW{1'b0}}),
+    .error_i (tx_access_error),
+    .busy_i  ('0)
   );
 
 endmodule : spi_host_window