| Name | cocotbext-spi JSON |
| Version |
0.4.0
JSON |
| download |
| home_page | |
| Summary | SPI modules for cocotb |
| upload_time | 2023-10-05 17:30:54 |
| maintainer | |
| docs_url | None |
| author | |
| requires_python | >=3.7 |
| license | MIT |
| keywords |
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# SPI Interface for Cocotb
[](https://github.com/schang412/cocotbext-spi/actions/workflows/regression-tests.yml)
[](https://pdm.fming.dev)
[](https://github.com/pre-commit/pre-commit)
GitHub repository: https://github.com/schang412/cocotbext-spi
## Introduction
SPI simulation framework for [cocotb](https://github.com/cocotb/cocotb).
## Installation
Installation from pip (release version, stable):
```bash
pip install cocotbext-spi
```
Installation from git (latest development version, potentially unstable):
```bash
pip install https://github.com/schang412/cocotbext-spi/archive/main.zip
```
Installation for active development:
```bash
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:
```verilog
module my_module(
input wire sclk,
input wire mosi,
output wire miso,
input wire cs, // active-low
)
```
The `SpiBus` class can be created as:
```python
from cocotbext.spi import SpiBus
spi_bus = SpiBus.from_entity(dut)
```
If there is some prefix, the `from_prefix` class method may be used:
```verilog
module my_module(
input wire spi0_sclk,
input wire spi0_mosi,
output wire spi0_miso,
input wire spi0_cs, // active-low
)
```
```python
spi_bus = SpiBus.from_prefix(dut, "spi0")
```
If the chip select has been renamed for clarity:
```verilog
module my_module(
input wire spi0_sclk,
input wire spi0_mosi,
output wire spi0_miso,
input wire spi0_ncs, // active-low
)
```
```python
spi_bus = SpiBus.from_prefix(dut, "spi0", 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:
```python
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.
```python
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()`
```python
# 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.
```python
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.
```python
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.
Raw data
{
"_id": null,
"home_page": "",
"name": "cocotbext-spi",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "",
"author": "",
"author_email": "Spencer Chang <spencer@sycee.xyz>",
"download_url": "https://files.pythonhosted.org/packages/6f/29/6f38dfbaff47ae64cca6a342334e3a9c322556325333189662e895dcc1b7/cocotbext-spi-0.4.0.tar.gz",
"platform": null,
"description": "# SPI Interface for Cocotb\n\n[](https://github.com/schang412/cocotbext-spi/actions/workflows/regression-tests.yml)\n[](https://pdm.fming.dev)\n[](https://github.com/pre-commit/pre-commit)\n\nGitHub repository: https://github.com/schang412/cocotbext-spi\n\n## Introduction\n\nSPI simulation framework for [cocotb](https://github.com/cocotb/cocotb).\n\n## Installation\n\nInstallation from pip (release version, stable):\n```bash\npip install cocotbext-spi\n```\n\nInstallation from git (latest development version, potentially unstable):\n```bash\npip install https://github.com/schang412/cocotbext-spi/archive/main.zip\n```\n\nInstallation for active development:\n```bash\ngit clone https://github.com/schang412/cocotbext-spi\npip install -e cocotbext-spi\n```\n\n## Documentation and Usage\n\nSee the `tests` directory for complete testbenches using these modules.\n\n### SPI Signals\n\nThe SPI bus signals are bundled together into a `SpiBus` class.\n\nIf the port instantiations look like:\n```verilog\nmodule my_module(\n input wire sclk, \n input wire mosi,\n output wire miso,\n input wire cs, // active-low\n)\n```\nThe `SpiBus` class can be created as:\n```python\nfrom cocotbext.spi import SpiBus\nspi_bus = SpiBus.from_entity(dut)\n```\n\nIf there is some prefix, the `from_prefix` class method may be used:\n```verilog\nmodule my_module(\n input wire spi0_sclk, \n input wire spi0_mosi,\n output wire spi0_miso,\n input wire spi0_cs, // active-low\n)\n```\n```python\nspi_bus = SpiBus.from_prefix(dut, \"spi0\")\n```\n\nIf the chip select has been renamed for clarity:\n```verilog\nmodule my_module(\n input wire spi0_sclk, \n input wire spi0_mosi,\n output wire spi0_miso,\n input wire spi0_ncs, // active-low\n)\n```\n```python\nspi_bus = SpiBus.from_prefix(dut, \"spi0\", cs_name=\"ncs\")\n```\n\n### SPI Config\n\nSPI Configuration parameters are bundled together into a `SpiConfig` class.\n\nTo create the object simply call it like a class and pass in arguments:\n```python\nfrom cocotbext.spi import SpiConfig\n\nspi_config = SpiConfig(\n word_width = 16, # number of bits in a SPI transaction\n sclk_freq = 25e6, # clock rate in Hz\n cpol = False, # clock idle polarity\n cpha = True, # clock phase (CPHA=True means data sampled on second edge)\n msb_first = True, # the order that bits are clocked onto the wire\n data_output_idle = 1, # the idle value of the MOSI or MISO line\n frame_spacing_ns = 1, # the spacing between frames that the master waits for or the slave obeys\n # the slave should raise SpiFrameError if this is not obeyed.\n ignore_rx_value = None, # MISO value that should be ignored when received\n cs_active_low = True # the chip select is active low\n)\n```\n\nAll parameters are optional, and the defaults are shown above.\n\n### SPI Master\n\nThe `SpiMaster` class acts as an SPI Master endpoint.\n\nTo use this class, import it, configure it, and connect to the dut.\n\n```python\nfrom cocotbext.spi import SpiMaster, SpiBus, SpiConfig\n\nspi_bus = SpiBus.from_entity(dut)\n\nspi_config = SpiConfig(\n word_width = 16, # all parameters optional\n sclk_freq = 25e6, # these are the defaults\n cpol = False,\n cpha = True,\n msb_first = True,\n cs_active_low = True # optional (assumed True)\n)\n\nspi_master = SpiMaster(spi_bus, spi_config)\n```\n\nTo 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()`\n\n```python\n# TX/RX transaction example\nspi_master.write_nowait([0xFFFF])\nawait spi_master.wait()\nread_bytes = await spi_master.read()\nprint(read_bytes)\n\n# we can alternatively call (which has equivalent functionality)\nawait spi_master.write([0xFFFF])\nread_bytes = await spi_masetr.read()\n```\n\n#### Constructor Parameters\n- `bus`: SpiBus\n- `config`: SpiConfig\n\n#### Methods\n- `write(data)`: send data (blocking)\n- `write_nowait(data)`: send data (non-blocking)\n- `read(count=-1)`: read count bytes from buffer, reading whole buffer by default (blocking)\n- `read_nowait(count=-1)`: read count bytes from buffer, reading whole buffer by default (non-blocking)\n- `count_tx()`: returns the number of items in the transmit queue\n- `count_rx()`: returns the number of items in the receive queue\n- `empty_tx()`: returns True if the transmit queue is empty\n- `empty_rx()`: returns True if the receive queue is empty\n- `idle()`: returns True if the transmit and receive buffers are empty\n- `clear()`: drop all data in the queue\n\n### SPI Slave\n\nThe `SpiSlaveBase` acts as an abstract class for a SPI Slave Endpoint.\n\nTo use this class, import it and inherit it. Then use the subclass as the slave and connect it to the dut.\n\n```python\nfrom cocotbext.spi import SpiMaster, SpiBus, SpiConfig\n\nclass SimpleSpiSlave(SpiSlaveBase):\n def __init__(self, bus):\n self._config = SpiConfig()\n self.content = 0\n super().__init__(bus)\n\n async def get_content(self):\n await self.idle.wait()\n return self.content\n\n async def _transaction(self, frame_start, frame_end):\n await frame_start\n self.idle.clear()\n\n self.content = int(await self._shift(16, tx_word=(0xAAAA)))\n\n await frame_end\n\nspi_slave = SimpleSpiSlave(SpiBus.from_entity(dut))\n```\n\n#### Implementation\n\nAll SPI Slave Classes should:\n- inherit the SpiSlaveBase class\n- define `self._config` adjust the values for:\n - `word_width`\n - `cpha`\n - `cpol`\n - `msb_first`\n - `frame_spacing_ns`\n- implement a `_transaction` coroutine\n - the coroutine should take 3 arguments, self, frame_start and frame_end\n - the coroutine should await frame_start at the transaction start, and frame_end when done.\n - frame_start and frame_end are Rising and Falling edges of the chip select based on the chip select polarity\n - when the coroutine receives a frame_start signal, it should clear the `self.idle` Event.\n - `self.idle` is automatically set when `_transaction` returns\n- 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.\n\n\n#### Simulated Devices\n\nThis 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.\n\nTo use these devices, you can simply import them.\n\n```python\nfrom cocotbext.spi.devices.TI import DRV8306\n\nspi_slave = DRV8306(SpiBus.from_entity(dut, cs_name=\"ncs\"))\n```\n\nTo submit a new device, make a pull request.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "SPI modules for cocotb",
"version": "0.4.0",
"project_urls": {
"repository": "https://github.com/schang412/cocotbext-spi"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "38735d9fc9e6251a8435e385d1f8611dbfab264388c7daa9f392661d8fecd78d",
"md5": "4a8529d54acfbb3bf2f5258dc9ffa7fb",
"sha256": "6daa4db2a2c4ec18cece00d3517f258ffc710e982776e4cb885cc82421c5bb89"
},
"downloads": -1,
"filename": "cocotbext_spi-0.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4a8529d54acfbb3bf2f5258dc9ffa7fb",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 20113,
"upload_time": "2023-10-05T17:30:53",
"upload_time_iso_8601": "2023-10-05T17:30:53.020179Z",
"url": "https://files.pythonhosted.org/packages/38/73/5d9fc9e6251a8435e385d1f8611dbfab264388c7daa9f392661d8fecd78d/cocotbext_spi-0.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6f296f38dfbaff47ae64cca6a342334e3a9c322556325333189662e895dcc1b7",
"md5": "931df386c759e7ba89d2a4e8201ca878",
"sha256": "3c2339e7dea6c7d6a70df7017526db39c7d87628af6e5f2a480ae37a5c4b992d"
},
"downloads": -1,
"filename": "cocotbext-spi-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "931df386c759e7ba89d2a4e8201ca878",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 29637,
"upload_time": "2023-10-05T17:30:54",
"upload_time_iso_8601": "2023-10-05T17:30:54.675640Z",
"url": "https://files.pythonhosted.org/packages/6f/29/6f38dfbaff47ae64cca6a342334e3a9c322556325333189662e895dcc1b7/cocotbext-spi-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-10-05 17:30:54",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "schang412",
"github_project": "cocotbext-spi",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "cocotbext-spi"
}