SPI_HOST HWIP Technical Specification


This document specifies SPI_HOST hardware IP (HWIP) functionality. This module conforms to the Comportable guideline for peripheral functionality. See that document for integration overview within the broader top-level system.


  • Hardware control for remote devices using the Serial Peripheral Interface (SPI)
  • Primarily designed for serial NOR flash devices such as the Winbond W25Q01JV
  • Number of chip select lines controlled by MaxCS parameter
  • Support for Standard SPI, Dual SPI or Quad SPI commands
    • Pins sd[0] through sd[3] are intended to connect to lines IO0 through IO3 respectively, on the target device.
    • Pin sd[0] may also be identified as “MOSI” by other SPI Hosts, while sd[1] is commonly referred to as “MISO”
  • RX and TX data held in separate FIFOs
    • 288 bytes for TX data, 256 bytes for RX data
    • FIFOs loaded/unloaded via 32-bit TL-UL registers
    • Support for arbitrary byte-count in each transaction
    • Parametrizable support for Big- or Little-Endian systems in ordering I/O bytes within 32-bit words.
  • SPI clock rate controlled by separate input clock to core
    • SPI sck line typically toggles at 1/2 the core clock frequency
    • An additional clock rate divider exists to reduce the frequency if needed
  • Support for all SPI polarity and phases (CPOL, CPHA)
    • Additional support for “Full-cycle” SPI transactions, wherein data can be read a full SPI Clock cycle after the active edge (as opposed to one half cycle as is typical for SPI interfaces)
  • Single Transfer Rate (STR) only (i.e. data received on multiple lines, but only on one clock edge)
    • No support for Dual Transfer Rate (DTR)
  • Pass-through mode for coordination with SPI_DEVICE IP
  • Automatic or manual control of chip select lines
  • Condensed interrupt footprint: Two lines for two distinct interrupt classes: “error” and “spi_event”
    • Fine-grain interrupt masking supplied by secondary enable registers


The Serial Peripheral Interface (SPI) is a synchronous serial interface quite commonly used for NOR flash devices as well as a number of other off-chip peripherals such as ADC’s, DAC’s, or temperature sensors. The interface is a de facto standard (not a formal one), and so there is no definitive reference describing the interface, or establishing compliance criteria.

It is therefore important to consult the data sheets for the desired peripheral devices in order to ensure compatibility. For instance, this OpenTitan SPI Host IP is primarily designed for controlling Quad SPI NOR flash devices, such as the W25Q01JV Serial NOR flash from Winbond or this 1 Gb M25QL NOR flash from Micron. Though this IP implementation aims to be general enough to support a variety of devices, the Winbond serial flash device is used as the primary reference for understanding our host requirements.

There are also a number of good references describing legacy host implementations for this protocol, which are useful for understanding some of the general needs for a wider range of target devices. For instance, the legacy SPI Block Guide from Motorola contains a definitive overview of some of the the general requirements for a standard SPI host, notably the definitions of SPI clock phase and polarity (CPOL and CPHA). In order to potentially support a broad range of devices, this SPI Host IP also supports all four of the standard SPI clock phases.

SPI Protocol Basics

Broadly speaking, the SPI host accepts commands from the TL-UL interface and, based on these commands, serially transmits and receives data on the external SPI interface pins. The timing and data-line formatting of the command sequence depend on the external peripheral device and the nature of the specific command issued.

In each standard SPI command a number of instruction-, address- or data-bytes are transmitted on sd[0], and response bytes are received on sd[1]. So in standard-mode commands, sd[0] is always configured as an output, and sd[1] is always an input. In standard SPI commands the sd[0] and sd[1] lines can be used as a full-duplex communication channel. Not all devices exploit this capability, opting instead to have clear input and output phases for each command. This half-duplex signaling behavior is especially common in devices with also support Dual- and Quad-mode commands, which are always half-duplex. The SPI_HOST IP optionally supports both full-duplex and half-duplex commands in standard mode.

