# luna-soc Documentation

## eptri - SoC controller for the LUNA USB Device

General Description

`eptri` (endpoint-tri) is a three-interface CSR controller that allows a CPU or Wishbone design to control the endpoints of a LUNA USB Device.

Features

- CONTROL peripheral for managing device connection, reset and connection speed.

- SETUP interface peripheral for reading control transactions from the host.

- OUT interface peripheral for reading data transfers from the host.

- IN interface peripheral for writing data transactions to the host.

### Introduction

#### Definitions

- Controller refers to the `eptri` controller as a whole, including all peripherals.

- Peripheral refers to `USBDeviceController`, `SetupFIFOInterface`, `InFIFOInterface` or `OutFIFOInterface`.

### Block Diagram

                                 ┌────────────────────────────────────────┐      ┌──────────────────────────────────────┐
                                 │USBDevice                               │      │EPTRI                                 │
                                 │                                        │      │                                      │
                                 │                                        │      ├───────────────────────────┬──────────┤
                                 │                                        │      │USBDeviceController        │Registers │◀─────────▶
                                 ├─────────────┐      ┌───────────────────┤      │                           ├──────────┤
                                 │UTMIInterface│      │EndpointMultiplexer│      │                           │IRQ       │──────────▶
                                 │             │      │                   │      ├───────────────────────────┼──────────┤
               ┌──────────┐      │             │      │                   │      │SetupFIFOInterface┌───────▶│Registers │◀─────────▶
               │USB PHY   │      │             │      │                   │      ├──────────┐       │        ├──────────┤
    ◀─── D+ ──▶│          │      │             │      │                   │      │8B FIFO   │───────┘        │IRQ       │──────────▶
               │          │◀────▶│             │◀────▶│                   │◀────▶├──────────┴────────────────┼──────────┤              SoC
    ◀─── D- ──▶│          │      │             │      │                   │      │InFIFOInterface   ┌────────│Registers │◀─────────▶
               │          │      │             │      │                   │      ├──────────┐       │        ├──────────┤
               └──────────┘      │             │      │                   │      │512B FIFO │◀──────┘        │IRQ       │──────────▶
                                 │             │      │                   │      ├──────────┴────────────────┼──────────┤
                                 │             │      │                   │      │OutFIFOInterface  ┌───────▶│Registers │◀─────────▶
                                 │             │      │                   │      ├──────────┐       │        ├──────────┤
                                 │             │      │                   │      │512B FIFO │───────┘        │IRQ       │──────────▶
                                 └─────────────┴──────┴───────────────────┘      └──────────┴────────────────┴──────────┘

### Usage

The exact details for integrating a LUNA eptri peripheral into a design will depend on the SoC platform you are using.

For example, using `luna-soc`:

    class Top(Elaboratable):
        def __init__(self):
            # instantiate the SoC
            self.soc = LunaSoC(
                cpu=VexRiscv(reset_addr=0x00000000, variant="cynthion"),
                clock_frequency=int(60e6),
            )

            # instantiate the eptri device controller peripheral
            self.usb0 = USBDeviceController()

            # instantiate the three endpoint interface peripherals
            self.usb0_ep_control = SetupFIFOInterface()
            self.usb0_ep_in = InFIFOInterface()
            self.usb0_ep_out = OutFIFOInterface()

            # add the peripherals to the SoC
            self.soc.add_peripheral(self.usb0)
            self.soc.add_peripheral(self.usb0_ep_control, as_submodule=False)
            self.soc.add_peripheral(self.usb0_ep_in, as_submodule=False)
            self.soc.add_peripheral(self.usb0_ep_out, as_submodule=False)

    def elaborate(self, platform):
        m = Module()

        m.submodules.soc = self.soc

        # instantiate a LUNA USB device
        usb0_bus = platform.request(platform.default_usb_connection)
        usb0_device = USBDevice(bus=usb0_bus)

        # add the eptri endpoint interface peripherals to the LUNA USB device
        # as endpoint handlers
        usb0_device.add_endpoint(self.usb0_ep_control)
        usb0_device.add_endpoint(self.usb0_ep_in)
        usb0_device.add_endpoint(self.usb0_ep_out)

        # connect the eptri device controller to the LUNA USB device
        m.d.comb += self.usb0.attach(usb0_device)

        m.submodules.usb0_device = usb0_device

        return m

### Registers

The `eptri` controller provides four sets of registers corresponding to each peripheral.

#### `USBx` - USBDeviceController

CONTROL Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0000 | [0:0] | read-write | `connect`
0x0000 | [8:8] | read-write | `low_speed_only`
0x0000 | [9:9] | read-write | `full_speed_only`

    Control register

            connect:         Set this bit to '1' to allow the associated USB device to connect to a host.
            low_speed_only:  Set this bit to '1' to force the device to operate at low speed.
            full_speed_only: Set this bit to '1' to force the device to operate at full speed.

STATUS Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0002 | [1:0] | read-only | `speed`

    Status register

            speed: Indicates the current speed of the USB device. 0 indicates High; 1 => Full,
                   2 => Low, and 3 => SuperSpeed (incl SuperSpeed+).

EV_ENABLE Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0008 | [0:0] | read-write | `mask`

EV_PENDING Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0009 | [0:0] | read-write | `mask`

#### `USBx_EP_CONTROL` - SetupFIFOInterface

CONTROL Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0000 | [7:0] | write-only | `address`

    Control register

           address: Controls the current device's USB address. Should be written after a SET_ADDRESS
                    request is received. Automatically resets back to zero on a USB reset.

