- Inherits from AutoCSR class to generate an API for writing to device.
- Control signals to connect to other hardware also CSR-bus compatible.
- Single-device master (only one CS_N signal)
- Configurable polarity, except data read/writes must be opposite polarity.
- Registers:
- Status: Transfer is done/not done.
- Length: Can set a number of bits to send. This number can exceed the bus width.
- MISO: R/O Data input.
- MOSI: R/W Data output.
- TODO
- Pads start in a Hi-Z state (can be done in Florent's core by passing in a
padsrecord that includesTristates?) - Configurable clock polarity of all 4 types.
- Configurable endianness.
- Configurable CS polarity.
- Chaining capable (doing multiple xfers w/o deasserting CS)
- Registers:
SPI_DATA_ADDR, SPI_XFER_ADDR, SPI_CONFIG_ADDR = range(3)
SPI_DATA_ADDR: Buffered, so a queue can immediately end new data once an xfer starts.SPI_XFER_ADDR: Number of bytes to read/write per xfer. Mask for device select.SPI_CONFIG_ADDR:
1 offline: all pins high-z (reset=1)
1 active: cs/transfer active (read-only)
1 pending: transfer pending in intermediate buffer (read-only)
1 cs_polarity: active level of chip select (reset=0)
1 clk_polarity: idle level of clk (reset=0)
1 clk_phase: first edge after cs assertion to sample data on (reset=0)
(clk_polarity, clk_phase) == (CPOL, CPHA) in Freescale language.
(0, 0): idle low, output on falling, input on rising
(0, 1): idle low, output on rising, input on falling
(1, 0): idle high, output on rising, input on falling
(1, 1): idle high, output on falling, input on rising
There is never a clk edge during a cs edge.
1 lsb_first: LSB is the first bit on the wire (reset=0)
1 half_duplex: 3-wire SPI, in/out on mosi (reset=0)
8 undefined
8 div_write: counter load value to divide this module's clock
to generate the SPI write clk (reset=0)
f_clk/f_spi_write == div_write + 2
8 div_read: ditto for the read clock
- Status Codes:
(
SPI_OFFLINE,
SPI_ACTIVE,
SPI_PENDING,
SPI_CS_POLARITY,
SPI_CLK_POLARITY,
SPI_CLK_PHASE,
SPI_LSB_FIRST,
SPI_HALF_DUPLEX,
) = (1 << i for i in range(8))
- Includes application-specific state machine in
SPIMasterclass that communicates with the SPI serial engine. More of a "link-layer" class?SPIMasteralso directly outputs CS signals outside the FPGA. Perhaps move this functionality into MiSoC?
The SPIMaster core should receive a CSR-based wrapper around SPIMachine in addition to the raw wishbone based wrapper. Verify that the core provides at least the functionality of the current SPI master in misoc. Add C header and api functions. Coordinate the change and alert people. Move to misoc.
- Either Florent's or ARTIQ serial engine are probably fine.
- Convert the ARTIQ Wishbone bus to live in the CSR region of the ARTIQ SoC.
- The Class
SPIMasterinartiq/artiq/gateware/spi.pyshould be kept in that file (possibly rename toControlUnitor something?). All other functionality moved to MiSoC.- MiSoC is the driver that xmits/receives bits/selects relevant device. Delegates to gateware "application" to interpret bits.
AutoCSRwill automatically generate C header with addresses for registers as well as appropriate write sequence.- Though ARTIQ's
SPIMasterdoesn't do this, I have seen FPGA cores where the SPI transfer length varies depending on the current transfer. Is it feasible to need to support this? Add control signal to update xfer length dynamically?
It's probably better to only reuse the ARTIQ serial engine with a CSR wrapper as @jordens is suggesting. (You can remove my SPIMaster) With a simple example of C code to do SPI transfers I'll be able to convert my code easily.