Along with the data lines, the SPI protocol also includes a chip select line, commonly called CS#, or in this IP we refer to it as cs_n. The SPI bus can be connected to many target peripherals, but each device on the bus gets its own chip select line, and so this active-low signal designates a particular device for each command.

The chip-select line also marks the beginning and end of each command. No device will accept any command input until cs_n has been asserted for that device, and most devices (if not all) do not accept a second command unless cs_n has been deasserted to mark the end of the previous command. Some simple devices, particularly those that support SPI daisy-chaining, do not process command input at all until after the cs_n line has been deasserted. In the case of NOR flash devices, read and write commands are indeterminate in length, and the data transfer ends only when the cs_n line is deasserted. So, though the exact details of operation may vary from device to device, the edges of the cs_n signal serve as an important markers for delineating the boundaries of each transaction.

The sd and cs_n lines are accompanied by a serial clock, sck. The host is responsible for generating the serial clock, and typically each side asserts outgoing data on one edge of the clock (e.g. on the rising edge) and samples data in the next edge (e.g. on the falling edge). When it comes to devices there is no universal convention on clock polarity (CPOL) or clock phase (CPHA). Some devices expect the clock line to be low when the host is idle, thus the clock should come as a sequence of positive pulses (CPOL = 0). On the other hand, other devices expect CPOL = 1, meaning that the clock line is inverted: high when idle with sequences of negative pulses.

Devices also differ in their expectations of clock phase (CPHA) relative to the data. Devices with CPHA = 0, expect that both the host and device will be sampling data on the leading edge, and asserting data on the trailing edge. (Because of the option for either polarity, the terms “leading” and “trailing” are preferred to “rising” or “falling”). When CPHA = 0, the first output bit is asserted with the falling edge of cs_n. Meanwhile if CPHA = 1, data is always is asserted on the leading edge of sck, and data is always sampled on the trailing edge of sck.

When operating at the fastest-rated clock speeds, some flash devices (i.e. both the Winbond and Micron devices noted above), require setup times which exceed half a clock-cycle. In order to support these fastest data rates, the SPI_HOST IP offers a modified “Full-cycle” (FULLCYC = 1) timing mode where data can be sampled a full cycle after the target device asserts data on the sd bus. This full cycle mode has no effect on any of the signals transmitted, only on the timing of the sampling of the incoming signals.

As mentioned earlier, the sd[0] and sd[1] lines are unidirectional in Standard SPI mode. On the other hand in the faster Dual- or Quad-modes, all data lines are bidirectional, and in Quad mode the number of data lines increases to four. For the purposes of this IP, Dual or Quad-mode commands can be thought of as consisting of up to four command phases in which the host:

  1. Transmits instructions or data at single-line rate,
  2. Transmits instructions address or data on 2 or 4 data lines,
  3. Holds the bus in a high-impedance state for some number of “dummy” clock cycles (neither side transmits), or
  4. Receives information from the target device.

This four phase command scheme is also applied to half-duplex interactions when in standard mode.

For even faster transfer rates, some flash chips support double transfer rate (DTR) variations to the SPI protocol wherein the device receives and transmits fresh data on both the leading and trailing edge. This IP only supports single transfer rate (STR), not DTR. A preliminary investigation of DTR transfer mode suggests that proper support for setup and hold times in this mode may require a level of sub-cycle timing control which is not currently planned for this IP.

Theory of Operations

TODO: Review text for accuracy after review updates.

SPI_HOST IP Command Interface