STATUS Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0002 | [7:0] | read-only | `address`
0x0002 | [11:8] | read-only | `epno`
0x0002 | [12:12] | read-only | `have`

    Status register

           address: Holds the current device's active USB address.
           epno:    The endpoint number associated with the most recently captured SETUP packet.
           have:    `1` iff data is available in the FIFO.

RESET Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0004 | [0:0] | write-only | `fifo`

    Reset register

           fifo: Local reset control for the SETUP handler; writing a '1' to this register clears
                 the handler state.

DATA Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0005 | [7:0] | read-only | `byte`

    Data register

           A FIFO that returns the bytes from the most recently captured SETUP packet.
           Reading a byte from this register advances the FIFO. The first eight bytes read
           from this contain the core SETUP packet.

EV_ENABLE Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0010 | [0:0] | read-write | `mask`

EV_PENDING Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0011 | [0:0] | read-write | `mask`

#### `USBx_EP_IN` - InFIFOInterface

ENDPOINT Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0000 | [3:0] | write-only | `number`

    Endpoint register

           number: Contains the endpoint the enqueued packet is to be transmitted on. Writing to this field
                   marks the relevant packet as ready to transmit; and thus should only be written after a
                   full packet has been written into the FIFO. If no data has been placed into the DATA FIFO,
                   a zero-length packet is generated.
                   Note that any IN requests that do not match the endpoint number are automatically NAK'd.

STALL Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0001 | [0:0] | write-only | `stalled`

    Stall register

           stalled: When this field contains '1', any IN tokens targeting `epno` will be responded to with a
                    STALL token, rather than DATA or a NAK.
                    For EP0, this field will automatically be cleared when a new SETUP token is received.

PID Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0002 | [0:0] | write-only | `toggle`

    Pid register

           toggle: Sets the current PID toggle bit for the given endpoint.

STATUS Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0004 | [15:0] | read-only | `nak`
0x0004 | [19:16] | read-only | `epno`
0x0004 | [24:24] | read-only | `idle`
0x0004 | [25:25] | read-only | `have`
0x0004 | [26:26] | read-only | `pid`

    Status register

           nak:  Contains a bitmask of endpoints that have responded with a NAK since the
                 last read of this register.
           epno: Contains the endpoint being transmitted on.
           idle: This value is `1` if no packet is actively being transmitted.
           have: This value is `1` if data is present in the transmit FIFO.
           pid:  Contains the current PID toggle bit for the given endpoint.

RESET Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0008 | [0:0] | write-only | `fifo`

    Reset register

           fifo: A write to this field Clears the FIFO without transmitting.

DATA Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0009 | [7:0] | write-only | `byte`

    Data register

           Each write enqueues a byte to be transmitted; gradually building a single packet to
           be transmitted. This queue should only ever contain a single packet; it is the software's
           responsibility to handle breaking requests down into packets.

EV_ENABLE Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0010 | [0:0] | read-write | `mask`

EV_PENDING Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0011 | [0:0] | read-write | `mask`

#### `USBx_EP_OUT` - OutFIFOInterface

CONTROL Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0000 | [7:0] | read-write | `address`

    Control register

           address: Controls the current device's USB address. Should be written after a SET_ADDRESS request
                    is received. Automatically resets back to zero on a USB reset.

ENDPOINT Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0001 | [3:0] | read-write | `number`

    Endpoint register

           number: Selects the endpoint number to prime. This interface allows priming multiple endpoints
           at once. That is, multiple endpoints can be ready to receive data at a time. See the `prime`
           and `enable` bits for usage.

ENABLE Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0002 | [0:0] | write-only | `enabled`

    Enable register

           enabled: Controls whether any data can be received on any primed OUT endpoint. This bit is
                    automatically cleared on receive in order to give the controller time to read data
                    from the FIFO. It must be re-enabled once the FIFO has been emptied.

PRIME Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0003 | [0:0] | write-only | `primed`

    Prime register

           primed: Controls "priming" an out endpoint. To receive data on any endpoint, the CPU must first
                   select the endpoint with the `epno` register; and then write a '1' into the prime and
                   enable register. This prepares our FIFO to receive data; and the next OUT transaction will
                   be captured into the FIFO.

                   When a transaction is complete, the `enable` bit is reset; the `prime` is not. This
                   effectively means that `enable` controls receiving on _any_ of the primed endpoints;
                   while `prime` can be used to build a collection of endpoints willing to participate in
                   receipt.

                   Note that this does not apply to the control endpoint. Once the control endpoint has
                   received a packet it will be un-primed and need to be re-primed before it can receive
                   again. This is to ensure that we can establish an order on the receipt of the setup
                   packet and any associated data.

                   Only one transaction / data packet is captured per `enable` write; repeated enabling is
                   necessary to capture multiple packets.

STALL Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0004 | [0:0] | write-only | `stalled`

    Stall register

           stalled: Controls STALL'ing the active endpoint. Setting or clearing this bit will set or clear
                    STALL on the provided endpoint. Endpoint STALLs persist even after `epno` is changed; so
                    multiple endpoints can be stalled at once by writing their respective endpoint numbers
                    into `epno` register and then setting their `stall` bits.

PID Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0005 | [0:0] | write-only | `toggle`

    Pid register

           toggle: Sets the current PID toggle bit for the given endpoint.

STATUS Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0006 | [3:0] | read-only | `epno`
0x0006 | [8:8] | read-only | `have`
0x0006 | [9:9] | read-only | `pid`

    Status register

           epno: Contains the endpoint number associated with the data in the FIFO -- that is,
                 the endpoint number on which the relevant data was received.
           have: `1` iff data is available in the FIFO.
           pid:  Contains the current PID toggle bit for the given endpoint.

