Skip to main content

SPI Interface for Cocotb

Regression Tests pdm-managed pre-commit

GitHub repository: https://github.com/schang412/cocotbext-spi

Introduction

SPI simulation framework for cocotb.

Installation

Installation from pip (release version, stable):

pip install cocotbext-spi

Installation from git (latest development version, potentially unstable):

pip install https://github.com/schang412/cocotbext-spi/archive/main.zip

Installation for active development:

git clone https://github.com/schang412/cocotbext-spi
pip install -e cocotbext-spi

Documentation and Usage

See the tests directory for complete testbenches using these modules.

SPI Signals

The SPI bus signals are bundled together into a SpiBus class.

If the port instantiations look like:

module my_module(
    input  wire sclk, 
    input  wire mosi,
    output wire miso,
    input  wire cs,  // active-low
)

The SpiBus class can be created as:

from cocotbext.spi import SpiBus
spi_bus = SpiBus.from_entity(dut)

If there is some prefix, the from_prefix class method may be used:

module my_module(
    input  wire spi0_sclk, 
    input  wire spi0_mosi,
    output wire spi0_miso,
    input  wire spi0_cs,  // active-low
)
spi_bus = SpiBus.from_prefix(dut, "spi0")

If some signals have been renamed for clarity:

module my_module(
    input  wire spi0__sck,
    input  wire spi0__mosi,
    output wire spi0__miso,
    input  wire spi0__ncs,  // active-low
)
spi_bus = SpiBus.from_prefix(dut, "spi0", bus_separator="__", sclk_name="sck", cs_name="ncs")

SPI Config

SPI Configuration parameters are bundled together into a SpiConfig class.

To create the object simply call it like a class and pass in arguments:

from cocotbext.spi import SpiConfig

spi_config = SpiConfig(
    word_width = 16,        # number of bits in a SPI transaction
    sclk_freq  = 25e6,      # clock rate in Hz
    cpol       = False,     # clock idle polarity
    cpha       = True,      # clock phase (CPHA=True means data sampled on second edge)
    msb_first  = True,      # the order that bits are clocked onto the wire
    data_output_idle = 1,   # the idle value of the MOSI or MISO line
    frame_spacing_ns = 1,   # the spacing between frames that the master waits for or the slave obeys
                            #       the slave should raise SpiFrameError if this is not obeyed.
    ignore_rx_value = None, # MISO value that should be ignored when received
    cs_active_low = True    # the chip select is active low
)

All parameters are optional, and the defaults are shown above.

SPI Master

The SpiMaster class acts as an SPI Master endpoint.

To use this class, import it, configure it, and connect to the dut.

from cocotbext.spi import SpiMaster, SpiBus, SpiConfig

spi_bus = SpiBus.from_entity(dut)

spi_config = SpiConfig(
    word_width = 16,     # all parameters optional
    sclk_freq  = 25e6,   # these are the defaults
    cpol       = False,
    cpha       = True,
    msb_first  = True,
    cs_active_low = True # optional (assumed True)
)

spi_master = SpiMaster(spi_bus, spi_config)

To send data into a design with SpiMaster, call write() or write_nowait(). Accepted data types are iterables of ints including lists, bytes, bytearrays, etc. Optionally, call wait() to wait for the transmit operation to complete. We can take a look at the data received back with read() or read_nowait()

# TX/RX transaction example
spi_master.write_nowait([0xFFFF])
await spi_master.wait()
read_bytes = await spi_master.read()
print(read_bytes)

# we can alternatively call (which has equivalent functionality)
await spi_master.write([0xFFFF])
read_bytes = await spi_masetr.read()

Constructor Parameters

  • bus: SpiBus
  • config: SpiConfig

Methods

  • write(data): send data (blocking)
  • write_nowait(data): send data (non-blocking)
  • read(count=-1): read count bytes from buffer, reading whole buffer by default (blocking)
  • read_nowait(count=-1): read count bytes from buffer, reading whole buffer by default (non-blocking)
  • count_tx(): returns the number of items in the transmit queue
  • count_rx(): returns the number of items in the receive queue
  • empty_tx(): returns True if the transmit queue is empty
  • empty_rx(): returns True if the receive queue is empty
  • idle(): returns True if the transmit and receive buffers are empty
  • clear(): drop all data in the queue

SPI Slave

The SpiSlaveBase acts as an abstract class for a SPI Slave Endpoint.

To use this class, import it and inherit it. Then use the subclass as the slave and connect it to the dut.

from cocotbext.spi import SpiMaster, SpiBus, SpiConfig

class SimpleSpiSlave(SpiSlaveBase):
    def __init__(self, bus):
        self._config = SpiConfig()
        self.content = 0
        super().__init__(bus)

    async def get_content(self):
        await self.idle.wait()
        return self.content

    async def _transaction(self, frame_start, frame_end):
        await frame_start
        self.idle.clear()

        self.content = int(await self._shift(16, tx_word=(0xAAAA)))

        await frame_end

spi_slave = SimpleSpiSlave(SpiBus.from_entity(dut))

Implementation

All SPI Slave Classes should:

  • inherit the SpiSlaveBase class
  • define self._config adjust the values for:
    • word_width
    • cpha
    • cpol
    • msb_first
    • frame_spacing_ns
  • implement a _transaction coroutine
    • the coroutine should take 3 arguments, self, frame_start and frame_end
    • the coroutine should await frame_start at the transaction start, and frame_end when done.
      • frame_start and frame_end are Rising and Falling edges of the chip select based on the chip select polarity
    • when the coroutine receives a frame_start signal, it should clear the self.idle Event.
      • self.idle is automatically set when _transaction returns
  • when implementing a method to read the class contents, make sure to await the self.idle, otherwise the data may not be up to date because the device is in the middle of a transaction.

Simulated Devices

This framework includes some SPI Slave devices built in. A list of supported devices can be found in cocotbext/spi/devices and are sorted by vendor.

To use these devices, you can simply import them.

from cocotbext.spi.devices.TI import DRV8306

spi_slave = DRV8306(SpiBus.from_entity(dut, cs_name="ncs"))

To submit a new device, make a pull request.

Metadata

Release files for cocotbext-spi 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cocotbext-spi 0.5.0
File Size Uploaded
cocotbext_spi-0.5.0.tar.gz 29.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cocotbext-spi 0.5.0
File Interpreter ABI Platform
cocotbext_spi-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 50.1 kB

Release files / cocotbext_spi-0.5.0.tar.gz

Download URL cocotbext_spi-0.5.0.tar.gz
Size 29.8 kB
Tags Source
SHA-256 checksum
How to use checksums
67f76fbee61574cbc6670da53d53270a6b549d914f6c21761c5fc1c65d9b45c4
BLAKE2b-256 checksum
How to use checksums
d31c3e6c179fb6e41571e82febf4b3eec9c35583c662ec5e1a7a3ac41e64e4f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.20.0.post1 CPython/3.10.15 Linux/6.5.0-1025-azure

Release files / cocotbext_spi-0.5.0-py3-none-any.whl

Download URL cocotbext_spi-0.5.0-py3-none-any.whl
Size 20.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c4e2c9cce2382e4529dac9b03b171c92988241c644afafb2a35a556812b9e10b
BLAKE2b-256 checksum
How to use checksums
deb7530c612220c180f01276e4177f5c0d1617fa4f7b4eae6070dae429db0462
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.20.0.post1 CPython/3.10.15 Linux/6.5.0-1025-azure

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page