Issuing a command generally consists of the following steps:

  1. Configure the IP to be compatible with the target peripheral. The CONFIGOPTS_0 multi-register has one set of configuration settings for each cs_n line.
  2. Load the instructions and data to be transmitted into the TXFIFO via the TXDATA register,
  3. Issue a 32-bit command to the appropriate Command multi-register (e.g. for controlling the device on cs_n[0] use COMMAND_0). Each command register has the following information,
    • The speed to use, COMMAND_0.SPEED_0, for this particular command (Standard, Dual, or Quad)
    • The number of bytes to transmit at reduced data rate, COMMAND_0.TX1_CNT_0, using sd[0] only
      • This field is specifically intended for Dual or Quad commands where the first instruction must be sent serially on sd[0]
    • The number of bytes to transmit at full data rate, COMMAND_0.TXN_CNT_0
    • The number of dummy sck cycles to wait before reading data, COMMAND_0.DUMMY_CYCLES_0
    • The number of bytes to receive at the full Dual or Quad rate, COMMAND_0.RX_CNT_0
  4. Read the peripheral response from the RXDATA register.

Configuration options

The CONFIGOPTS_0 multi-register has one entry per cs_n line and holds clock configuration and timing settings which are specific to each peripheral. Once the CONFIGOPTS_0 multi-register has been programed for each SPI peripheral device, the values can be left unchanged.

The following sections give details on how the SPI_HOST can be used to control a specific peripheral. For simplicity, this section decribes how to interact one device, attached to cs_n[0], and as such references are made to the multi-registers CONFIGOPTS_0 and COMMAND_0. To configure timing and send commands to devices on other cs_n lines, instead use the COMMAND and CONFIGOPTS multi-registers corresponding to desired cs_n line.

The most common differences between target devices are the requirements for a specific SPI clock phase or polarity, CPOL and CPHA, which were described in the previous section SPI Protocol Basics. These clock parameters can be set via the CONFIGOPTS_0.CPOL_0 or CONFIGOPTS_0.CPHA_0 register fields. Likewise, as also described in the previous section, if device setup times require a full clock cycle before sampling the output, Full-Cycle Mode can be enabled by asserting the CONFIGOPTS_0.FULLCYC_0 bit.

Clock rate selection

The SPI clock rate for each peripheral is set by two factors:

  • The SPI_HOST core clock (which may be generated independently from the TL-UL interface clock)
  • An additional 16-bit clock divider

The SPI protocol usually requires activity (either sampling or asserting data) on either edge of the sck clock. For this reason the maximum sck frequency is at most one half the SPI_HOST core frequency. In order to support a broader range of SPI clock frequencies, the SPI_HOST core operates on a separate clock domain, which may be independent from the TL-UL bus clock. This arrangement allows gives more flexibility in setting the serial clock frequency by means of an external PLL, and in principle the sck frequency could even be configured to exceed the bus clock. For example, if the TL-UL bus is operating at 100MHz, a 200MHz SPI core clock can be fed to the SPI_HOST IP, in order to acheive data rates of 100 MTransfers/s (near the maximum clock rate of the Winbond flash device).

Since some peripheral devices attached to the same SPI_HOST may require different clock frequencies, there is also the option to divide the core clock by an additional factor when dealing with slower peripherals.


Alternatively, this clock-divide feature can also be used to entirely bypass the need for an independent core clock. Instead the core can be driven by the TL-UL bus clock, and the sck period can be adjusted using the CONFIGOPTS_0.CLKDIV_0 setting.

Chip-select timing control

Typically the cs_n line is automatically deasserted after the last edge of sck. However, by asserting CONFIGOPTS_0.CSAAT_0 before issuing a particular command, one can instruct the core to hold cs_n low indefinitely after the last clock edge. This is useful for merging two adjacent commands together, to create very long commands such as continuous read operations. The cs_n line can then be deasserted by either issuing another command after clearing the CONFIGOPTS_0.CSAAT_0 field, issuing a command to a different device (using a different COMMAND register), or simply resetting the core FSM via the CONTROL.RST_FSM register.