RESET Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0008 | [0:0] | write-only | `fifo`

    Reset register

           fifo: Local reset for the OUT handler; clears the out FIFO.

DATA Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0009 | [7:0] | read-only | `byte`

    Data register

           Read-only register. A FIFO that returns the bytes from the most recently captured OUT transaction.
           Reading a byte from this register advances the FIFO.

           byte:    Contains the most recently received byte.

EV_ENABLE Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0020 | [0:0] | read-write | `mask`

EV_PENDING Register

Offset | Range | Access | Field
--- | --- | --- | ---
0x0021 | [0:0] | read-write | `mask`

### Interrupts

Each of the `eptri` peripherals can generate the following interrupts:

USBDeviceController Registers
Interrupt | Peripheral | Description
--- | --- | ---
USBx | USBDeviceController | Interrupt that triggers when the host issued a USB bus reset.
USBx_EP_CONTROL | SetupFIFOInterface | Interrupt that triggers when the host wrote a new SETUP packet to the bus.
USBx_EP_IN | InFIFOInterface | Interrupt that triggers after the peripheral has written a data packet to the bus and read back a PID ACK response from the host.
USBx_EP_OUT | OutFIFOInterface | Interrupt that triggers when the peripheral has read a data packet from the host.

### Programming Guide

The programming guide provides sequence diagrams that detail the steps required to perform the various operations supported by the `eptri` controller.

The following pseudo-code is used through-out to indicate register operations:

Register Operations
Operation | Description
--- | ---
`r(PERIPHERAL.register)` | Read a value from the `register` belonging to `PERIPHERAL`.
`w(PERIPHERAL.register, bits)` | Write `bits` to the `register` belonging to `PERIPHERAL`.

#### Device Connection

#### Bus Reset

#### Control OUT Transfers

#### Control IN Transfers

#### Bulk OUT Transfers

#### Bulk IN Transfers

## luna_soc

### luna_soc package

#### Subpackages

##### luna_soc.gateware package

###### Subpackages

###### luna_soc.gateware.core package

###### Subpackages

###### luna_soc.gateware.core.spiflash package

###### Submodules

###### luna_soc.gateware.core.spiflash.controller module

