Skip to content

Instantly share code, notes, and snippets.

@cr1901
Created March 30, 2016 04:34
Show Gist options
  • Select an option

  • Save cr1901/077b0bf15bd373f425f4c7a908e063d5 to your computer and use it in GitHub Desktop.

Select an option

Save cr1901/077b0bf15bd373f425f4c7a908e063d5 to your computer and use it in GitHub Desktop.
ARTIQ/MiSoC SPI Compare/Recommendations

Florent/MiSoC SPI Master

  • 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.

ARTIQ Gateware SPI Master

  • TODO

ARTIQ Coredevice SPI Master

  • Pads start in a Hi-Z state (can be done in Florent's core by passing in a pads record that includes Tristates?)
  • 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 SPIMaster class that communicates with the SPI serial engine. More of a "link-layer" class? SPIMaster also directly outputs CS signals outside the FPGA. Perhaps move this functionality into MiSoC?

Composite (Merge Florent and ARTIQ SPIMasters)

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 SPIMaster in artiq/artiq/gateware/spi.py should be kept in that file (possibly rename to ControlUnit or 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.
  • AutoCSR will automatically generate C header with addresses for registers as well as appropriate write sequence.
  • Though ARTIQ's SPIMaster doesn'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?
@enjoy-digital

Copy link
Copy Markdown

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment