TS-4100 FPGA Sections
FPGA Registers
The TS-4100 FPGA provides additional DIO (that are connected to a Crossbar MUX), some miscellaneous system peripherals, and the 32-bit ZPU microcontroller. The FPGA is a Lattice MachXO2.
See the GPIO section for information on accessing the FPGA DIO.
The FPGA registers are accessed via an I2C bus. The FPGA emulates an I2C EEPROM, allowing for a simple and standard communication protocol to the FPGA. The FPGA is available at I2C addresses 0x28-0x2F. Accessing individual registers requires a chip address write, a 16-bit register address write, then 8-bit data values. A read or write stream can occur; every every byte read or written the internal register pointer moves to the next sequential register. This allows for reading or writing multiple registers without having to re-issue the chip and register address sequence.
We provide a simple access mechanism to the FPGA using the tshwctl
utility. This utility can read or write arbitrary registers, return some information about the FPGA, as well as configure the Crossbar MUX. Sources for tshwctl
and other utilities specific to the TS-4100 can be found in the TS-4100 utilities github repository.
The register map is broken in to a few different sections:
Section | Address | Bits | Description |
---|---|---|---|
GPIOn | 0x0000-0x007F | 7:3 | Reserved (Write 0) |
2 | GPIOn Input Data | ||
1 | GPIOn Output Data | ||
0 | GPIOn Output Enable | ||
CROSSBARn | 0x0080-0x00FF | 7 | CROSSBARn GPIO mode |
6:0 | CROSSBARn Value | ||
BANKn | 0x0100-0x010F | 7:0 | GPIOn Bank Input |
0x0110-0x011F | 7:0 | GPIOn Bank Output Data | |
0x0120-0x012F | 7:0 | GPIOn Bank Output Enable | |
Misc | 0x0130 | 7:0 | Model Number MSB (0x41) |
0x0131 | 7:0 | Model Number LSB (0x00) | |
0x0132 | 7:0 | FPGA Rev | |
0x0133-0x1FFF | 7:0 | Reserved | |
ZPU | 0x1FFF-0x2FFF | 7:0 | ZPU RAM access |
GPIOn
Registers 0x00-0x7F provide DIO control. The GPIO can be manipulated via the sysfs GPIO interface, information on this can be found in the GPIO section which is the recommended way to manipulate these pins. Each register in this section manipulates a different DIO pin. See the "FPGA I/O" table below for the register offset for this section. For example, to set "DIO_1" to a low output, the value 0x1 would be written to FPGA register 0x26 (the I/O number of "DIO_1").
Note: | The sysfs GPIO interface is recommended because it guarantees a clean state transition. When setting a GPIOn register, modifying multiple bits simultaneously creates a race condition between the output and output enable bits. This may result in a short glitch on the pin as it transitions. The sysfs GPIO driver will only manipulate a single bit at a time resulting in a clean and guaranteed transition. |
CROSSBARn
Registers 0x80-0xFF provide control for the Crossbar MUX. Like GPIOn above, each register represents a single DIO pin which are listed in the "FPGA I/O" table below. In order to change the MUX setting of any individual pin, its corresponding register is written to. For example, to set "UARTA_TXD" to output the data from "UART2_TXD", write the value of 0x5 (the I/O number of "UART2_TXD") to register (0x80+0x21) = 0xA1 (the I/O number of "UARTA_TXD" plus the CROSSBARn section starting register). The 'tshwctl' utility provides an easy abstraction for this process. See the Crossbar MUX section for more information on this process as well as a breakdown of Crossbar assignments.
BANKn
Registers 0x100-0x12F provide banked DIO access. The banked DIO allows for manipulating multiple pins simultaneously. Each bank register has 8 bits that represent 8 DIO pins. There are 48 bank registers total, 16 for GPIO input, 16 for GPIO output, and 16 for GPIO output enable. The bank and bit position of any given DIO listed in the "FPGA I/O" table below can be calculated by dividing the I/O number by 8 to get the bank number and then taking the modulus of that same calculation to get the bit position. The BANKn registers are not intended for normal use and exist to allow the ZPU to readily manipulate GPIO pins.
Misc
Registers 0x130-0x132 provide the model number and FPGA software revision. Registers 0x133-0x1FFF are reserved.
ZPU
Registers 0x2000-0x3FFF are RAM intended for use by the ZPU. Normally unused unless the ZPU is loaded and run, these registers can be used for volatile storage if wanted.
I/O Number | Signal name | Direction |
---|---|---|
0x01 | SPARE_1 | I/O |
0x02 | SPARE_2 | I/O |
0x03 | SPARE_3 | I/O |
0x04 | SPARE_4 | I/O |
0x05 | UART2_TXD | Input |
0x06 | UART2_CTS# | Input |
0x07 | UART3_TXD | Input |
0x08 | UART6_TXD | Input |
0x09 | UART2_RXD | Output |
0x0A | UART2_RTS# | Output |
0x0B | UART3_RXD | Output |
0x0C | UART6_RXD | Output |
0x0D | WIFI_RXD | Input |
0x0E | WIFI_RTS | Input |
0x0F | WIFI_IRQ# | Input |
0x10 | WIFI_TXD | Output |
0x11 | WIFI_CTS | Output |
0x12 | ZPU_BREAK | Input |
0x13 | ZPU_RESET | Output |
0x14 | EN_WIFI_PWR | Output |
0x15 | WIFI_RESET# | Output |
0x16 | EN_USB_HOST_5V | Output |
0x17 | EN_LCD_3V3 | Output |
0x18 | ETH_PHY_RESET# | Output |
0x19 | OFF_BD_RESET# | Output |
0x1B | GREEN_LED# | Output |
0x1C | RED_LED# | Output |
0x1D | UARTA_RXD | I/O |
0x1E | UARTB_RXD | I/O |
0x1F | UARTC_RXD | I/O |
0x20 | UARTD_RXD | I/O |
0x21 | UARTA_TXD | I/O |
0x22 | UARTB_TXD | I/O |
0x23 | UARTC_TXD | I/O |
0x24 | UARTD_TXD | I/O |
0x25 | DIO_0 | I/O |
0x26 | DIO_1 | I/O |
0x27 | DIO_2 | I/O |
0x28 | DIO_3[1] | I/O |
0x29 | DIO_4 | I/O |
0x2A | DIO_5 | I/O |
0x2B | DIO_6 | I/O |
0x2C | DIO_7 | I/O |
0x2D | DIO_8 | I/O |
0x2E | DIO_9 | I/O |
0x31 | DIO_12 | I/O |
0x32 | DIO_13 | I/O |
0x33 | DIO_14 | I/O |
0x34 | DIO_15 | I/O |
0x35 | DIO_16 | I/O |
0x36 | DIO_17 | I/O |
0x37 | DIO_18 | I/O |
0x38 | DIO_19 | I/O |
0x39 | DIO_20 | I/O |
0x3A | DIO_21 | I/O |
0x3B | DIO_22 | I/O |
0x3C | DIO_23 | I/O |
0x3D | DIO_24 | I/O |
0x3E | DIO_25 | I/O |
0x3F | DIO_26 | I/O |
0x40 | DIO_27 | I/O |
0x41 | DIO_28 | I/O |
0x42 | DIO_29 | I/O |
0x43 | DIO_30 | I/O |
0x44 | DIO_31 | I/O |
0x45 | DIO_32 | I/O |
0x46 | DIO_33 | I/O |
0x47 | DIO_34 | I/O |
0x48 | DIO_35 | I/O |
0x49 | DIO_36 | I/O |
0x4A | DIO_37 | I/O |
0x4B | DIO_38 | I/O |
0x4C | DIO_39 | I/O |
0x4E | DIO_41 | I/O |
0x4F | DIO_42 | I/O |
0x50 | DIO_43 | I/O |
0x51 | DIO_44 | I/O |
0x52 | DIO_45 | I/O |
0x53 | DIO_46 | I/O |
DIO_3 Clock Override
DIO_3 has special modes that override the normal output and places a clock frequency on it. This is required for compatibility with certain TS-8XXX baseboards with MUXBUS functionality. See the ZPU section for more information on MUXBUS and TS-8XXX baseboards. The override consists of two registers, and only the Output Data bits in each register.
0x57:0x58 OD bit | DIO_3 output |
---|---|
b00 | DIO_3 |
b01 | 14.3 MHz clock |
b10 | 12.5 MHz clock |
b11 | 12.5 MHz clock |
- ↑ For compatibility with various TS-8XXX baseboards, this pin has a special mode that allows it to output a clock. See I/O register 0x57 and 0x58.
Crossbar
The TS-4100 implements a limited crossbar MUX. This allows functional reassignment of pins to serve other purposes. For example, it is possible to connect different UARTs to different locations which can be used to repurpose otherwise unused UART ports. Additionally it can be used to connect a passthrough from a CPU GPIO to a pin that is only otherwise available from the FPGA.
Due to space constraints of the FPGA, there is a limitation of how pins can be assigned. The "Crossbar Assignable" column of the FPGA I/O table below lists the type of input assignment a pin will accept. The table also lists the default assignment of every pin.
- All FPGA I/O pins listed in the table can have their input assigned as "GPIO". Note that even with an input assignment of "GPIO", some pins are still limited to being an input or output only GPIO. Pins assigned to an input of "GPIO" are controlled by the standard GPIO interface and numbered according to the FPGA GPIO table. Also note that if an invalid assignment is given to a pin, it will default back to the "GPIO" assignment.
- An input of "GPIO" means that the logical input to the switching block comes directly from its associated pin. For example, the "UART2_TXD" signal is set to "GPIO" as its input. This means that the input to this switchable signal comes from the pin, which is connected to the CPU UART2_TXD signal. The "WIFI_TXD" signal has its input set to "UART2_TXD", with the "WIFI_TXD" physical pin connecting directly to the UART input of the Wi-Fi/BT module. This full path connects the CPU UART output, to the FPGA pin, to the "UART2_TXD" switching block, to the "WIFI_TXD" output pin, to the UART RX on the Wi-Fi/BT module.
- No matter which FPGA I/O is assigned, the output signal must have its data direction set to out and the input signal must have its data direction set to in. Without these set properly the physical pins themselves will be unable to properly MUX signals.
- The FPGA I/O pins compatible with an "Any" input assignment can be assigned any other pin in the table as an input.
- The FPGA I/O pins compatible with "Input only" assignment can only be assigned "GPIO" as an input. They can, however, be used as inputs in to other pins that are able to accept it as an input. Attempting to set this pin to any other input assignment will result it in automatically reverting to "GPIO".
- The FPGA I/O pins compatible with "UART only" assignments can only be assigned I/O numbers 0x01 through 0x08 inclusive. Attempting to assign any other input will automatically set the pin to "GPIO".
I/O Number | Signal name | Crossbar Assignable | Default Input Assignment |
---|---|---|---|
0x01 | SPARE_1 | Any | GPIO |
0x02 | SPARE_2 | Any | GPIO |
0x03 | SPARE_3 | Any | GPIO[1] |
0x04 | SPARE_4 | Any | WIFI_IRQ |
0x05 | UART2_TXD | Input only | GPIO |
0x06 | UART2_CTS# | Input only | GPIO |
0x07 | UART3_TXD | Input only | GPIO |
0x08 | UART6_TXD | Input only | GPIO |
0x09 | UART2_RXD | Any | WIFI_RXD |
0x0A | UART2_RTS# | Any | WIFI_RTS |
0x0B | UART3_RXD | Any | UARTA_RXD |
0x0C | UART6_RXD | Any | UARTB_RXD |
0x0D | WIFI_RXD | Input only | GPIO |
0x0E | WIFI_RTS | Input only | GPIO |
0x0F | WIFI_IRQ# | Input only | GPIO |
0x10 | WIFI_TXD | UART only | UART2_TXD |
0x11 | WIFI_CTS | UART only | UART2_RTS |
0x12 | ZPU_BREAK | Input only | GPIO |
0x13 | ZPU_RESET | Input only | GPIO |
0x14 | EN_WIFI_PWR | Input only | GPIO |
0x15 | WIFI_RESET# | Input only | GPIO |
0x16 | EN_USB_HOST_5V | Input only | GPIO |
0x17 | EN_LCD_3V3 | Input only | GPIO |
0x18 | ETH_PHY_RESET# | Input only | SPARE_3 |
0x19 | OFF_BD_RESET# | Input only | GPIO |
0x1B | GREEN_LED# | Input only | GPIO |
0x1C | RED_LED# | Input only | GPIO |
0x1D | UARTA_RXD | UART only | GPIO |
0x1E | UARTB_RXD | UART only | GPIO |
0x1F | UARTC_RXD | UART only | GPIO |
0x20 | UARTD_RXD | UART only | GPIO |
0x21 | UARTA_TXD | UART only | UART3_TXD |
0x22 | UARTB_TXD | UART only | UART6_TXD |
0x23 | UARTC_TXD | UART only | GPIO |
0x24 | UARTD_TXD | UART only | GPIO |
0x25 | DIO_0 | UART only | GPIO |
0x26 | DIO_1 | UART only | GPIO |
0x27 | DIO_2 | UART only | GPIO |
0x28 | DIO_3 | UART only | GPIO |
0x29 | DIO_4 | UART only | GPIO |
0x2A | DIO_5 | UART only | GPIO |
0x2B | DIO_6 | UART only | GPIO |
0x2C | DIO_7 | UART only | GPIO |
0x2D | DIO_8 | UART only | GPIO |
0x2E | DIO_9 | UART only | GPIO |
0x31 | DIO_12 | UART only | GPIO |
0x32 | DIO_13 | UART only | GPIO |
0x33 | DIO_14 | UART only | GPIO |
0x34 | DIO_15 | UART only | GPIO |
0x35 | DIO_16 | UART only | GPIO |
0x36 | DIO_17 | UART only | GPIO |
0x37 | DIO_18 | UART only | GPIO |
0x38 | DIO_19 | UART only | GPIO |
0x39 | DIO_20 | UART only | GPIO |
0x3A | DIO_21 | UART only | GPIO |
0x3B | DIO_22 | UART only | GPIO |
0x3C | DIO_23 | UART only | GPIO |
0x3D | DIO_24 | UART only | GPIO |
0x3E | DIO_25 | UART only | GPIO |
0x3F | DIO_26 | UART only | GPIO |
0x40 | DIO_27 | UART only | GPIO |
0x41 | DIO_28 | UART only | GPIO |
0x42 | DIO_29 | UART only | GPIO |
0x43 | DIO_30 | UART only | GPIO |
0x44 | DIO_31 | UART only | GPIO |
0x45 | DIO_32 | UART only | GPIO |
0x46 | DIO_33 | UART only | GPIO |
0x47 | DIO_34 | UART only | GPIO |
0x48 | DIO_35 | UART only | GPIO |
0x49 | DIO_36 | UART only | GPIO |
0x4A | DIO_37 | UART only | GPIO |
0x4B | DIO_38 | UART only | GPIO |
0x4C | DIO_39 | UART only | GPIO |
0x4E | DIO_41 | UART only | GPIO |
0x4F | DIO_42 | UART only | GPIO |
0x50 | DIO_43 | UART only | GPIO |
0x51 | DIO_44 | UART only | GPIO |
0x52 | DIO_45 | UART only | GPIO |
0x53 | DIO_46 | UART only | GPIO |
- ↑ While assigned to GPIO by default, this is used as an input to ETH_PHY_RESET#
Modify Crossbar Assignments
All of the crossbar assignments are managed through the FPGA syscon registers, in the bank of registers labeled as "CROSSBARn". However, this can more easily be managed through the 'tshwctl' utility. The 'tshwctl' utility provides a pair of flags that make it quick to assign an input to an FPGA I/O. For example, normally UART 2 is set up to connect to the on-board Bluetooth module. However, if a model of TS-4100 does not have this module present, or it is not needed in a particular application, it can be assigned to another unused set of UART pins on the TS-SOCKET interface, like UARTC:
tshwctl --out 0x9 --in 0x1f # Set UART2_RXD's input assignment to be UARTC_RXD. The UART2_RXD signal in the FPGA is connected directly to UART2_RXD on the CPU.
tshwctl --out 0x23 --in 0x5 # Set UARTC_TXD's input assignment to be UART2_TXD. The UART2_TXD signal in the FPGA is connected directly to UART2_TXD on the CPU.
tshwctl --out 0x10 --in 0x80 # Set WIFI_TXD's input assignment to GPIO. This prevents UART2_TXD data from appearing on this pin when unwanted.
tshwctl --out 0x11 --in 0x80 # Set WIFI_CTS's input assignment to GPIO. This prevents UART2_RTS data from appearing on this pin when unwanted.
Note: | Using 'tshwctl' to set crossbar assignments also sets the the GPIO direction. The I/O number passed as --out is set to a low output, and the I/O number passed as --in is set to an input. |
The latest sources for 'tshwctl' and other utilities can be found in the TS-4100 utilities github repository.