class luna_soc.gateware.core.spiflash.controller.SPIController(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  Wishbone generic SPI Flash Controller interface.

  Provides a generic SPI Controller that can be interfaced using CSRs. Supports multiple access modes with the help of `width` and `mask` registers which can be used to configure the PHY into any supported SDR mode (single/dual/quad/octal).

  class Cs(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    SPI chip select register

    select : SPI chip select signal.

    select: <amaranth_soc.csr.reg.Field object at 0x7f65625fa450>
  class Data(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Data register

    rx : Read the next byte in the RX FIFO tx : Write the given byte to the TX FIFO

  class Phy(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    PHY control register

    length : SPI transfer length in bits. width : SPI transfer bus width (1/2/4/8). mask : SPI DQ output enable mask.

  class Status(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Status register

    rx_ready : RX FIFO contains data. tx_ready : TX FIFO ready to receive data.

    rx_ready: <amaranth_soc.csr.reg.Field object at 0x7f6561a2e470>
    tx_ready: <amaranth_soc.csr.reg.Field object at 0x7f6561a2e580>
  elaborate(platform)

###### luna_soc.gateware.core.spiflash.mmap module

class luna_soc.gateware.core.spiflash.mmap.SPIFlashMemoryMap(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  Wishbone Memory-mapped SPI Flash controller.

  Supports sequential accesses so that command and address is only sent when necessary.

  MMAP_DEFAULT_TIMEOUT = 256
  OE_MASK = {1: 1, 2: 3, 4: 15, 8: 255}
  elaborate(platform)
  static reverse_bytes(word)

###### luna_soc.gateware.core.spiflash.phy module

class luna_soc.gateware.core.spiflash.phy.ECP5ConfigurationFlashInterface(*args, src_loc_at=0, **kwargs)

  Bases: `Elaboratable`

  Gateware that creates a connection to an MSPI configuration flash.

  Automatically uses appropriate platform resources; this abstracts away details necessary to e.g. drive the MCLK lines on an ECP5, which has special handling.

  __init__(*, bus)

    Params: bus – The SPI bus object to extend.

  elaborate(platform)

class luna_soc.gateware.core.spiflash.phy.SPIClockGenerator(*args, src_loc_at=0, **kwargs)

  Bases: `Elaboratable`

  elaborate(platform)

class luna_soc.gateware.core.spiflash.phy.SPIPHYController(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  Provides a generic PHY that can be used by a SPI flash controller.

  It supports single/dual/quad/octal output reads from the flash chips.

  elaborate(platform)

###### luna_soc.gateware.core.spiflash.port module

class luna_soc.gateware.core.spiflash.port.SPIControlPort(data_width)

  Bases: `Signature`

class luna_soc.gateware.core.spiflash.port.SPIControlPortCDC(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  Converts one SPIControlPort between clock domains.

  elaborate(platform)

class luna_soc.gateware.core.spiflash.port.SPIControlPortCrossbar(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  Merge multiple SPIControlPorts with a round-robin scheduler.

  elaborate(platform)
  get_port(index)

class luna_soc.gateware.core.spiflash.port.StreamCore2PHY(data_width)

  Bases: `Signature`

  create(*, path=None, src_loc_at=0)

    Create an interface object from this signature.

    The default `Signature.create()` implementation consists of one line:

        def create(self, *, path=None, src_loc_at=0):
            return PureInterface(self, path=path, src_loc_at=1 + src_loc_at)

    This implementation creates an interface object from this signature that serves purely as a container for the attributes corresponding to the signature members, and implements no behavior. Such an implementation is sufficient for signatures created ad-hoc using the :py:`Signature({ ... })` constructor as well as simple signature subclasses.

    When defining a `Signature` subclass that needs to customize the behavior of the created interface objects, override this method with a similar implementation that references the class of your custom interface object:

        class CustomSignature(wiring.Signature):
            def create(self, *, path=None, src_loc_at=0):
                return CustomInterface(self, path=path, src_loc_at=1 + src_loc_at)

        class CustomInterface(wiring.PureInterface):
            @property
            def my_property(self):
                ...

    The :py:`path` and :py:`src_loc_at` arguments are necessary to ensure the generated signals have informative names and accurate source location information.

    The custom `create()` method may take positional or keyword arguments in addition to the two listed above. Such arguments must have a default value, because the `SignatureMembers.create()` method will call the `Signature.create()` member without these additional arguments when this signature is a member of another signature.

  property data_width

class luna_soc.gateware.core.spiflash.port.StreamCore2PHYInterface(signature, *, path=None, src_loc_at=0)

  Bases: `PureInterface`

  property payload

    Joint signal with all data.

class luna_soc.gateware.core.spiflash.port.StreamPHY2Core(data_width)

  Bases: `Signature`

  create(*, path=None, src_loc_at=0)

    Create an interface object from this signature.

    The default `Signature.create()` implementation consists of one line:

        def create(self, *, path=None, src_loc_at=0):
            return PureInterface(self, path=path, src_loc_at=1 + src_loc_at)

    This implementation creates an interface object from this signature that serves purely as a container for the attributes corresponding to the signature members, and implements no behavior. Such an implementation is sufficient for signatures created ad-hoc using the :py:`Signature({ ... })` constructor as well as simple signature subclasses.

    When defining a `Signature` subclass that needs to customize the behavior of the created interface objects, override this method with a similar implementation that references the class of your custom interface object:

        class CustomSignature(wiring.Signature):
            def create(self, *, path=None, src_loc_at=0):
                return CustomInterface(self, path=path, src_loc_at=1 + src_loc_at)

        class CustomInterface(wiring.PureInterface):
            @property
            def my_property(self):
                ...

    The :py:`path` and :py:`src_loc_at` arguments are necessary to ensure the generated signals have informative names and accurate source location information.

    The custom `create()` method may take positional or keyword arguments in addition to the two listed above. Such arguments must have a default value, because the `SignatureMembers.create()` method will call the `Signature.create()` member without these additional arguments when this signature is a member of another signature.

  property data_width

class luna_soc.gateware.core.spiflash.port.StreamPHY2CoreInterface(signature, *, path=None, src_loc_at=0)

  Bases: `PureInterface`

  property payload

    Joint signal with all data.

###### luna_soc.gateware.core.spiflash.utils module

class luna_soc.gateware.core.spiflash.utils.RoundRobin(*args, src_loc_at=0, **kwargs)

  Bases: `Elaboratable`

  Round-robin scheduler.

  For a given set of requests, the round-robin scheduler will grant one request. Once it grants a request, if any other requests are active, it grants the next active request with a greater number, restarting from zero once it reaches the highest one.

  Use `EnableInserter` to control when the scheduler is updated.

  ###### Parameters

  countint

    Number of requests.

  ###### Attributes

  requestsSignal(count), in

    Set of requests.

  grantSignal(range(count)), out

    Number of the granted request. Does not change if there are no active requests.

  validSignal(), out

    Asserted if grant corresponds to an active request. Deasserted otherwise, i.e. if no requests are active.

  elaborate(platform)

class luna_soc.gateware.core.spiflash.utils.WaitTimer(*args, src_loc_at=0, **kwargs)

  Bases: `Elaboratable`

  elaborate(platform)

###### Module contents

class luna_soc.gateware.core.spiflash.ECP5ConfigurationFlashInterface(*args, src_loc_at=0, **kwargs)

  Bases: `Elaboratable`

  Gateware that creates a connection to an MSPI configuration flash.

  Automatically uses appropriate platform resources; this abstracts away details necessary to e.g. drive the MCLK lines on an ECP5, which has special handling.

  __init__(*, bus)

    Params: bus – The SPI bus object to extend.

  elaborate(platform)

class luna_soc.gateware.core.spiflash.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  SPI Flash peripheral main module.

  This class provides a wrapper that can instantiate both `SPIController` and `SPIFlashMemoryMap` and connect them to the PHY.

  Both options share access to the PHY using a crossbar. Also, performs CDC if a different clock is used in the PHY.

  elaborate(platform)

class luna_soc.gateware.core.spiflash.PinSignature

  Bases: `Signature`

class luna_soc.gateware.core.spiflash.SPIPHYController(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  Provides a generic PHY that can be used by a SPI flash controller.

  It supports single/dual/quad/octal output reads from the flash chips.

  elaborate(platform)

###### luna_soc.gateware.core.usb2 package

###### Submodules

###### luna_soc.gateware.core.usb2.device module

Contains the organizing gateware used to add USB Device functionality to your own designs; including the core `USBDevice` class.

class luna_soc.gateware.core.usb2.device.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  SoC controller for a USBDevice.

  Breaks our USBDevice control and status signals out into registers so a CPU / Wishbone master can control our USB device.

  The attributes below are intended to connect to a USBDevice. Typically, they’d be created by using the .controller() method on a USBDevice object, which will automatically connect all relevant signals.

  ###### Attributes

  connect: Signal(), output

    High when the USBDevice should be allowed to connect to a host.

  class Control(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Control register

    connect: Set this bit to ‘1’ to allow the associated USB device to connect to a host. low_speed_only: Set this bit to ‘1’ to force the device to operate at low speed. full_speed_only: Set this bit to ‘1’ to force the device to operate at full speed.

    connect: <amaranth_soc.csr.reg.Field object at 0x7f6561717450>
    full_speed_only: <amaranth_soc.csr.reg.Field object at 0x7f6561732af0>
    low_speed_only: <amaranth_soc.csr.reg.Field object at 0x7f6561750ad0>
  class Status(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Status register

    speed: Indicates the current speed of the USB device. 0 indicates High; 1 => Full,

      2 => Low, and 3 => SuperSpeed (incl SuperSpeed+).

    speed: <amaranth_soc.csr.reg.Field object at 0x7f65617691d0>
  attach(device: USBDevice)

    Returns a list of statements necessary to connect this to a USB controller.

    The returned values makes all of the connections necessary to provide control and fetch status from the relevant USB device. These can be made either combinationally or synchronously, but combinational is recommended; as these signals are typically fed from a register anyway.

    ###### Parameters

    device: USBDevice

      The `USBDevice` object to be controlled.

  elaborate(platform)

###### luna_soc.gateware.core.usb2.ep_control module

Implementation of a Triple-FIFO endpoint manager.

Equivalent (but not binary-compatbile) implementation of ValentyUSB’s `eptri`.

For an example, see `examples/usb/eptri` or TinyUSB’s `luna/dcd_eptri.c`.

class luna_soc.gateware.core.usb2.ep_control.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  Setup component of our eptri-equivalent interface.

  Implements the USB Setup FIFO, which handles SETUP packets on any endpoint.

  This interface is similar to an `OutFIFOInterface`, but always ACKs packets, and does not allow for any flow control; as a USB device must always be ready to accept control packets. [USB2.0: 8.6.1]

  ###### Attributes

  interface: EndpointInterface

    Our primary interface to the core USB device hardware.

  class Control(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Control register

    address: Controls the current device’s USB address. Should be written after a SET_ADDRESS

      request is received. Automatically resets back to zero on a USB reset.

    address: <amaranth_soc.csr.reg.Field object at 0x7f656162dfd0>
  class Data(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Data register

    A FIFO that returns the bytes from the most recently captured SETUP packet. Reading a byte from this register advances the FIFO. The first eight bytes read from this contain the core SETUP packet.

    byte: <amaranth_soc.csr.reg.Field object at 0x7f65616979d0>
  class Reset(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Reset register

    fifo: Local reset control for the SETUP handler; writing a ‘1’ to this register clears

      the handler state.

    fifo: <amaranth_soc.csr.reg.Field object at 0x7f65616b01d0>
  class Status(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Status register

    address: Holds the current device’s active USB address. epno: The endpoint number associated with the most recently captured SETUP packet. have: 1 iff data is available in the FIFO.

    address: <amaranth_soc.csr.reg.Field object at 0x7f6561689e10>
    epno: <amaranth_soc.csr.reg.Field object at 0x7f65616bf710>
    have: <amaranth_soc.csr.reg.Field object at 0x7f65616bf770>
  elaborate(platform)

###### luna_soc.gateware.core.usb2.ep_in module

Implementation of a Triple-FIFO endpoint manager.

Equivalent (but not binary-compatbile) implementation of ValentyUSB’s `eptri`.

For an example, see `examples/usb/eptri` or TinyUSB’s `luna/dcd_eptri.c`.

class luna_soc.gateware.core.usb2.ep_in.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  IN component of our eptri-equivalent interface.

  Implements the FIFO that handles eptri IN requests. This FIFO collects USB data, and transmits it in response to an IN token. Like all eptri interfaces; it can handle only one pending packet at a time.

  ###### Attributes

  interface: EndpointInterface

    Our primary interface to the core USB device hardware.

  class Data(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Data register

    Each write enqueues a byte to be transmitted; gradually building a single packet to be transmitted. This queue should only ever contain a single packet; it is the software’s responsibility to handle breaking requests down into packets.

    byte: <amaranth_soc.csr.reg.Field object at 0x7f6561437d70>
  class Endpoint(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Endpoint register

    number: Contains the endpoint the enqueued packet is to be transmitted on. Writing to this field

      marks the relevant packet as ready to transmit; and thus should only be written after a full packet has been written into the FIFO. If no data has been placed into the DATA FIFO, a zero-length packet is generated. Note that any IN requests that do not match the endpoint number are automatically NAK’d.

    number: <amaranth_soc.csr.reg.Field object at 0x7f65614705f0>
  class Pid(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Pid register

    toggle: Sets the current PID toggle bit for the given endpoint.

    toggle: <amaranth_soc.csr.reg.Field object at 0x7f6561470e90>
  class Reset(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Reset register

    fifo: A write to this field Clears the FIFO without transmitting.

    fifo: <amaranth_soc.csr.reg.Field object at 0x7f65614716d0>
  class Stall(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Stall register

    stalled: When this field contains ‘1’, any IN tokens targeting epno will be responded to with a

      STALL token, rather than DATA or a NAK. For EP0, this field will automatically be cleared when a new SETUP token is received.

    stalled: <amaranth_soc.csr.reg.Field object at 0x7f6561471f70>
  class Status(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Status register

    nak: Contains a bitmask of endpoints that have responded with a NAK since the

      last read of this register.

    epno: Contains the endpoint being transmitted on. idle: This value is 1 if no packet is actively being transmitted. have: This value is 1 if data is present in the transmit FIFO. pid: Contains the current PID toggle bit for the given endpoint.

    epno: <amaranth_soc.csr.reg.Field object at 0x7f6561472990>
    have: <amaranth_soc.csr.reg.Field object at 0x7f6561472c30>
    idle: <amaranth_soc.csr.reg.Field object at 0x7f6561472b10>
    nak: <amaranth_soc.csr.reg.Field object at 0x7f65614728d0>
    pid: <amaranth_soc.csr.reg.Field object at 0x7f6561472d50>
  __init__(max_packet_size=512)

    ###### Parameters

    > max_packet_size: int, optional

    >   Sets the maximum packet size that can be transmitted on this endpoint. This should match the value provided in the relevant endpoint descriptor.

  elaborate(platform)

###### luna_soc.gateware.core.usb2.ep_out module

Implementation of a Triple-FIFO endpoint manager.

Equivalent (but not binary-compatbile) implementation of ValentyUSB’s `eptri`.

For an example, see `examples/usb/eptri` or TinyUSB’s `luna/dcd_eptri.c`.

class luna_soc.gateware.core.usb2.ep_out.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  OUT component of our eptri

  Implements the OUT FIFO, which handles receiving packets from our host.

  ###### Attributes

  interface: EndpointInterface

    Our primary interface to the core USB device hardware.

  class Control(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Control register

    address: Controls the current device’s USB address. Should be written after a SET_ADDRESS request

      is received. Automatically resets back to zero on a USB reset.

    address: <amaranth_soc.csr.reg.Field object at 0x7f65612a25d0>
  class Data(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Data register

    Read-only register. A FIFO that returns the bytes from the most recently captured OUT transaction. Reading a byte from this register advances the FIFO.

    byte: Contains the most recently received byte.

    byte: <amaranth_soc.csr.reg.Field object at 0x7f65612a2db0>
  class Enable(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Enable register

    enabled: Controls whether any data can be received on any primed OUT endpoint. This bit is

      automatically cleared on receive in order to give the controller time to read data from the FIFO. It must be re-enabled once the FIFO has been emptied.

    enabled: <amaranth_soc.csr.reg.Field object at 0x7f65612a35f0>
  class Endpoint(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Endpoint register

    number: Selects the endpoint number to prime. This interface allows priming multiple endpoints at once. That is, multiple endpoints can be ready to receive data at a time. See the prime and enable bits for usage.

    number: <amaranth_soc.csr.reg.Field object at 0x7f65612a3e90>
  class Pid(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Pid register

    toggle: Sets the current PID toggle bit for the given endpoint.

    toggle: <amaranth_soc.csr.reg.Field object at 0x7f65612ac6b0>
  class Prime(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Prime register

    primed: Controls “priming” an out endpoint. To receive data on any endpoint, the CPU must first

      select the endpoint with the epno register; and then write a ‘1’ into the prime and enable register. This prepares our FIFO to receive data; and the next OUT transaction will be captured into the FIFO.

      When a transaction is complete, the enable bit is reset; the prime is not. This effectively means that enable controls receiving on _any_ of the primed endpoints; while prime can be used to build a collection of endpoints willing to participate in receipt.

      Note that this does not apply to the control endpoint. Once the control endpoint has received a packet it will be un-primed and need to be re-primed before it can receive again. This is to ensure that we can establish an order on the receipt of the setup packet and any associated data.

      Only one transaction / data packet is captured per enable write; repeated enabling is necessary to capture multiple packets.

    primed: <amaranth_soc.csr.reg.Field object at 0x7f65612acef0>
  class Reset(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Reset register

    fifo: Local reset for the OUT handler; clears the out FIFO.

    fifo: <amaranth_soc.csr.reg.Field object at 0x7f65612ad850>
  class Stall(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Stall register

    stalled: Controls STALL’ing the active endpoint. Setting or clearing this bit will set or clear

      STALL on the provided endpoint. Endpoint STALLs persist even after epno is changed; so multiple endpoints can be stalled at once by writing their respective endpoint numbers into epno register and then setting their stall bits.

    stalled: <amaranth_soc.csr.reg.Field object at 0x7f65612ae030>
  class Status(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Status register

    epno: Contains the endpoint number associated with the data in the FIFO – that is,

      the endpoint number on which the relevant data was received.

    have: 1 iff data is available in the FIFO. pid: Contains the current PID toggle bit for the given endpoint.

    epno: <amaranth_soc.csr.reg.Field object at 0x7f65612ae8d0>
    have: <amaranth_soc.csr.reg.Field object at 0x7f65612aebd0>
    pid: <amaranth_soc.csr.reg.Field object at 0x7f65612aeb10>
  __init__(max_packet_size=512)

    ###### Parameters

    > max_packet_size: int, optional

    >   Sets the maximum packet size that can be transmitted on this endpoint. This should match the value provided in the relevant endpoint descriptor.

  elaborate(platform)

###### luna_soc.gateware.core.usb2.ulpi module

ULPI interfacing hardware.

class luna_soc.gateware.core.usb2.ulpi.Signature

  Bases: `Signature`

  ULPI bus signature.

  ###### Interface attributes

  i`Signal`

    Input value of the ULPI data lines.

  o`Signal`

    Output value of the ULPI data lines.

  oe`Signal`

    True iff we’re trying to drive the ULPI data lines.

  clk`Signal`

    The ULPI clock signal.

  nxt`Signal`

    The ULPI ‘next’ throttle signal.

  stp`Signal`

    The ULPI ‘stop’ event signal.

  dir`Signal`

    The ULPI bus-direction signal.

  rst`Signal`

    The ULPI ‘reset’ signal.

###### Module contents

###### Submodules

###### luna_soc.gateware.core.blockram module

class luna_soc.gateware.core.blockram.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  SRAM storage peripheral.

  ###### Parameters

  sizeint

    Memory size in bytes.

  data_widthint

    The width of each memory word.

  granularityint

    The number of bits of data per each address.

  writablebool

    Memory is writable.

  initlist[byte] Optional

    The initial value of the relevant memory.

  namestr

    A descriptive name for the given memory.

  ###### Attributes

  bus`amaranth_soc.wishbone.Interface`

    Wishbone bus interface.

  property constant_map
  elaborate(platform)
  property init

###### luna_soc.gateware.core.ila module

class luna_soc.gateware.core.ila.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  A simple peripheral interface to the ila.

  class Control(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    A CSR register.

    ###### Parameters

    fields`dict` or `list` or `Field`

      Collection of register fields. If `None` (default), a dict is populated from Python variable annotations. `fields` is used to create a `FieldActionMap`, `FieldActionArray`, or `FieldAction`, depending on its type (dict, list, or Field).

    ###### Interface attributes

    element`Element`

      Interface between this register and a CSR bus primitive.

    ###### Attributes

    field`FieldActionMap` or `FieldActionArray` or `FieldAction`

      Collection of field instances.

    f`FieldActionMap` or `FieldActionArray` or `FieldAction`

      Shorthand for `Register.field`.

    ###### Raises

    `TypeError`

      If `fields` is neither `None`, a `dict`, a `list`, or a `Field`.

    `ValueError`

      If `fields` is not `None` and at least one variable annotation is a `Field`.

    `ValueError`

      If `element.access` is not readable and at least one field is readable.

    `ValueError`

      If `element.access` is not writable and at least one field is writable.

    trigger: <amaranth_soc.csr.reg.Field object at 0x7f6561fc46e0>
  class Trace(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    A CSR register.

    ###### Parameters

    fields`dict` or `list` or `Field`

      Collection of register fields. If `None` (default), a dict is populated from Python variable annotations. `fields` is used to create a `FieldActionMap`, `FieldActionArray`, or `FieldAction`, depending on its type (dict, list, or Field).

    ###### Interface attributes

    element`Element`

      Interface between this register and a CSR bus primitive.

    ###### Attributes

    field`FieldActionMap` or `FieldActionArray` or `FieldAction`

      Collection of field instances.

    f`FieldActionMap` or `FieldActionArray` or `FieldAction`

      Shorthand for `Register.field`.

    ###### Raises

    `TypeError`

      If `fields` is neither `None`, a `dict`, a `list`, or a `Field`.

    `ValueError`

      If `fields` is not `None` and at least one variable annotation is a `Field`.

    `ValueError`

      If `element.access` is not readable and at least one field is readable.

    `ValueError`

      If `element.access` is not writable and at least one field is writable.

    a: <amaranth_soc.csr.reg.Field object at 0x7f6562657d90>
    b: <amaranth_soc.csr.reg.Field object at 0x7f6562657c50>
    c: <amaranth_soc.csr.reg.Field object at 0x7f65625d9810>
    d: <amaranth_soc.csr.reg.Field object at 0x7f65625d96e0>
  elaborate(platform)

###### luna_soc.gateware.core.timer module

A simple timer peripheral.

class luna_soc.gateware.core.timer.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  class Counter(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    A CSR register.

    ###### Parameters

    fields`dict` or `list` or `Field`

      Collection of register fields. If `None` (default), a dict is populated from Python variable annotations. `fields` is used to create a `FieldActionMap`, `FieldActionArray`, or `FieldAction`, depending on its type (dict, list, or Field).

    ###### Interface attributes

    element`Element`

      Interface between this register and a CSR bus primitive.

    ###### Attributes

    field`FieldActionMap` or `FieldActionArray` or `FieldAction`

      Collection of field instances.

    f`FieldActionMap` or `FieldActionArray` or `FieldAction`

      Shorthand for `Register.field`.

    ###### Raises

    `TypeError`

      If `fields` is neither `None`, a `dict`, a `list`, or a `Field`.

    `ValueError`

      If `fields` is not `None` and at least one variable annotation is a `Field`.

    `ValueError`

      If `element.access` is not readable and at least one field is readable.

    `ValueError`

      If `element.access` is not writable and at least one field is writable.

    __init__(width)

      Counter value

  class Enable(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Counter enable

    enable: <amaranth_soc.csr.reg.Field object at 0x7f6561e84450>
  class Mode(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Timer mode. When `periodic` is set to 1 the counter will automatically be reset to the reload value.

    periodic: <amaranth_soc.csr.reg.Field object at 0x7f6561e87b50>
  class Reload(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    Reload value of counter.

  elaborate(platform)

###### luna_soc.gateware.core.uart module

class luna_soc.gateware.core.uart.Peripheral(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  class BaudRate(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    baud rate divider, defaults to init

  class RxAvail(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    is ‘1’ when 1-byte receive buffer is full; reset by a read from rx_data

    rxe: <amaranth_soc.csr.reg.Field object at 0x7f6561dc9400>
  class RxData(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    valid to read from when rx_avail is high, last received byte

    data: <amaranth_soc.csr.reg.Field object at 0x7f6561dc99a0>
  class TxData(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    valid to write to when tx_rdy is high, will trigger a transmit

    data: <amaranth_soc.csr.reg.Field object at 0x7f6561c30c90>
  class TxReady(*args, src_loc_at=0, **kwargs)

    Bases: `Register`

    is ‘1’ when 1-byte transmit buffer is empty

    txe: <amaranth_soc.csr.reg.Field object at 0x7f6561c30910>
  elaborate(platform)

class luna_soc.gateware.core.uart.PinSignature

  Bases: `Signature`

  UART pin signature.

  ###### Interface attributes

  tx`Signal`

    Output.

  rx`Signal`

    Input.

###### Module contents

###### luna_soc.gateware.cpu package

###### Submodules

###### luna_soc.gateware.cpu.ic module

The simplest interrupt controller.

class luna_soc.gateware.cpu.ic.InterruptController(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  add(peripheral, *, name, number=None)
  elaborate(platform)
  interrupts() → dict[int, (<class 'str'>, <class 'amaranth.lib.wiring.Component'>)]

###### luna_soc.gateware.cpu.minerva module

###### luna_soc.gateware.cpu.vexriscv module

class luna_soc.gateware.cpu.vexriscv.VexRiscv(*args, src_loc_at=0, **kwargs)

  Bases: `Component`

  arch = 'riscv'
  byteorder = 'little'
  data_width = 32
  elaborate(platform)
  name = 'vexriscv'
  property reset_addr

###### Module contents

##### luna_soc.generate package

###### Submodules

###### luna_soc.generate.c module

Generate a C library for SoC designs.

class luna_soc.generate.c.Header(memory_map: ~amaranth_soc.memory.MemoryMap, interrupts: dict[int, (<class 'str'>, <class 'amaranth.lib.wiring.Component'>)])

  Bases: `object`

  generate(file=None, macro_name='SOC_RESOURCES', platform_name='Generic Platform')

    Generate a C header file that simplifies access to the platform’s resources.

    Parameters:

      - macro_name – Optional. The name of the guard macro for the C header, as a string without spaces.

      - file – Optional. If provided, this will be treated as the file= argument to the print() – function. This can be used to generate file content instead of printing to the terminal.

class luna_soc.generate.c.LinkerScript(memory_map: MemoryMap, reset_addr: int = 0)

  Bases: `object`

  generate(file=None, macro_name='SOC_RESOURCES', platform_name='Generic Platform')

    Generates a ldscript that holds our primary RAM and ROM regions.

    Parameters:

      file – Optional. If provided, this will be treated as the file= argument to the print() – function. This can be used to generate file content instead of printing to the terminal.

###### luna_soc.generate.introspect module

Introspection tools for SoC designs.

luna_soc.generate.introspect.csr_base(memory_map: MemoryMap) → int

  Scan a memory map for the starting address for csr peripheral registers.

luna_soc.generate.introspect.csr_peripherals(memory_map: MemoryMap) → dict[Name, list[ResourceInfo]]

  Scan a memory map for csr peripheral registers.

luna_soc.generate.introspect.interrupts(fragment: Component) → dict[int, (<class 'str'>, <class 'amaranth.lib.wiring.Component'>)]

luna_soc.generate.introspect.memory_map(fragment: Component) → MemoryMap

luna_soc.generate.introspect.reset_addr(fragment: Component) → MemoryMap

luna_soc.generate.introspect.soc(fragment: Component) → Component

luna_soc.generate.introspect.wb_peripherals(memory_map: MemoryMap) → dict[~amaranth_soc.memory.MemoryMap.Name, list[tuple[~amaranth.lib.wiring.Component, ~amaranth_soc.memory.MemoryMap.Name, (<class 'int'>, <class 'int'>)]]]

  Scan a memory map for wishbone peripherals.

###### luna_soc.generate.rust module

Generate Rust support files for SoC designs.

class luna_soc.generate.rust.LinkerScript(memory_map: MemoryMap, reset_addr: int = 0)

  Bases: `object`

  generate(file=None)

    Generate a memory.x file for the given SoC design

###### luna_soc.generate.svd module

Generate a SVD file for SoC designs.

class luna_soc.generate.svd.SVD(memory_map: ~amaranth_soc.memory.MemoryMap, interrupts: dict[int, (<class 'str'>, <class 'amaranth.lib.wiring.Component'>)])

  Bases: `object`

  generate(file=None, vendor='luna-soc', name='soc', description=None)

###### Module contents

##### luna_soc.util package

###### Submodules

###### luna_soc.util.readbin module

luna_soc.util.readbin.get_boot_address(filename_or_regions, offset=0)

luna_soc.util.readbin.get_mem_data(filename_or_regions, data_width=32, endianness='big', mem_size=None, offset=0)

luna_soc.util.readbin.get_mem_regions(filename_or_regions, offset)

###### Module contents

#### Submodules

##### luna_soc.top_level_cli module

luna_soc.top_level_cli.build(args, fragment, platform, build_dir)

  Top-level build command. Invokes the build steps for each artifact to be generated.

luna_soc.top_level_cli.top_level_cli(fragment, *pos_args, **kwargs)

  Runs a default CLI that assists in building and running SoC gateware.

  If the user’s options resulted in the board being programmed, this returns the fragment that was programmed onto the board. Otherwise, it returns None.

  Parameters:

    fragment – The design to be built; or a callable that returns a fragment, – such as a Elaborable type. If the latter is provided, any keyword or positional arguments not specified here will be passed to this callable.

#### Module contents

- Index

- Module Index