Most devices require at least one-half sck clock-cycle between either edge of cs_n and the nearest sck edge. However, some devices may require more timing margin and so the SPI_HOST core offers some configuration registers for controlling the timing of the cs_n edges when operating under automatic control. The relevant parameters are as follows:

  • TIDLE: The minimum time between each rising edge of cs_n and the following falling edge. This time delay is a half sck cycle by default but can be extended to as long as eight sck cycles by setting the CONFIGOPTS_0.CSNIDLE_0 register.
  • TLEAD: The minimum time between each falling edge of cs_n and the first leading edge of sck. This time delay is a half sck cycle by default but can be extended to as long as eight sck cycles by setting the CONFIGOPTS_0.CSNLEAD_0 register.
  • TTRAIL: The minimum time between the last trailing edge of sck and the following rising edge of cs_n. This time delay is a half sck cycle by default but can be extended to as long as eight sck cycles by setting the CONFIGOPTS_0.CSNTRAIL_0 register.

These settings are all minimum bounds, and delays in the FSM implementation may create more margin in each of these timing constraints.

Special Command Fields

The COMMAND_0 register must be written every time a command is issued. Whenever a 1 is written to COMMAND_0.GO_0, the contents of the CONFIGOPTS_0 and COMMAND_0 registers are passed through the Config/Command CDC to the SPI_HOST core FSM, along with a Chip Select mask signal, indicating which device should receive the command (for example cs_n[0]) Once the command is issued, the core will immediately deassert STATUS.READY, and once the command has started STATUS.ACTIVE will go high. The STATUS.ACTIVE line takes a few cycles to assert, due to CDC delays. The command is complete when STATUS.ACTIVE goes low. A spi_event interrupt can also be triggered to go off on completion by setting EVENT_ENABLE.IDLE.

Chip Select Masks

Each instance of the SPI_HOST IP supports a parametrizable number of chip select lines (cs_n[MaxCS-1:0]). Each cs_n line can be routed either to a single peripheral or to a daisy-chain of peripherals. Whenever a 1 is written to one of the the GO bits in the COMMAND multiregister, a cs_n mask is sent (along with the COMMAND and CONFIGOPTS multi-register data for that line) to indicate which device is meant to receive the command. The SPI_HOST core typically then manages the details of asserting and deasserting the proper cs_n line, subject to the timing parameters expressed in CONFIGOPTS_0.CSAAT_0, CONFIGOPTS_0.CSNLEAD_0, CONFIGOPTS_0.CSNTRAIL_0, and CONFIGOPTS_0.CSNIDLE_0.

Alternatively the cs_n lines can be controlled entirely by firmware. If the register CONTROL.MANCS_EN is set high then the cs_n lines are directly controlled by the CONTROL.MANUAL_CS register.

If Pass-through mode is enabled then the cs_n lines are controlled by neither the SPI_HOST hardware nor the firmware register. In Pass-though mode, control of the cs_n lines passes directly to the inter-module port, pt_cs_ni.

Arbitrary Length Commands

Typically the length of each command is limited by the maximum number of bits in the COMMAND_0.TXN_CNT_0, COMMAND_0.RX_CNT_0, and COMMAND_0.TX1_CNT_0 fields. However, a series of SPI_HOST IP commands can be merged into one long command sequence using the CONFIGOPTS_0.CSAAT_0 field, which leaves the cs_n line low after the first SPI_HOST command. By raising the cs_n line only after the last command has completed, the peripheral will interpret the resulting transmit/receive sequences as one long command.

Back-to-back Commands

There is no command queue in the SPI_HOST IP. However a second command can be placed into the Config/Command CDC whenever STATUS.READY is high, even if the previous command is still running. The internal state within the Config/Command CDC provides the option of scheduling a second command to execute immediately after completion of the current command.

On the other hand, writing a one to COMMAND_0.GO_0 (or any GO bit in this multi-register) when STATUS.READY is low will trigger an error condition, which must be acknowledged by software.

Data Formatting (Placeholder)

Section moved to PR #5149

Pass-through Mode

The SPI_HOST also supports a special “Pass-through” mode, which allows for the direct control of the serial interface by another block (namely SPI_DEVICE).

To enable this mode, one sets CONTROL.PASSTHRU to one.

