diff --git a/top/x400/Makefile.x4xx.inc b/top/x400/Makefile.x4xx.inc
index 2c6de75..fa62080 100644
--- a/top/x400/Makefile.x4xx.inc
+++ b/top/x400/Makefile.x4xx.inc
@@ -74,6 +74,7 @@ x4xx_global_regs.v \
x4xx_versioning_regs.v \
x4xx_dio.v \
x4xx_gpio_atr.v \
+x4xx_gpio_spi.v \
rf/100m/rf_core_100m.v \
rf/200m/rf_core_200m.v \
rf/200m/rf_down_4to2.v \
diff --git a/top/x400/doc/X4XX_FPGA_left.htm b/top/x400/doc/X4XX_FPGA_left.htm
index c302c2f..0a10171 100644
--- a/top/x400/doc/X4XX_FPGA_left.htm
+++ b/top/x400/doc/X4XX_FPGA_left.htm
@@ -269,6 +269,21 @@
IPASS_CONTROL
+
+ +
+ DIG_IFC_REGMAP
+
+
+ +
+ SPI_OVER_GPIO_REGS
+
+
+
SPI_SLAVE_CONFIG
+
SPI_TRANSACTION_CONFIG
+
SPI_TRANSACTION_GO
+
SPI_STATUS
+
+
+
DIO_REGMAP
@@ -579,7 +594,8 @@
RADIO_GPIO_ATR_REGS
-
DIO_SOURCE_CONTROL
+
DIO_SOURCE_CONTROL
+
DIGITAL_IFC_REGS
diff --git a/top/x400/doc/X4XX_FPGA_right.htm b/top/x400/doc/X4XX_FPGA_right.htm
index 4e3b3c3..2827c1a 100644
--- a/top/x400/doc/X4XX_FPGA_right.htm
+++ b/top/x400/doc/X4XX_FPGA_right.htm
@@ -3229,6 +3229,492 @@ Total Offset =
+
+
+
+
+
DIG_IFC_REGMAP
+
+
SPI_OVER_GPIO_REGS
+
+
+
+
+
Offset 0x0000: SPI_SLAVE_CONFIG(3:0) Register Array (R|W)
+
+
(show extended info)
+
+
+
+
+
+
+|
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+ | SPI_SLAVE_CONFIG |
+ | offset=0x0000 + i*4 |
+
+
+ |
+
+
+
+
+
+|
+
+
+Cannot determine accessibility through this path |
+|
+Total Offset = |
+| 0x00E000 + i*4
+
+ |
+
+
+ |
+
+
+
+
+
+
Initial Values
+
+
+
+
This register is defined in HDL source file x4xx_gpio_spi.v.
+It uses RegType SPI_SETUP which is defined in HDL source file x4xx_gpio_spi.v.
+
+
+
+
+
+Controls SPI Transaction
+Set of configuration registers for the supported slaves.
+
+
+
+
+
+
+
+ | 31..28 |
+
+ Reserved
+
+
+ |
+
+
+
+ | 27 |
+
+ MOSI_EDGE (initialvalue=0)
+ Controls the edge in which the MOSI line is updated.
+ 0 = falling edge of SCLK.
+ 1 = rising edge of SCLK.
+
+ |
+
+
+
+ | 26 |
+
+ MISO_EDGE (initialvalue=0)
+ Controls the edge in which the MISO line is latched.
+ 0 = falling edge of SCLK.
+ 1 = rising edge of SCLK.
+
+ |
+
+
+
+ | 25..20 |
+
+ SPI_LENGTH (initialvalue=0)
+ Indicates the length of SPI transactions to this slave.
+
+ |
+
+
+
+ | 19..15 |
+
+ SLAVE_CS (initialvalue=0)
+ Indicates which GPIO line to use for the CS signal.
+ 0-11 : Port A GPIO
+ 16-27: Port B GPIO
+
+ |
+
+
+
+ | 14..10 |
+
+ SLAVE_MISO (initialvalue=0)
+ Indicates which GPIO line to use for the MISO signal.
+ 0-11 : Port A GPIO
+ 16-27: Port B GPIO
+
+ |
+
+
+
+ | 9..5 |
+
+ SLAVE_MOSI (initialvalue=0)
+ Indicates which GPIO line to use for the MOSI signal.
+ 0-11 : Port A GPIO
+ 16-27: Port B GPIO
+
+ |
+
+
+
+ | 4..0 |
+
+ SLAVE_CLK (initialvalue=0)
+ Indicates which GPIO line to use for the SCLK signal.
+ 0-11 : Port A GPIO
+ 16-27: Port B GPIO
+
+ |
+
+
+
+
+
+
+
+
+
+
Offset 0x0010: SPI_TRANSACTION_CONFIG Register (R|W)
+
+
(show extended info)
+
+
+
+
+
+
+|
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+ | SPI_TRANSACTION_CONFIG |
+ | offset=0x0010 |
+
+
+ |
+
+
+
+
+
+|
+
+
+Total Offset = |
+| 0x00E010
+
+ |
+
+
+ |
+
+
+
+
+
+
Initial Value = 0x00000000
+
+
+
This register is defined in HDL source file x4xx_gpio_spi.v.
+
+
+
+
+
+Controls clock rate and target for subsequent SPI transactions.
+
+
+
+
+
+
+
+ | 31..24 |
+
+ Reserved
+
+
+ |
+
+
+
+ | 23..18 |
+
+ Reserved
+
+
+ |
+
+
+
+ | 17..16 |
+
+ SPI_SLAVE_SELECT (initialvalue=0)
+
+
+ |
+
+
+
+ | 15..0 |
+
+ SPI_CLK_DIV (initialvalue=0)
+ Controls the rate for subsequent SPI transactions. SCLK = DataClk/[(SPI_CLK_DIV+1)]
+
+ |
+
+
+
+
+
+
+
+
+
+
Offset 0x0014: SPI_TRANSACTION_GO Register (W)
+
+
(show extended info)
+
+
+
+
+
+
+|
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+ | SPI_TRANSACTION_GO |
+ | offset=0x0014 |
+
+
+ |
+
+
+
+
+
+|
+
+
+Total Offset = |
+| 0x00E014
+
+ |
+
+
+ |
+
+
+
+
+
+
Initial Value = 0x00000000
+
+
+
This register is defined in HDL source file x4xx_gpio_spi.v.
+
+
+
+
+
+Starts a SPI transaction
+
+
+
+
+
+
+
+ | 31..0w |
+
+ SPI_DATA (initialvalue=0)
+ Payload to be sent for the SPI transaction. If the payload is shorter than 32 bits,
+ it must be aligned to the MSbs in this field. LSbs are ignored in this scenario.
+
+ |
+
+
+
+
+
+
+
+
+
+
Offset 0x0018: SPI_STATUS Register (R)
+
+
(show extended info)
+
+
+
+
+
+
+|
+
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+ | SPI_STATUS |
+ | offset=0x0018 |
+
+
+ |
+
+
+
+
+
+|
+
+
+Total Offset = |
+| 0x00E018
+
+ |
+
+
+ |
+
+
+
+
+
+
Initial Value = 0x00000000
+
+
+
This register is defined in HDL source file x4xx_gpio_spi.v.
+
+
+
+
+
+Contains the status of the SPI engine.
+
+
+
+
+
+
+
+ | 31..25 |
+
+ Reserved
+
+
+ |
+
+
+
+ | 24 |
+
+ SPI_READY (initialvalue=0)
+ Indicates the SPI engine is ready to start a new SPI transaction.
+
+ |
+
+
+
+ | 23..0 |
+
+ SPI_RESPONSE (initialvalue=0)
+ Records the response of the last completed SPI transaction.
+
+ |
+
+
+
+
+
+
+
+
@@ -8020,7 +8506,7 @@ Total Offset =
Controls whether GPIO lines use the TX and RX state of an RF channel
(Classic ATR) or the daughterboard state the selector for the
- @.GPIO_ATR_STATE.
+
ATR_STATE.
@@ -8069,7 +8555,7 @@ Controls whether GPIO lines use the TX and RX state of an RF channel
ATR_OPTION (initialvalue=0)
Sets the scheme in which RF states in the radio will control GPIO
lines. 0 = DB state is used. RF states are combined and the
- GPIO state is driven based on all 16 @.GPIO_ATR_STATE registers.
+ GPIO state is driven based on all 16 ATR_STATE registers.
1 = Each RF channel has its separate ATR state(Classic ATR).
Use register CLASSIC_ATR_CONFIG to indicate the RF channel
to which each GPIO line responds to.
@@ -16322,6 +16808,69 @@ Window to access the DIO register map through the control port from the radio bl
+
+
+
+
+
+
Offset 0x2000: DIGITAL_IFC_REGS Window (R|W)
+
Target regmap = DIG_IFC_REGMAP
+
(show extended info)
+
+
+
+
+
+
+|
+
+
+
+ |
+
+
+
+
+ | DIGITAL_IFC_REGS |
+ | offset=0x2000 |
+ | size=0x1000 (4 Kbytes) |
+
+
+ |
+
+
+
+
+
+|
+
+
+Total Offset = |
+| 0x00E000
+
+ |
+
+
+ |
+
+
+
+
+
+
This window is defined in HDL source file x4xx_core_common.v.
+
+
+
+
+
+Register space reserved for configuring a digital interface over the GPIO lines.
+ Currently, SPI is the only supported protocol.
+
+
+
diff --git a/top/x400/regmap/dig_ifc_regmap_utils.vh b/top/x400/regmap/dig_ifc_regmap_utils.vh
new file mode 100644
index 0000000..7ead185
--- /dev/null
+++ b/top/x400/regmap/dig_ifc_regmap_utils.vh
@@ -0,0 +1,88 @@
+//
+// Copyright 2021 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: dig_ifc_regmap_utils.vh
+// Description:
+// The constants in this file are autogenerated by XmlParse.
+
+//===============================================================================
+// A numerically ordered list of registers and their HDL source files
+//===============================================================================
+
+ // SPI_SLAVE_CONFIG : 0x0 (x4xx_gpio_spi.v)
+ // SPI_TRANSACTION_CONFIG : 0x10 (x4xx_gpio_spi.v)
+ // SPI_TRANSACTION_GO : 0x14 (x4xx_gpio_spi.v)
+ // SPI_STATUS : 0x18 (x4xx_gpio_spi.v)
+
+//===============================================================================
+// RegTypes
+//===============================================================================
+
+ // SPI_SETUP Type (from x4xx_gpio_spi.v)
+ localparam SPI_SETUP_SIZE = 32;
+ localparam SPI_SETUP_MASK = 32'hFFFFFFF;
+ localparam SLAVE_CLK_SIZE = 5; //SPI_SETUP:SLAVE_CLK
+ localparam SLAVE_CLK_MSB = 4; //SPI_SETUP:SLAVE_CLK
+ localparam SLAVE_CLK = 0; //SPI_SETUP:SLAVE_CLK
+ localparam SLAVE_MOSI_SIZE = 5; //SPI_SETUP:SLAVE_MOSI
+ localparam SLAVE_MOSI_MSB = 9; //SPI_SETUP:SLAVE_MOSI
+ localparam SLAVE_MOSI = 5; //SPI_SETUP:SLAVE_MOSI
+ localparam SLAVE_MISO_SIZE = 5; //SPI_SETUP:SLAVE_MISO
+ localparam SLAVE_MISO_MSB = 14; //SPI_SETUP:SLAVE_MISO
+ localparam SLAVE_MISO = 10; //SPI_SETUP:SLAVE_MISO
+ localparam SLAVE_CS_SIZE = 5; //SPI_SETUP:SLAVE_CS
+ localparam SLAVE_CS_MSB = 19; //SPI_SETUP:SLAVE_CS
+ localparam SLAVE_CS = 15; //SPI_SETUP:SLAVE_CS
+ localparam SPI_LENGTH_SIZE = 6; //SPI_SETUP:SPI_LENGTH
+ localparam SPI_LENGTH_MSB = 25; //SPI_SETUP:SPI_LENGTH
+ localparam SPI_LENGTH = 20; //SPI_SETUP:SPI_LENGTH
+ localparam MISO_EDGE_SIZE = 1; //SPI_SETUP:MISO_EDGE
+ localparam MISO_EDGE_MSB = 26; //SPI_SETUP:MISO_EDGE
+ localparam MISO_EDGE = 26; //SPI_SETUP:MISO_EDGE
+ localparam MOSI_EDGE_SIZE = 1; //SPI_SETUP:MOSI_EDGE
+ localparam MOSI_EDGE_MSB = 27; //SPI_SETUP:MOSI_EDGE
+ localparam MOSI_EDGE = 27; //SPI_SETUP:MOSI_EDGE
+
+//===============================================================================
+// Register Group SPI_OVER_GPIO_REGS
+//===============================================================================
+
+ // SPI_SLAVE_CONFIG Register (from x4xx_gpio_spi.v)
+ localparam SPI_SLAVE_CONFIG_COUNT = 4; // Number of elements in array
+
+ // SPI_TRANSACTION_CONFIG Register (from x4xx_gpio_spi.v)
+ localparam SPI_TRANSACTION_CONFIG = 'h10; // Register Offset
+ localparam SPI_TRANSACTION_CONFIG_SIZE = 32; // register width in bits
+ localparam SPI_TRANSACTION_CONFIG_MASK = 32'h3FFFF;
+ localparam SPI_CLK_DIV_SIZE = 16; //SPI_TRANSACTION_CONFIG:SPI_CLK_DIV
+ localparam SPI_CLK_DIV_MSB = 15; //SPI_TRANSACTION_CONFIG:SPI_CLK_DIV
+ localparam SPI_CLK_DIV = 0; //SPI_TRANSACTION_CONFIG:SPI_CLK_DIV
+ localparam SPI_SLAVE_SELECT_SIZE = 2; //SPI_TRANSACTION_CONFIG:SPI_SLAVE_SELECT
+ localparam SPI_SLAVE_SELECT_MSB = 17; //SPI_TRANSACTION_CONFIG:SPI_SLAVE_SELECT
+ localparam SPI_SLAVE_SELECT = 16; //SPI_TRANSACTION_CONFIG:SPI_SLAVE_SELECT
+
+ // SPI_TRANSACTION_GO Register (from x4xx_gpio_spi.v)
+ localparam SPI_TRANSACTION_GO = 'h14; // Register Offset
+ localparam SPI_TRANSACTION_GO_SIZE = 32; // register width in bits
+ localparam SPI_TRANSACTION_GO_MASK = 32'hFFFFFFFF;
+ localparam SPI_DATA_SIZE = 32; //SPI_TRANSACTION_GO:SPI_DATA
+ localparam SPI_DATA_MSB = 31; //SPI_TRANSACTION_GO:SPI_DATA
+ localparam SPI_DATA = 0; //SPI_TRANSACTION_GO:SPI_DATA
+
+ // SPI_STATUS Register (from x4xx_gpio_spi.v)
+ localparam SPI_STATUS = 'h18; // Register Offset
+ localparam SPI_STATUS_SIZE = 32; // register width in bits
+ localparam SPI_STATUS_MASK = 32'h1FFFFFF;
+ localparam SPI_RESPONSE_SIZE = 24; //SPI_STATUS:SPI_RESPONSE
+ localparam SPI_RESPONSE_MSB = 23; //SPI_STATUS:SPI_RESPONSE
+ localparam SPI_RESPONSE = 0; //SPI_STATUS:SPI_RESPONSE
+ localparam SPI_READY_SIZE = 1; //SPI_STATUS:SPI_READY
+ localparam SPI_READY_MSB = 24; //SPI_STATUS:SPI_READY
+ localparam SPI_READY = 24; //SPI_STATUS:SPI_READY
+
+ // Return the offset of an element of register array SPI_SLAVE_CONFIG
+ function integer SPI_SLAVE_CONFIG (input integer i);
+ SPI_SLAVE_CONFIG = (i * 'h4) + 'h0;
+ endfunction
diff --git a/top/x400/regmap/radio_dio_regmap_utils.vh b/top/x400/regmap/radio_dio_regmap_utils.vh
index 62de3d7..6916dc7 100644
--- a/top/x400/regmap/radio_dio_regmap_utils.vh
+++ b/top/x400/regmap/radio_dio_regmap_utils.vh
@@ -13,6 +13,7 @@
// RADIO_GPIO_ATR_REGS : 0x0 (x4xx_core_common.v)
// DIO_SOURCE_CONTROL : 0x1000 (x4xx_core_common.v)
+ // DIGITAL_IFC_REGS : 0x2000 (x4xx_core_common.v)
//===============================================================================
// RegTypes
@@ -29,3 +30,7 @@
// DIO_SOURCE_CONTROL Window (from x4xx_core_common.v)
localparam DIO_SOURCE_CONTROL = 'h1000; // Window Offset
localparam DIO_SOURCE_CONTROL_SIZE = 'h1000; // size in bytes
+
+ // DIGITAL_IFC_REGS Window (from x4xx_core_common.v)
+ localparam DIGITAL_IFC_REGS = 'h2000; // Window Offset
+ localparam DIGITAL_IFC_REGS_SIZE = 'h1000; // size in bytes
diff --git a/top/x400/x4xx_core.v b/top/x400/x4xx_core.v
index 4e944e3..6098925 100644
--- a/top/x400/x4xx_core.v
+++ b/top/x400/x4xx_core.v
@@ -249,6 +249,7 @@ module x4xx_core #(
.PCIE_PRESENT (0)
) x4xx_core_common_i (
.radio_clk (radio_clk),
+ .radio_clk_2x (radio_clk_2x),
.radio_rst (radio_rst),
.rfnoc_chdr_clk (rfnoc_chdr_clk),
.rfnoc_chdr_rst (rfnoc_chdr_rst),
diff --git a/top/x400/x4xx_core_common.v b/top/x400/x4xx_core_common.v
index 3dac18a..89dd49a 100644
--- a/top/x400/x4xx_core_common.v
+++ b/top/x400/x4xx_core_common.v
@@ -38,6 +38,7 @@ module x4xx_core_common #(
) (
// Clocks and resets
input wire radio_clk,
+ input wire radio_clk_2x,
input wire radio_rst,
input wire rfnoc_chdr_clk,
@@ -234,16 +235,16 @@ module x4xx_core_common #(
.s_ctrlport_resp_ack (m_resp_ack),
.s_ctrlport_resp_status (m_resp_status),
.s_ctrlport_resp_data (m_resp_data),
- .m_ctrlport_req_wr ({timekeeper_req_wr, versioning_req_wr, global_regs_req_wr, dio_req_wr}),
- .m_ctrlport_req_rd ({timekeeper_req_rd, versioning_req_rd, global_regs_req_rd, dio_req_rd}),
- .m_ctrlport_req_addr ({timekeeper_req_addr, versioning_req_addr, global_regs_req_addr, dio_req_addr}),
- .m_ctrlport_req_data ({timekeeper_req_data, versioning_req_data, global_regs_req_data, dio_req_data}),
+ .m_ctrlport_req_wr ({timekeeper_req_wr, versioning_req_wr, global_regs_req_wr, dio_req_wr}),
+ .m_ctrlport_req_rd ({timekeeper_req_rd, versioning_req_rd, global_regs_req_rd, dio_req_rd}),
+ .m_ctrlport_req_addr ({timekeeper_req_addr, versioning_req_addr, global_regs_req_addr, dio_req_addr}),
+ .m_ctrlport_req_data ({timekeeper_req_data, versioning_req_data, global_regs_req_data, dio_req_data}),
.m_ctrlport_req_byte_en (),
.m_ctrlport_req_has_time (),
.m_ctrlport_req_time (),
- .m_ctrlport_resp_ack ({timekeeper_resp_ack, versioning_resp_ack, global_regs_resp_ack, dio_resp_ack}),
+ .m_ctrlport_resp_ack ({timekeeper_resp_ack, versioning_resp_ack, global_regs_resp_ack, dio_resp_ack}),
.m_ctrlport_resp_status ({timekeeper_resp_status, versioning_resp_status, global_regs_resp_status, dio_resp_status}),
- .m_ctrlport_resp_data ({timekeeper_resp_data, versioning_resp_data, global_regs_resp_data, dio_resp_data})
+ .m_ctrlport_resp_data ({timekeeper_resp_data, versioning_resp_data, global_regs_resp_data, dio_resp_data})
);
@@ -349,6 +350,7 @@ module x4xx_core_common #(
// Radio CtrlPort Splitter
//-----------------------------------------------------------------------
+ // Radio CtrlPort endpoints
wire [ 1*NUM_DBOARDS-1:0] rf_ctrlport_req_wr;
wire [ 1*NUM_DBOARDS-1:0] rf_ctrlport_req_rd;
wire [ 20*NUM_DBOARDS-1:0] rf_ctrlport_req_addr;
@@ -371,9 +373,36 @@ module x4xx_core_common #(
wire [ 2*NUM_DBOARDS-1:0] radio_dio_resp_status;
wire [ 32*NUM_DBOARDS-1:0] radio_dio_resp_data;
+ wire [ 1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_wr;
+ wire [ 1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_rd;
+ wire [ 20*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_addr;
+ wire [ 32*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_data;
+ wire [ 4*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_byte_en;
+ wire [ 1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_has_time;
+ wire [ 64*NUM_DBOARDS-1:0] gpio_atr_ctrlport_req_time;
+ wire [ 1*NUM_DBOARDS-1:0] gpio_atr_ctrlport_resp_ack;
+ wire [ 2*NUM_DBOARDS-1:0] gpio_atr_ctrlport_resp_status;
+ wire [ 32*NUM_DBOARDS-1:0] gpio_atr_ctrlport_resp_data;
+
+ wire [ 1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_wr;
+ wire [ 1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_rd;
+ wire [ 20*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_addr;
+ wire [ 32*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_data;
+ wire [ 4*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_byte_en;
+ wire [ 1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_has_time;
+ wire [ 64*NUM_DBOARDS-1:0] gpio_spi_ctrlport_req_time;
+ wire [ 1*NUM_DBOARDS-1:0] gpio_spi_ctrlport_resp_ack;
+ wire [ 2*NUM_DBOARDS-1:0] gpio_spi_ctrlport_resp_status;
+ wire [ 32*NUM_DBOARDS-1:0] gpio_spi_ctrlport_resp_data;
+
+ // GPIO control signals from radio ctrlport endpoints to
+ // x4xx_dio.
wire [NUM_DBOARDS*32-1:0] atr_gpio_out;
wire [NUM_DBOARDS*32-1:0] atr_gpio_ddr;
+ wire [NUM_DBOARDS*32-1:0] spi_gpio_out;
+ wire [NUM_DBOARDS*32-1:0] spi_gpio_ddr;
+
genvar db;
generate
for (db = 0; db < NUM_DBOARDS; db = db+1) begin : gen_radio_ctrlport
@@ -385,67 +414,100 @@ module x4xx_core_common #(
// This section takes the CtrlPort master from each radio block and splits it
// into a CtrlPort bus for the associated daughter(m_radio_ctrlport_*), the
// RFDC timing control (rf_ctrlport_*), the ATR GPIO control for the DB state
- // the current radio(db) and DIO main control block(x4xx_dio).
+ // the current radio(db), the SPI controller of the radio, and DIO main
+ // control block(x4xx_dio).
// Refer to diagram in the RADIO_CTRLPORT_REGMAP Register map for a
// visual representation on how these interfaces are distributed.
// Register space offset calculation
localparam [19:0] DIO_SOURCE_CONTROL_OFFSET = DIO_WINDOW + DIO_SOURCE_CONTROL;
localparam [19:0] RADIO_GPIO_ATR_OFFSET = DIO_WINDOW + RADIO_GPIO_ATR_REGS;
+ localparam [19:0] DIGITAL_IFC_OFFSET = DIO_WINDOW + DIGITAL_IFC_REGS;
// Register space size calculation
localparam [31:0] RFDC_TIMING_WINDOW_SIZE_W = $clog2(RFDC_TIMING_WINDOW_SIZE);
localparam [31:0] DB_WINDOW_SIZE_W = $clog2(DB_WINDOW_SIZE);
localparam [31:0] DIO_SOURCE_CONTROL_SIZE_W = $clog2(DIO_SOURCE_CONTROL_SIZE);
localparam [31:0] RADIO_GPIO_ATR_SIZE_W = $clog2(RADIO_GPIO_ATR_REGS_SIZE);
-
- wire gpio_atr_ctrlport_req_wr;
- wire gpio_atr_ctrlport_req_rd;
- wire [19:0] gpio_atr_ctrlport_req_addr;
- wire [31:0] gpio_atr_ctrlport_req_data;
- wire [ 3:0] gpio_atr_ctrlport_req_byte_en;
- wire gpio_atr_ctrlport_req_has_time;
- wire [63:0] gpio_atr_ctrlport_req_time;
- wire gpio_atr_ctrlport_resp_ack;
- wire [ 1:0] gpio_atr_ctrlport_resp_status;
- wire [31:0] gpio_atr_ctrlport_resp_data;
-
+ localparam [31:0] DIGITAL_IFC_REGS_SIZE_W = $clog2(DIGITAL_IFC_REGS_SIZE);
ctrlport_decoder_param #(
- .NUM_SLAVES (4),
- .PORT_BASE ({ DIO_SOURCE_CONTROL_OFFSET,
+ .NUM_SLAVES (5),
+ .PORT_BASE ({ DIGITAL_IFC_OFFSET,
+ DIO_SOURCE_CONTROL_OFFSET,
RADIO_GPIO_ATR_OFFSET,
RFDC_TIMING_WINDOW[19:0],
DB_WINDOW[19:0]
}),
- .PORT_ADDR_W ({ DIO_SOURCE_CONTROL_SIZE_W,
+ .PORT_ADDR_W ({ DIGITAL_IFC_REGS_SIZE_W,
+ DIO_SOURCE_CONTROL_SIZE_W,
RADIO_GPIO_ATR_SIZE_W,
RFDC_TIMING_WINDOW_SIZE_W,
DB_WINDOW_SIZE_W
})
) ctrlport_decoder_param_i (
- .ctrlport_clk (radio_clk),
- .ctrlport_rst (radio_rst),
- .s_ctrlport_req_wr (s_radio_ctrlport_req_wr [ 1*db+: 1]),
- .s_ctrlport_req_rd (s_radio_ctrlport_req_rd [ 1*db+: 1]),
- .s_ctrlport_req_addr (s_radio_ctrlport_req_addr [20*db+:20]),
- .s_ctrlport_req_data (s_radio_ctrlport_req_data [32*db+:32]),
- .s_ctrlport_req_byte_en (s_radio_ctrlport_req_byte_en [ 4*db+: 4]),
- .s_ctrlport_req_has_time (s_radio_ctrlport_req_has_time [ 1*db+: 1]),
- .s_ctrlport_req_time (s_radio_ctrlport_req_time [64*db+:64]),
- .s_ctrlport_resp_ack (s_radio_ctrlport_resp_ack [ 1*db+: 1]),
- .s_ctrlport_resp_status (s_radio_ctrlport_resp_status [ 2*db+: 2]),
- .s_ctrlport_resp_data (s_radio_ctrlport_resp_data [32*db+:32]),
- .m_ctrlport_req_wr ({ radio_dio_req_wr [ 1*db+: 1], gpio_atr_ctrlport_req_wr, rf_ctrlport_req_wr [ 1*db+: 1], m_radio_ctrlport_req_wr [ 1*db+: 1] }),
- .m_ctrlport_req_rd ({ radio_dio_req_rd [ 1*db+: 1], gpio_atr_ctrlport_req_rd, rf_ctrlport_req_rd [ 1*db+: 1], m_radio_ctrlport_req_rd [ 1*db+: 1] }),
- .m_ctrlport_req_addr ({ radio_dio_req_addr [20*db+:20], gpio_atr_ctrlport_req_addr, rf_ctrlport_req_addr [20*db+:20], m_radio_ctrlport_req_addr [20*db+:20] }),
- .m_ctrlport_req_data ({ radio_dio_req_data [32*db+:32], gpio_atr_ctrlport_req_data, rf_ctrlport_req_data [32*db+:32], m_radio_ctrlport_req_data [32*db+:32] }),
- .m_ctrlport_req_byte_en ({ radio_dio_req_byte_en [ 4*db+: 4], gpio_atr_ctrlport_req_byte_en, rf_ctrlport_req_byte_en [ 4*db+: 4], m_radio_ctrlport_req_byte_en [ 4*db+: 4] }),
- .m_ctrlport_req_has_time ({ radio_dio_req_has_time [ 1*db+: 1], gpio_atr_ctrlport_req_has_time, rf_ctrlport_req_has_time [ 1*db+: 1], m_radio_ctrlport_req_has_time [ 1*db+: 1] }),
- .m_ctrlport_req_time ({ radio_dio_req_time [64*db+:64], gpio_atr_ctrlport_req_time, rf_ctrlport_req_time [64*db+:64], m_radio_ctrlport_req_time [64*db+:64] }),
- .m_ctrlport_resp_ack ({ radio_dio_resp_ack [ 1*db+: 1], gpio_atr_ctrlport_resp_ack, rf_ctrlport_resp_ack [ 1*db+: 1], m_radio_ctrlport_resp_ack [ 1*db+: 1] }),
- .m_ctrlport_resp_status ({ radio_dio_resp_status [ 2*db+: 2], gpio_atr_ctrlport_resp_status, rf_ctrlport_resp_status [ 2*db+: 2], m_radio_ctrlport_resp_status [ 2*db+: 2] }),
- .m_ctrlport_resp_data ({ radio_dio_resp_data [32*db+:32], gpio_atr_ctrlport_resp_data, rf_ctrlport_resp_data [32*db+:32], m_radio_ctrlport_resp_data [32*db+:32] })
+ .ctrlport_clk ( radio_clk ),
+ .ctrlport_rst ( radio_rst ),
+ .s_ctrlport_req_wr ( s_radio_ctrlport_req_wr [ 1*db+: 1] ),
+ .s_ctrlport_req_rd ( s_radio_ctrlport_req_rd [ 1*db+: 1] ),
+ .s_ctrlport_req_addr ( s_radio_ctrlport_req_addr [20*db+:20] ),
+ .s_ctrlport_req_data ( s_radio_ctrlport_req_data [32*db+:32] ),
+ .s_ctrlport_req_byte_en ( s_radio_ctrlport_req_byte_en [ 4*db+: 4] ),
+ .s_ctrlport_req_has_time ( s_radio_ctrlport_req_has_time [ 1*db+: 1] ),
+ .s_ctrlport_req_time ( s_radio_ctrlport_req_time [64*db+:64] ),
+ .s_ctrlport_resp_ack ( s_radio_ctrlport_resp_ack [ 1*db+: 1] ),
+ .s_ctrlport_resp_status ( s_radio_ctrlport_resp_status [ 2*db+: 2] ),
+ .s_ctrlport_resp_data ( s_radio_ctrlport_resp_data [32*db+:32] ),
+ .m_ctrlport_req_wr ({ gpio_spi_ctrlport_req_wr [ 1*db+: 1],
+ radio_dio_req_wr [ 1*db+: 1],
+ gpio_atr_ctrlport_req_wr [ 1*db+: 1],
+ rf_ctrlport_req_wr [ 1*db+: 1],
+ m_radio_ctrlport_req_wr [ 1*db+: 1] }),
+ .m_ctrlport_req_rd ({ gpio_spi_ctrlport_req_rd [ 1*db+: 1],
+ radio_dio_req_rd [ 1*db+: 1],
+ gpio_atr_ctrlport_req_rd [ 1*db+: 1],
+ rf_ctrlport_req_rd [ 1*db+: 1],
+ m_radio_ctrlport_req_rd [ 1*db+: 1] }),
+ .m_ctrlport_req_addr ({ gpio_spi_ctrlport_req_addr [20*db+:20],
+ radio_dio_req_addr [20*db+:20],
+ gpio_atr_ctrlport_req_addr [20*db+:20],
+ rf_ctrlport_req_addr [20*db+:20],
+ m_radio_ctrlport_req_addr [20*db+:20] }),
+ .m_ctrlport_req_data ({ gpio_spi_ctrlport_req_data [32*db+:32],
+ radio_dio_req_data [32*db+:32],
+ gpio_atr_ctrlport_req_data [32*db+:32],
+ rf_ctrlport_req_data [32*db+:32],
+ m_radio_ctrlport_req_data [32*db+:32] }),
+ .m_ctrlport_req_byte_en ({ gpio_spi_ctrlport_req_byte_en [ 4*db+: 4],
+ radio_dio_req_byte_en [ 4*db+: 4],
+ gpio_atr_ctrlport_req_byte_en [ 4*db+: 4],
+ rf_ctrlport_req_byte_en [ 4*db+: 4],
+ m_radio_ctrlport_req_byte_en [ 4*db+: 4] }),
+ .m_ctrlport_req_has_time ({ gpio_spi_ctrlport_req_has_time [ 1*db+: 1],
+ radio_dio_req_has_time [ 1*db+: 1],
+ gpio_atr_ctrlport_req_has_time [ 1*db+: 1],
+ rf_ctrlport_req_has_time [ 1*db+: 1],
+ m_radio_ctrlport_req_has_time [ 1*db+: 1] }),
+ .m_ctrlport_req_time ({ gpio_spi_ctrlport_req_time [64*db+:64],
+ radio_dio_req_time [64*db+:64],
+ gpio_atr_ctrlport_req_time [64*db+:64],
+ rf_ctrlport_req_time [64*db+:64],
+ m_radio_ctrlport_req_time [64*db+:64] }),
+ .m_ctrlport_resp_ack ({ gpio_spi_ctrlport_resp_ack [ 1*db+: 1],
+ radio_dio_resp_ack [ 1*db+: 1],
+ gpio_atr_ctrlport_resp_ack [ 1*db+: 1],
+ rf_ctrlport_resp_ack [ 1*db+: 1],
+ m_radio_ctrlport_resp_ack [ 1*db+: 1] }),
+ .m_ctrlport_resp_status ({ gpio_spi_ctrlport_resp_status [ 2*db+: 2],
+ radio_dio_resp_status [ 2*db+: 2],
+ gpio_atr_ctrlport_resp_status [ 2*db+: 2],
+ rf_ctrlport_resp_status [ 2*db+: 2],
+ m_radio_ctrlport_resp_status [ 2*db+: 2] }),
+ .m_ctrlport_resp_data ({ gpio_spi_ctrlport_resp_data [32*db+:32],
+ radio_dio_resp_data [32*db+:32],
+ gpio_atr_ctrlport_resp_data [32*db+:32],
+ rf_ctrlport_resp_data [32*db+:32],
+ m_radio_ctrlport_resp_data [32*db+:32] })
);
// Compute ATR state for this radio
@@ -459,19 +521,37 @@ module x4xx_core_common #(
) x4xx_gpio_atr_i (
.ctrlport_clk (radio_clk),
.ctrlport_rst (radio_rst),
- .s_ctrlport_req_wr (gpio_atr_ctrlport_req_wr),
- .s_ctrlport_req_rd (gpio_atr_ctrlport_req_rd),
- .s_ctrlport_req_addr (gpio_atr_ctrlport_req_addr),
- .s_ctrlport_req_data (gpio_atr_ctrlport_req_data),
- .s_ctrlport_resp_ack (gpio_atr_ctrlport_resp_ack),
- .s_ctrlport_resp_status (gpio_atr_ctrlport_resp_status),
- .s_ctrlport_resp_data (gpio_atr_ctrlport_resp_data),
+ .s_ctrlport_req_wr (gpio_atr_ctrlport_req_wr [ 1*db+: 1]),
+ .s_ctrlport_req_rd (gpio_atr_ctrlport_req_rd [ 1*db+: 1]),
+ .s_ctrlport_req_addr (gpio_atr_ctrlport_req_addr [20*db+:20]),
+ .s_ctrlport_req_data (gpio_atr_ctrlport_req_data [32*db+:32]),
+ .s_ctrlport_resp_ack (gpio_atr_ctrlport_resp_ack [ 1*db+: 1]),
+ .s_ctrlport_resp_status (gpio_atr_ctrlport_resp_status [ 2*db+: 2]),
+ .s_ctrlport_resp_data (gpio_atr_ctrlport_resp_data [32*db+:32]),
.db_state (db_state),
.gpio_in ({4'b0, gpio_in_b, 4'b0, gpio_in_a}),
.gpio_out (atr_gpio_out[db*32+: 32]),
.gpio_ddr (atr_gpio_ddr[db*32+: 32])
);
+ x4xx_gpio_spi #(
+ .NUM_SLAVES (2)
+ ) x4xx_gpio_spi_i(
+ .ctrlport_clk (radio_clk),
+ .ctrlport_clk_2x (radio_clk_2x),
+ .ctrlport_rst (radio_rst),
+ .s_ctrlport_req_wr (gpio_spi_ctrlport_req_wr [ 1*db+: 1]),
+ .s_ctrlport_req_rd (gpio_spi_ctrlport_req_rd [ 1*db+: 1]),
+ .s_ctrlport_req_addr (gpio_spi_ctrlport_req_addr [20*db+:20]),
+ .s_ctrlport_req_data (gpio_spi_ctrlport_req_data [32*db+:32]),
+ .s_ctrlport_resp_ack (gpio_spi_ctrlport_resp_ack [ 1*db+: 1]),
+ .s_ctrlport_resp_status (gpio_spi_ctrlport_resp_status [ 2*db+: 2]),
+ .s_ctrlport_resp_data (gpio_spi_ctrlport_resp_data [32*db+:32]),
+ .gpio_out (spi_gpio_out[db*32+: 32]),
+ .gpio_ddr (spi_gpio_ddr[db*32+: 32]),
+ .gpio_in ({4'b0, gpio_in_b, 4'b0, gpio_in_a})
+ );
+
end
endgenerate
@@ -686,10 +766,10 @@ module x4xx_core_common #(
.atr_gpio_ddr (atr_gpio_ddr),
.ps_gpio_out ({4'b0, ps_gpio_out_b, 4'b0, ps_gpio_out_a}),
.ps_gpio_ddr ({4'b0, ps_gpio_ddr_b, 4'b0, ps_gpio_ddr_a}),
- .digital_ifc_gpio_out_radio0 (32'b0),
- .digital_ifc_gpio_ddr_radio0 (32'b0),
- .digital_ifc_gpio_out_radio1 (32'b0),
- .digital_ifc_gpio_ddr_radio1 (32'b0),
+ .digital_ifc_gpio_out_radio0 (spi_gpio_out[31:0]),
+ .digital_ifc_gpio_ddr_radio0 (spi_gpio_ddr[31:0]),
+ .digital_ifc_gpio_out_radio1 (spi_gpio_out[63:32]),
+ .digital_ifc_gpio_ddr_radio1 (spi_gpio_ddr[63:32]),
.user_app_in_a (gpio_in_fabric_a),
.user_app_in_b (gpio_in_fabric_b),
.user_app_out_a (gpio_out_fabric_a),
@@ -771,6 +851,10 @@ endmodule
//
// Window to access the DIO register map through the control port from the radio blocks.
//
+//
+// Register space reserved for configuring a digital interface over the GPIO lines.
+// Currently, SPI is the only supported protocol.
+//
//
//
diff --git a/top/x400/x4xx_gpio_atr.v b/top/x400/x4xx_gpio_atr.v
index 98ba881..86e1a6a 100644
--- a/top/x400/x4xx_gpio_atr.v
+++ b/top/x400/x4xx_gpio_atr.v
@@ -312,13 +312,13 @@ endmodule
//
// Controls whether GPIO lines use the TX and RX state of an RF channel
// (Classic ATR) or the daughterboard state the selector for the
-// @.GPIO_ATR_STATE.
+// @.ATR_STATE.
//
//
//
// Sets the scheme in which RF states in the radio will control GPIO
// lines. 0 = DB state is used. RF states are combined and the
-// GPIO state is driven based on all 16 @.GPIO_ATR_STATE registers.
+// GPIO state is driven based on all 16 @.ATR_STATE registers.
// 1 = Each RF channel has its separate ATR state(Classic ATR).
// Use register @.CLASSIC_ATR_CONFIG to indicate the RF channel
// to which each GPIO line responds to.
diff --git a/top/x400/x4xx_gpio_spi.v b/top/x400/x4xx_gpio_spi.v
new file mode 100644
index 0000000..b5866f8
--- /dev/null
+++ b/top/x400/x4xx_gpio_spi.v
@@ -0,0 +1,534 @@
+//
+// Copyright 2021 Ettus Research, A National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: x4xx_gpio_spi
+//
+// Description:
+//
+// This block enables control of a SPI master engine via CtrlPort
+// transactions.
+// It also enables customization on how signals from the SPI buses
+// connected to the master are mapped to the GPIO Ports.
+// This block supports configuring communication to up to 4 SPI slaves.
+//
+// Parameters:
+//
+// NUM_SLAVES : Number of SPI slaves to be supported. Values from 1 to 4
+// are supported. SPI transfers can only target one slave
+// at a time.
+// BASE_ADDRESS : Start address for this register block.
+// SIZE_ADDRESS : Size of the CtrlPort window to consider in this block.
+//
+
+`default_nettype none
+
+
+module x4xx_gpio_spi #(
+ parameter NUM_SLAVES = 4,
+ parameter [19:0] BASE_ADDRESS = 0,
+ parameter [19:0] SIZE_ADDRESS = 19'h20
+) (
+ input wire ctrlport_clk,
+ input wire ctrlport_clk_2x,
+ input wire ctrlport_rst,
+
+ // Request
+ input wire s_ctrlport_req_wr,
+ input wire s_ctrlport_req_rd,
+ input wire [19:0] s_ctrlport_req_addr,
+ input wire [31:0] s_ctrlport_req_data,
+
+ // Response
+ output reg s_ctrlport_resp_ack = 1'b0,
+ output reg [ 1:0] s_ctrlport_resp_status = 2'b0,
+ output reg [31:0] s_ctrlport_resp_data = 32'b0,
+
+ // GPIO control/status
+ output wire [31:0] gpio_out,
+ output wire [31:0] gpio_ddr,
+ input wire [31:0] gpio_in
+);
+
+ `include "../../lib/rfnoc/core/ctrlport.vh"
+ `include "regmap/dig_ifc_regmap_utils.vh"
+
+ // Registers / wires for SPI core communication
+ reg [31:0] set_data = 0;
+ reg [ 7:0] set_addr = 0;
+ reg set_stb = 1'b0;
+
+ wire [31:0] readback;
+ wire readback_stb;
+ wire readback_stb_extended;
+
+ wire sclk;
+ wire mosi;
+ wire miso;
+ // This array is set to the maximum supported SPI slaves instead of
+ // the provided NUM_SLAVES to facilitate concurrent re-mapping.
+ // See section(GPIO Mapping) of this file.
+ wire [3:0] ss;
+
+ // Auxiliary signals to compute which GPIO lines are outputs
+ reg [31:0] gpio_is_mosi = 32'b0;
+ reg [31:0] gpio_is_sclk = 32'b0;
+ reg [31:0] gpio_is_cs = 32'b0;
+
+ // SPI-to-GPIO mapping signals.
+ // These arrays are set to the maximum supported SPI slaves instead of
+ // the provided NUM_SLAVES to facilitate concurrent re-mapping.
+ // See section(GPIO Mapping) of this file.
+ reg [ SLAVE_CLK_SIZE-1:0] sclk_mapping [3:0];
+ reg [SLAVE_MOSI_SIZE-1:0] mosi_mapping [3:0];
+ reg [SLAVE_MISO_SIZE-1:0] miso_mapping [3:0];
+ reg [ SLAVE_CS_SIZE-1:0] ss_mapping [3:0];
+
+ //---------------------------------------------------------------------------
+ // Address calculation
+ //---------------------------------------------------------------------------
+
+ wire address_in_range =
+ (s_ctrlport_req_addr >= BASE_ADDRESS) &&
+ (s_ctrlport_req_addr < BASE_ADDRESS + SIZE_ADDRESS);
+
+ // Check that address is targeting slave configuration.
+ wire address_is_slave =
+ (s_ctrlport_req_addr >= BASE_ADDRESS + SPI_SLAVE_CONFIG(0)) &&
+ (s_ctrlport_req_addr <= BASE_ADDRESS + SPI_SLAVE_CONFIG(3));
+
+ // Decode the slave being addressed.
+ wire [1:0]slave_address = s_ctrlport_req_addr[3:2];
+
+ //---------------------------------------------------------------------------
+ // Slave configuration signals
+ //---------------------------------------------------------------------------
+
+ // These settings are registered individually for each slave
+ reg [ NUM_SLAVES-1:0] data_in_edge = {NUM_SLAVES{1'b0}};
+ reg [ NUM_SLAVES-1:0] data_out_edge = {NUM_SLAVES{1'b0}};
+ reg [SPI_LENGTH_SIZE-1:0] slave_spi_length [NUM_SLAVES-1:0];
+
+ // One-hot encoding to indicate active slave
+ reg [NUM_SLAVES-1:0] slave_select = {NUM_SLAVES{1'b0}};
+
+ //---------------------------------------------------------------------------
+ // FSM to handle transfers
+ //---------------------------------------------------------------------------
+
+ localparam IDLE = 3'd0;
+ localparam SET_DIVIDER = 3'd1;
+ localparam WRITE_SPI = 3'd2;
+ localparam CONFIG_TRANSFER = 3'd3;
+ localparam WAIT_SPI = 3'd4;
+
+ localparam DIVIDER_ADDRESS = 8'd0;
+ localparam CTRL_ADDRESS = 8'd1;
+ localparam DATA_ADDRESS = 8'd2;
+
+ reg [ 2:0] state = IDLE;
+ reg [ 31:0] data_cache;
+ reg [SPI_CLK_DIV_SIZE-1:0] divider;
+ reg [ 1:0] cs;
+ reg spi_go = 1'b0;
+ reg spi_ready = 1'b0;
+
+ integer slave_i;
+
+ //---------------------------------------------------------------------------
+ // CtrlPort Register endpoints
+ //---------------------------------------------------------------------------
+
+ always @ (posedge ctrlport_clk) begin
+
+ if (ctrlport_rst) begin
+ s_ctrlport_resp_ack <= 1'b0;
+ spi_go <= 1'b0;
+ spi_ready <= 1'b0;
+ divider <= {SPI_CLK_DIV_SIZE{1'b0}};
+ cs <= 2'b0;
+
+ // Assigned to unassigned mapping. This avoids overwriting
+ // signals with those from uninitialized slaves.
+ for (slave_i=0; slave_i<4; slave_i=slave_i+1) begin
+ sclk_mapping[slave_i] <= 5'h31;
+ mosi_mapping[slave_i] <= 5'h31;
+ miso_mapping[slave_i] <= 5'h31;
+ ss_mapping [slave_i] <= 5'h31;
+ end
+
+ for (slave_i=0; slave_i
+//
+//
+//
+//
+//
+// Controls SPI Transaction
+//
+//
+//
+// Indicates which GPIO line to use for the SCLK signal.
+// 0-11 : Port A GPIO
+// 16-27: Port B GPIO
+//
+//
+//
+//
+// Indicates which GPIO line to use for the MOSI signal.
+// 0-11 : Port A GPIO
+// 16-27: Port B GPIO
+//
+//
+//
+//
+// Indicates which GPIO line to use for the MISO signal.
+// 0-11 : Port A GPIO
+// 16-27: Port B GPIO
+//
+//
+//
+//
+// Indicates which GPIO line to use for the CS signal.
+// 0-11 : Port A GPIO
+// 16-27: Port B GPIO
+//
+//
+//
+//
+// Indicates the length of SPI transactions to this slave.
+//
+//
+//
+//
+// Controls the edge in which the MISO line is latched.
+// 0 = falling edge of SCLK.
+// 1 = rising edge of SCLK.
+//
+//
+//
+//
+// Controls the edge in which the MOSI line is updated.
+// 0 = falling edge of SCLK.
+// 1 = rising edge of SCLK.
+//
+//
+//
+//
+// Set of configuration registers for the supported slaves.
+//
+//
+//
+// Controls clock rate and target for subsequent SPI transactions.
+//
+//
+// Controls the rate for subsequent SPI transactions. SCLK = DataClk/[(SPI_CLK_DIV+1)]
+//
+//
+//
+//
+//
+// Starts a SPI transaction
+//
+//
+// Payload to be sent for the SPI transaction. If the payload is shorter than 32 bits,
+// it must be aligned to the MSbs in this field. LSbs are ignored in this scenario.
+//
+//
+//
+//
+// Contains the status of the SPI engine.
+//
+//
+// Indicates the SPI engine is ready to start a new SPI transaction.
+//
+//
+// Records the response of the last completed SPI transaction.
+//
+//
+//
+//
+//XmlParse xml_off