Programmable IO¶
The Programmable IO IP Core is a versatile and highly configurable module designed for generating and controlling low-speed digital interfaces. It features an internal state machine that can be programmed to drive the IO signal in various sequences. This allows the IP core to support a wide range of protocols and custom interfaces by bit-banging the signal according to the programmed commands.
State Machine¶
The core of the Programmable IO IP Core is its internal state machine, which operates in four distinct states:
Signal High (HIGH)
In this state, the IO signal is set to a high logic level (1).
This state is used when the protocol requires a high signal on the IO line.
Command value: 0x0
Signal Low (LOW)
In this state, the IO signal is set to a low logic level (0).
This state is used when the protocol requires a low signal on the IO line.
Command value: 0x1
Wait (WAIT)
The WAIT state introduces a delay in the signal transition.
It is useful for timing control, ensuring that the signal remains in its current state for a specified period.
Command value: 0x2
Read (READ)
In the READ state, the core samples the IO signal and returns its value.
This state is essential for protocols that require reading data from the IO line.
Command value: 0x3
Command Interface¶
The state machine transitions between these states based on commands received via a control interface. Each command specifies the next state and any necessary parameters, such as the duration of the WAIT state or the number of pins to read in the READ state.
Example Commands:
SET_HIGH: Transition to the HIGH state.
SET_LOW: Transition to the LOW state.
SET_WAIT(n): Enter the WAIT state for ‘n’ clock cycles.
READ: Transition to the READ state and capture the current IO signal.
Usage¶
To utilize the Programmable IO IP Core for bit-banging various low-speed interfaces, users must configure the state machine with a sequence of commands that reflect the desired protocol’s timing and signal transitions. The commands can be sent in real-time, allowing dynamic reconfiguration based on operational needs.
Example Sequence:
SET_LOW: Start with the signal low.
SET_WAIT(10): Wait for 10 clock cycles.
SET_HIGH: Set the signal high.
SET_WAIT(5): Wait for 5 clock cycles.
READ: Read the signal to capture the input value.
This sequence could be part of a protocol where the signal is pulled low, held for a period, then raised, and a value is read from the line.
Applications¶
The flexibility of the Programmable IO IP Core makes it suitable for a variety of applications, including but not limited to:
Custom serial communication protocols
GPIO signal manipulation
Interface with legacy hardware with specific timing requirements
Prototyping new digital communication standards
Configuration¶
Available bus architectures:
APB3
Wishbone
AvalonMM
By default, all buses are defined with 12 bit address and 32 bit data width.
Parameter¶
Pio.Parameter defines the IO pins of the programmable IO controller.
Name |
Type |
Description |
Default |
---|---|---|---|
Width |
Int |
Number of IO pins. Must be greater then 0. |
PioCtrl.InitParameter defines the initialization values for certian registers.
Name |
Type |
Description |
Default |
---|---|---|---|
clockDivider |
Int |
Initialization value of the internal clock divider |
0 |
readDelay |
Int |
Initialization value of the register which delays read actions |
0 |
Note
Parameter in InitParameter with a value “0” are equal to disabled. This allows to only set certain parameters.
PioCtrl.MemoryMappedParameter defines the FIFO width.
Name |
Type |
Description |
Default |
---|---|---|---|
commandFifoDepth |
Int |
FIFO depth for incoming commands. |
16 |
readFifoDepth |
Int |
FIFO depth for outgoing read results. |
8 |
PioCtrl.PermissionParameter defines the permission rules for bus access.
Name |
Type |
Description |
Default |
---|---|---|---|
busCanWriteClockDividerConfig |
Boolean |
Toggles bus access to the clock divider. |
PioCtrl.Parameter configures the programmable IO controller. It uses Pio.Parameter as parameter.
Name |
Type |
Description |
Default |
---|---|---|---|
io |
Pio.Parameter |
Class with IO parameters |
|
readBufferDepth |
Int |
Number of registers on the input path to stabilize read values. Disabled when 0. |
2 |
init |
PioCtrl.InitParameter |
Class to parametrize the initialization values. |
InitParameter.disabled |
permission |
PioCtrl.PermissionParameter |
Class to set bus access. |
PermissionParameter.granted |
memory |
PioCtrl.MemoryMappedParameter |
Class to define FIFO depth. |
MemoryMappedParameter.default |
dataWidth |
Int |
Width of the data field used in the command FIFO to pass additional information to the controller. |
24 |
clockDividerWidth |
Int |
Width of the clock divider counter. |
20 |
readDelayWidth |
Int |
Width of the read delay counter. |
8 |
PioCtrl.Parameter has some functions with pre-predefined parameters for common use-cases.
object Parameter {
def default(pins: Int = 1) =
Parameter(Pio.Parameter(pins))
def light(pins: Int = 1) =
Parameter(Pio.Parameter(pins), memory = MemoryMappedParameter.lightweight, dataWidth = 16)
}
Register Mapping¶
IP Identification:
The register map starts with an IP Identification block to provide all information about the underlying IP core to software drivers. This allows to provide backwards compatible drivers.
Address |
Bit |
Field |
Default |
Permission |
Description |
---|---|---|---|---|---|
0x000 |
31 - 24 |
API |
0x0 |
Rx |
API version of the implemented IP Identification. |
23 - 16 |
Length |
0x8 |
Rx |
Length of the IP Identification block in Bytes. |
|
15 - 0 |
ID |
0x1 |
Rx |
IP value of this IP core. |
|
0x004 |
31 - 24 |
Major Version |
0x1 |
Rx |
Major number if this IP core. Version schema is major.minor.patch. |
23 - 16 |
Minor Version |
0x0 |
Rx |
Minor number if this IP core. Version schema is major.minor.patch. |
|
15 - 0 |
Patch Version |
0x0 |
Rx |
Patch number if this IP core. Version schema is major.minor.patch. |
Self Disclosure:
This block discloses information about the IP core to software drivers to simplify them.
Address |
Bit |
Field |
Default |
Permission |
Description |
---|---|---|---|---|---|
0x008 |
31 - 24 |
readBufferDepth |
Rx |
Number of registers on the input path to stabilize read values. |
|
23 - 16 |
clockDividerWidth |
Rx |
Width of the clock divider counter. |
||
15 - 8 |
dataWidth |
Rx |
Width of the data field used in the command FIFO to pass additional information to the controller. |
||
7 - 0 |
IO width |
Rx |
Number of IO pins. |
||
0x00C |
15 - 8 |
readFifoDepth |
Rx |
Depth of the read FIFO. |
|
7 - 0 |
commandFifoDepth |
Rx |
Depth of the command FIFO. |
||
0x010 |
0 |
busCanWriteClockDividerConfig |
Rx |
Flag whether the clock divider is writable. |
Command and Read FIFO:
Address |
Bit |
Field |
Default |
Permission |
Description |
---|---|---|---|---|---|
0x014 |
16 |
validBit |
Rx |
This bit contains a 1 when the result FIFO returned valid payload. |
|
15 - 0 |
resultFifo |
Rx |
Payload from the result FIFO. |
||
0x014 |
31 - 0 |
commandFifo |
xW |
|
|
0x018 |
31 - 24 |
occupancy |
Rx |
Number of occupied slots in the result FIFO. |
|
23 - 16 |
vacancy |
Rx |
Number of empty slots in the command FIFO. |
Clock Divider and Read Delay:
Address |
Bit |
Field |
Default |
Permission |
Description |
---|---|---|---|---|---|
0x01C |
clockDividerWidth - 0 |
clockDividerValue |
Depends on PioCtrl.InitParameter |
RW or Rx |
Value for the clock divider counter to divide down the input clock. |
0x020 |
readDelayWidth - 0 |
ReadDelayValue |
Depends on PioCtrl.InitParameter |
RW or Rx |
Number of cycles to delay during the read action. |