A multiplexor then configures the output signals cio_sck_o and cio_cs_no to directly match the inter-module signals pt_sck_i and pt_cs_ni[MaxCS-1:0]. Likewise the bidirectional port-control cio_sd_o[3:0] and cio_sdt_t[3:0] are then respectively driven by inter-module signals cio_sdo_i[3:0] and cio_sdi_o[3:0]. Meanwhile the peripheral data input signal cio_sdo_o[3:0] is always connected to the inter-module pt_sdi_o[3:0].

Interrupt aggregation

In order to reduce the total number of interrupts in the system, the SPI_HOST has only two interrupt lines: error and spi_event. Within these two interrupt classes, there are a number of conditions which can trigger them.

Each interrupt class has a secondary status and mask register, to control which sub-classes of SPI events will cause an interrupt.

SPI Events and Event Interrupts

The SPI_HOST supports interrupts for the following SPI events:

  • IDLE: The SPI_HOST is idle.
  • READY: The SPI_HOST is ready to accept a new command.
  • RXFULL: The SPI_HOST has run out of room in the RXFIFO.
  • RXWM: The number of 32-bit words in the RXFIFO currently exceeds the value set in CONTROL.RX_WATERMARK.
  • TXEMPTY: The SPI_HOST has transmitted all the data in the TX FIFO.
  • TXWM: The number of 32-bit words in the TX FIFO currently is currently less than the value set in CONTROL.TX_WATERMARK

Most SPI events signal a particular condition that persists until it is fixed, and these conditions can be detected by polling the corresponding field in the STATUS register.

In addition to these events, there are also two additional diagnostic fields in the STATUS register:

  • RXSTALL: The RXFIFO is full, and the SPI HOST is stalled and waiting for firmware to remove some data.
  • TXSTALL: The TX FIFO is not only empty, but the SPI HOST is stalled and waiting for firmware to add more data.

These bits can provide diagnostic data for tuning the throughput of the device, but do not themselves generate event interrupts.

By default none of these SPI events trigger an interrupt. They need to be enabled by writing to the corresponding field in EVENT_ENABLE.

The SPI event interrupt is signaled only when the IP enters the corresponding state. For example if an interrupt is requested when the TX FIFO is empty, the IP will only generate one interrupt when the last data word is transmitted from the TX FIFO. In this case, no new interrupts will be created until more data has been added to the FIFO, and all of it has been transmitted.

Error Interrupt Conditions

An error interrupt is usually caused by a violation of the SPI_HOST programming model:

By default all of these programming violations will cause an error interrupt when they occur. They will also halt the IP until the corresponding bit is cleared in the ERROR_STATUS register.

Each of these errors can be optionally ignored by clearing the corresponding bit in ERROR_ENABLE. Clearing an error-enable bit will suppress interrupts for that class of violation and will allow the IP to proceed even if one of these errors has occurred. The ERROR_STATUS register will continue to report all of these violations even if one of the corresponding bits in ERROR_ENABLE is zero.

The ERROR_STATUS bit should be cleared before clearing the error interrupt in the INTR_STATE register. Failure do to so may result in a repeated interrupt.

Status Indicators


Other Registers


The SPI_HOST state machine is disabled on reset. Before any commands are processed, the block must be enabled by writing one to the CONTROL.SPIEN register. Writing a zero to this register temporarily suspends any previously submitted transactions. If the block is re-enabled by writing a one to CONTROL.SPIEN, any previously executing commands will continue from wherever they left off.

An unacknowledged error interrupt will also suspend the core state machine.

Component reset

In addition to the global hardware reset, there are three software reset options.

  • The main control FSM can be held in reset by writing a one to CONTROL.RST_FSM. This can be used to cancel a previous command.
  • The TX FIFO can be cleared by writing a one to CONTROL.RST_TXFIFO
  • The RXFIFO can be cleared by writing a one to CONTROL.RST_RXFIFO

Block Diagram

Hardware Interfaces

Referring to the Comportable guideline for peripheral device functionality, the module spi_host has the following hardware interfaces defined.

Primary Clock: clk_i

Other Clocks: clk_core_i

Bus Device Interfaces (TL-UL): tl

Bus Host Interfaces (TL-UL): none

Peripheral Pins for Chip IO:

Pin namedirectionDescription

SPI Clock


Chip Select# (One hot, active low). The size of this port should match NumCS.


SPI data bus


Interrupt NameDescription

Error-related interrupts, see ERROR_ENABLE register for more information.


Event-related interrupts, see EVENT_ENABLE register for more information.

Security Alerts: none

Design Details

Component Overview.

TODO High level introductory description of

  • Control FSM
  • SDQ Shift register
  • Byte Select
  • Byte Merge
  • TX FIFO and RXFIFO interfaces

Command and Config CDC

Highlights for this unit:

  • New commands can always be written to COMMAND_0 or CONFIGOPTS_0
  • It is an error however to write a one to COMMAND_0.GO unless STATUS.READY is one.
  • The COMMAND_0.GO bit triggers a four-phase synchronizer, which copies the relevant multi-registers and cs_n masks to coreCmdConf.
  • STATUS.READY is low while this synchronizer is in operation
  • The core FSM is responsible for issuing the cc_ack signal.
  • coreCmdCnf is only updated and acknowledged (using cc_ack) when the FSM is not busy.

Shift Register

Standard mode

Dual mode

Quad mode

Byte Select

The Byte Select, or bytesel, unit is responsible for unpacking data from the FIFO to it can be loaded into the shift register

TODO: For simplicity move ByteOrder control to be between TXFIFO/TXDATA and between RXFIFO/RXDATA.

Byte Merge

End of Command

RXFIFO Full or TX FIFO Empty

Config/Command CDC

Passthrough Mode Multiplexors

Programmer’s Guide

TODO. (Outline Below)

Basic Configuration

Issuing a Standard SPI command

Issuing a Dual or Quad SPI command

Instruction code sent at Standard SPI bit width

All Bytes Sent at Dual or Quad Rate

Register Table

spi_host.INTR_STATE @ 0x0

Interrupt State Register

Reset default = 0x0, mask 0x3
  spi_event error

Error-related interrupts, see ERROR_ENABLE register for more information.


Event-related interrupts, see EVENT_ENABLE register for more information.

spi_host.INTR_ENABLE @ 0x4

Interrupt Enable Register

Reset default = 0x0, mask 0x3
  spi_event error

Enable interrupt when INTR_STATE.error is set.


Enable interrupt when INTR_STATE.spi_event is set.

spi_host.INTR_TEST @ 0x8

Interrupt Test Register

Reset default = 0x0, mask 0x3
  spi_event error

Write 1 to force INTR_STATE.error to 1.


Write 1 to force INTR_STATE.spi_event to 1.

spi_host.CONTROL @ 0xc

Control register

Reset default = 0x7f, mask 0xe000ffff

If EVENT_ENABLE.RXWM is set, the IP will send an interrupt when the depth of the RX FIFO reaches RX_WATERMARK words (32b each).


If EVENT_ENABLE.TXWM is set, the IP will send an interrupt when the depth of the RX FIFO drops below TX_WATERMARK words (32b each).


Enables Pass-through mode, wherein the SPI_HOST IP surrenders control of the SPI bus to another block. In this mode the sck, cs_n and sd signals are no longer driven by the SPI_HOST IP, rather they are multiplexed out to match the on-chip inputs pt_sck_i, pt_cs_n_i, pt_sden_i, pt_sdo_i, and pt_sdi_o. (Since the sd bus is bidirectional, there are separate input, output and tri-state controls for this bus.)


Clears the entire IP to the reset state when set to 1, including the FIFOs, the CDC's, the core state machine and the shift register. In the current implementation, the CDC FIFOs are drained not reset. Therefore software must confirm that both FIFO's empty before releasing clearing this bit.


Enables the SPI host. On reset, this field is 0, meaning that no transactions can proceed.

spi_host.STATUS @ 0x10

Status register

Reset default = 0x0, mask 0xffd0ffff

Transmit queue depth. Indicates how many unsent 32-bit words are currently in the TX FIFO. When active, this result may be an overestimate due to synchronization delays,


Receive queue depth. Indicates how many unread 32-bit words are currently in the RX FIFO. When active, this result may an underestimate due to synchronization delays.


If high, the number of 32-bits in the RX FIFO now exceeds the CONTROL.RX_WATERMARK entries (32b each).


The value of the ByteOrder parameter, provided so that firmware can confirm proper IP configuration.


If high, signifies that an ongoing transaction has stalled due to lack of available space in the RX FIFO


When high, indicates that the receive fifo is empty. Any reads from RX FIFO will cause an error interrupt.


When high, indicates that the receive fifo is full. Any ongoing transactions will stall until firmware reads some data from DATA.


If high, the amount of data in the TX FIFO has fallen below the level of CONTROL.TX_WATERMARK words (32b each).


If high, signifies that an ongoing transaction has stalled due to lack of data in the TX FIFO


When high, indicates that the transmit data fifo is empty.


When high, indicates that the transmit data fifo is full. Any further writes to DATA will create an error interrupt.


When high, indicates the SPI host is processing a previously issued command.


When high, indicates the SPI host is ready to receive commands. Writing to COMMAND when READY is low is an error, and will trigger an interrupt.

spi_host.CONFIGOPTS @ 0x14

Configuration options register.

Reset default = 0x0, mask 0xefffffff

Contains options for controlling each peripheral. One register per cs_n line


Core clock divider. Slows down subsequent SPI transactions by a factor of (CLKDIV+1) relative to the core clock frequency. The period of sck, T(sck) then becomes 2*(CLK_DIV+1)*T(core)


Minimum idle time between commands. Indicates the minimum number of sck half-cycles to hold cs_n high between commands. Setting this register to zero creates a minimally-wide CS_N-high pulse of one-half sck cycle.


CS_N Trailing Time. Indicates the number of half sck cycles, CSNTRAIL+1, to leave between last edge of sck and the rising edge of cs_n. Setting this register to zero corresponds to the minimum delay of one-half sck cycle.


CS_N Leading Time. Indicates the number of half sck cycles, CSNLEAD+1, to leave between the falling edge of cs_n and the first edge of sck. Setting this register to zero corresponds to the minimum delay of one-half sck cycle


Full cycle. Modifies the CPHA sampling behaviour to allow for longer device logic setup times. Rather than sampling the SD bus a half cycle after shifting out data, the data is sampled a full cycle after shifting data out. This means that if CPHA = 0, data is shifted out on the trailing edge, and sampled a full cycle later. If CPHA = 1, data is shifted and sampled with the trailing edge, also separated by a full cycle.


The phase of the sck clock signal relative to the data. When CPHA = 0, the data changes on the trailing edge of sck and is typically sampled on the leading edge. Conversely if CPHA = 1 high, data lines change on the leading edge of sck and are typically sampled on the trailing edge. CPHA should be chosen to match the phase of the selected device. The sampling behavior is modified by the !!CONFIGOPTS_0.FULLCYC bit.


The polarity of the sck clock signal. When CPOL is 0, sck is low when idle, and emits high pulses. When CPOL is low, sck is high when idle, and emits a series of low pulses.

spi_host.CSID @ 0x18

Chip-Select ID

Reset default = 0x0, mask 0xffffffff

Controls which device to target with the next command. This register is passed to the core whenever COMMAND is written. The core then asserts cio_csb_o[CSID] during the execution of the command.


Chip Select ID

spi_host.COMMAND @ 0x1c

Command Register

Reset default = 0x0, mask 0x3fff

Parameters specific to each command segment. One common register for all devices


Segment Length.

For read or write segments, this field controls the number of 1-byte bursts to transmit and or receive in this command segment. The number of cyles required to send or received a byte will depend on COMMAND.SPEED. For dummy segments, (COMMAND.DIRECTION == 0), this register controls the number of dummy cycles to issue.


Chip select active after transaction. If CSAAT = 0, the chip select line is raised immediately at the end of the command segment. If COMMAND.CSAAT = 1, the chip select line is left low at the end of the current transaction segment. This allows the creation longer, more complete SPI transactions, consisting of several separate segments for issuing instructions, pausing for dummy cycles, and transmitting or receiving data from the device.


The speed for this command segment: "0" = Standard SPI. "1" = Dual SPI. "2"=Quad SPI, "3": RESERVED.


The direction for the following command: "0" = Dummy cycles (no TX/RX). "1" = Rx only, "2" = Tx only, "3" Bidirectional Tx/Rx (Standard SPI mode only).

spi_host.DATA @ + 0x20
1 item wo window
Byte writes are supported

SPI Transmit and Receive Data.

Write data to this window to place it in the TXFIFO. Reads from this register pull data from the RXFIFO. Byte-enables are supported for writes.

The serial order of bit transmission is chosen to match SPI flash devices. Individual bytes are always transmitted with the most significant bit first. Multi-byte writes are also supported, and if ByteOrder = 0, the bits of DATA are transmitted strictly in order of decreasing signficance (i.e. most signicant bit first). 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 multi-byte data writes. (Though within each byte the most significant bit is always sent first.)

spi_host.ERROR_ENABLE @ 0x24

Controls which classes of errors raise an interrupt.

Reset default = 0x1f, mask 0x1f

Command Error: If this bit is set, the block sends an error interrupt whenever a command is issued while busy (i.e. a 1 is when STATUS.READY is not asserted.)


Overflow Errors: If this bit is set, the block sends an error interrupt whenever the TX FIFO overflows.


Underflow Errors: If this bit is set, the block sends an error interrupt whenever there is a read from DATA but the RX FIFO is empty.


Invalid Command Errors: If this bit is set, the block sends an error interrupt whenever a command is sent with invalid values for COMMAND.SPEED or COMMAND.DIRECTION.


Invalid CSID: If this bit is set, the block sends an error interrupt whenever a command is submitted, but CSID exceeds NumCS.

spi_host.ERROR_STATUS @ 0x28

Indicates that any errors that have occurred. When an error occurs, the corresponding bit must be cleared here before issuing any further commands.

Reset default = 0x0, mask 0x1f

Indicates a write to COMMAND when STATUS.READY = 0.


Indicates that firmware has overflowed the TX FIFO


Indicates that firmware has attempted to read from DATA when the RX FIFO is empty.


Indicates an invalid command segment, meaning either an invalid value of COMMAND.SPEED or a request for bidirectional data transfer at dual or quad speed


Indicates a command was attempted with an invalid value for CSID.

spi_host.EVENT_ENABLE @ 0x2c

Controls which classes of SPI events raise an interrupt.

Reset default = 0x0, mask 0x3f

Assert to send a spi_event interrupt whenever STATUS.RXFULL goes high


Assert to send a spi_event interrupt whenever STATUS.TXEMPTY goes high


Assert to send a spi_event interrupt whenever the number of 32-bit words in the RX FIFO is greater than CONTROL.RX_WATERMARK. To prevent the reassertion of this interrupt, read more data from the RX FIFO, or increase CONTROL.RX_WATERMARK.


Assert to send a spi_event interrupt whenever the number of 32-bit words in the TX FIFO is less than CONTROL.TX_WATERMARK. To prevent the reassertion of this interrupt add more data to the TX FIFO, or reduce CONTROL.TX_WATERMARK.


Assert to send a spi_event interrupt whenever STATUS.READY goes high


Assert to send a spi_event interrupt whenever STATUS.ACTIVE goes low