GPIO Chip

This design combines many common I/O peripherals into a single layout and interfaces to the outside world using an 8-bit bus interface compatible with many old 8-bit and 16-bit microprocessors. It contains 16 individually programmable GPIO lines, 3 timer/counters, 3 DACs, a PRNG, one UART, one SPI port and 16 bytes of general-purpose registers.

Pad Assignments

Table 15 Pad description

Pad

Name

Type

Summary

bidir[0]

INTn

O

Interrupt output, active low

bidir[1]

SDI

I

SPI Serial Data In

bidir[2]

RSTm

I

Active-low design reset

bidir[3]

SDO

O

SPI Serial Data Out

bidir[4]

SCLK

O

SPI Serial Clock Out

bidir[5]

T0

O

Timer 0 toggle output

bidir[6]

T1

O

Timer 1 toggle output

bidir[12:7]

A[5:0]

I

Bus address inputs

bidir[20:13]

D[7:0]

IO

Bidirectional bus data lines

bidir[21]

CEn

I (PU)

Bus Chip Enable input

bidir[22]

OEn

I

Bus Output Enable input

bidir[23]

WEn

I

Bus Write Enable input

bidir[24]

PA[0]/T0CLK/CTSn

IO

PORTA bit 0 or Timer 0 external clock or UART Clear To Send output

bidir[25]

PA[1]/T1CLK

IO

PORTA bit 1 or Timer 1 external clock

bidir[31:26]

PA[7:2]

IO

PORTA GPIO port

bidir[39:32]

PB[7:0]

IO

PORTB GPIO port

bidir[40]

RXD

I (PU)

UART Receive Data input

bidir[41]

TXD

O

UART Transmit Data output

analog[0]

DAC[0]

O

Digital To Analog Converter output

analog[5]

DAC[1]

O

Digital To Analog Converter output

analog[10]

DAC[2]

O

Digital To Analog Converter output

Bus Interface

The design’s internal registers are addressed using a 8-bit data bus with data lines on the D[7:0] pads, register address provided on the A[5:0] pads and controlled by the CEn, OEn and WEn inputs. Any register read or write cycle requires CEn to be low in addition to either OEn or WEn being low. OEn takes precedence over WEn, but the condition of all three inputs being low simultaneously should generally be avoided. OEn being low indicates a read access, with the value of the addressed register being presented on the D[7:0] lines, which become outputs during this time. WEn being low indicates a write access, with a value presented on the D[7:0] lines being written into the addressed register, if the register in question is writeable. For read-only registers, WEn simply has no effect.

All three control lines are synchronous to the clock. WEn takes effect on every rising clock edge where it and CEn are low and OEn is high. When OEn goes low, the D[7:0] become outputs immediately, outputing the value of the addressed register, but if the addressed register triggers a side effect when read (i.e. UDAT), this only triggers on the next rising clock edge after OEn and CEn going low.

Register Descriptions

All registers are listed by address and mnemonic.

GPIO Port

Two 8-bit GPIO ports are provided through these registers, with pin direction and pull resistors individually programmable. Every bit of these registers is mapped to the corresponding bit on the PA/PB pads. DDRx controls pin direction, with logic ones indicating outputs and logic zeroes indicating inputs. The PORTx registers control the states of any outputs, with logic ones indicating a high output state and logic zeroes indicating a low output state. For pins configured as inputs, the input levels can be sampled by reading the PINx registers, where high level inputs generate logic ones and low level inputs generate logic zeroes.

Inputs can additionally be configured to have an internal pull-up or pull-down resistor with the PUx and PDx registers. PUx enables pull-ups while PDx enables pull-downs. Setting bits in either register for port bits configured as outputs has no effect.

'h00 - DDRA

'h01 - DDRB

'h02 - PORTA

'h03 - PORTB

'h04 - PINA - Read Only

'h05 - PINB - Read Only

'h2B - PUA

'h2C - PUB

'h2D - PDA

'h2E - PDB

Serial Ports

Two serial ports, one SPI master port and one UART, are provided through these registers. Both have individually programmable bitrates, generated by dividing the input clock. SDIV contains the divider value for the SPI port and UDIV the divider value for the UART. The final bitrate for either is then clock / (UDIV/SDIV + 1).

Both ports have a data register, SDAT for the SPI port and UDAT for the UART, which immediately initiate a data transfer when written to. In the case of the SPI port, a full-duplex data exchange takes place, with the received byte obtainable by reading SDAT once the transfer is complete. The UART will asynchronously receive bytes, which can then be obtained by reading UDAT.

The SSTAT register provides status information and configuration options for the serial ports. The bits SBUSY, for the SPI port, and UBUSY, for the UART, indicate if the corresponding serial port is still busy transmitting the last value written to its data register. No further data register writes may take place for a serial port if its corresponding busy bit is set. The UART additionally provides the UHB status bit which reads one if it has completed receiving a new byte and this data is now available in UDAT. Reading UDAT then also clears UHB. Buffer overruns are not detected.

The UART is capable of generating an interrupt whenever it has received a byte, which can be enabled by setting the UIEN bit in SSTAT. Basic flow control can also be enabled by setting FLOWEN. PORTA bit zero, corresponding to the PA[0] pad, must additionally be an output pin to use this feature. Setting FLOWEN overrides the output value setting of this pad with the CTSn flow control line. This line goes high whenever UHB is set and only goes low when UHB becomes low again. This indicates to the other end of the connection that no further bytes can be received by the UART until UDAT is read.

'h06 - SDIV

'h07 - SDAT

'h08 - UDIV (LSB)

'h09 - UDIV (MSB)

'h0A - UDAT

'h0B - SSTAT - Only marked bits are writeable

Timer/Counters

Three timer/counters provide precise general-purpose or interrupt timing based on the system clock, or an external clock, or can count pulses from an external source. All timers are 16-bits wide with a 16-bit prescaler and a 16-bit compare unit. Reading and writing these 16-bit registers through the 8-bit databus must follow a specific pattern. All put the TMRx registers can have their LSB and MSB read in any order. To read the timer values, a write to the TCAPT register will instantly copy all timer values from TMRx to the corresponding CAPx registers, which may then be read in any order. Writing any 16-bit register must be done LSB first. When writing to the LSB of one of these registers, the value is not directly written, but instead cached in a hidden temporary register. When the write to the MSB is done, the value presented on the bus and that in the temporary register are combined to form a full 16-bit value, which is then instantaneously written to the target register.

Each timer functions the same: it counts up from zero until reaching the value programmed in TTOPx, at which point it resets to zero, optionally generating an interrupt or toggling an output pin. The rate at which each timer counts up can be set in multiple ways and if the TPREx registers have been programmed with non-zero values, the count rate is additionally divided by TPREx + 1. The simplest and default method is counting up at the rate of the design input clock, divided by TPREx + 1. However, timers TMR0 and TMR1 may also receive a count rate from an external source, which can be selected by setting TxEXT in TOPT. Once enabled, the clock source of the affected timer switches to its corresponding TxCLK input pad. As T0CLK and T1CLK are shared with PA[0] and PA[1], the corresponding PORTA bits must be set to inputs. They can then still be read normally through PINA on top of functioning as TxCLK and a pull-up or pull-down may still be enabled for either pad. The design will then detect positive going edges on TxCLK and the corresponding timer/counter will increment every TPREx + 1 such edges.

Setting TMRIEx bits in TOPT enables the generation of timer interrupts for the corresponding timer/counter. Every time a interrupt-enabled timer reaches TTOPx and resets to zero, its TxIRQ bit is set and an interrupt is generated. These interrupts must be cleared by writing to the TIRQS register. Every logic one in the written value resets the corresponding TxIRQ bit, clearing the interrupt. Reading TIRQS reveals which timers currently have their TxIRQ bit set. If a TMRIEx bit is cleared while the corresponding TxIRQ bit is set, the TxIRQ bit also clears.

'h0C - TOPT

'h0D - TIRQS

'h0E - TCAPT - Write Only

Writing this register instantaneously captures all current TMRx values into the corresponding CAPx registers.

'h0F - T0PRE (LSB)

'h10 - T0PRE (MSB)

'h11 - T1PRE (LSB)

'h12 - T1PRE (MSB)

'h13 - T2PRE (LSB)

'h14 - T2PRE (MSB)

'h15 - T0TOP (LSB)

'h16 - T0TOP (MSB)

'h17 - T1TOP (LSB)

'h18 - T1TOP (MSB)

'h19 - T2TOP (LSB)

'h1A - T2TOP (MSB)

'h1B - TMR0 (write) / CAP0 (read) (LSB)

'h1C - TMR0 (write) / CAP0 (read) (MSB)

'h1D - TMR1 (write) / CAP1 (read) (LSB)

'h1E - TMR1 (write) / CAP1 (read) (MSB)

'h1F - TMR2 (write) / CAP2 (read) (LSB)

'h20 - TMR2 (write) / CAP2 (read) (MSB)

Digital To Analog Converters

Three DACs provide analog output capabilities. Each DAC is 12-bits wide, with a change of a DAC’s register value corresponding to a proportional voltage change on its analog output pin. A value of zero produces a voltage close to 0V while the maximum value of 'hFFF produces a voltage close to the supply voltage¹. Values in-between these two extremes produce voltages on a linear slope between 0V and the supply voltage. Each DAC is typically capable of driving a 1Kohm load.

¹Proper functioning of the DACs is not guranteed at supply voltages not equal to 5V +/- 10% as all passive circuit components were tuned for 5V operation.

'h21 - DAC0 (MSB)

'h22 - DAC0 (LSB)

'h23 - DAC1 (MSB)

'h24 - DAC1 (LSB)

'h25 - DAC2 (MSB)

'h26 - DAC2 (LSB)

PRNG

A Xorshift-based PRNG provides random values that update on every clock cycle. 24 of the PRNG state’s 32-bits are left uninitialized on reset, meaning they start with a truly random state from the register bit flip-flops settling into random states on power-up, providing a different random number sequence each time. The whole 32-bit state of the PRNG is accessible, though it is not capturable in whole like is the case with the timer values.

'h27 - PRNG

'h28 - PRNG

'h29 - PRNG

'h2A - PRNG

General-Purpose Registers

16 addresses in the range 'h30 through 'h3F (inclusive) map to registers which are readable and writeable, but are not mapped to any hardware function. This essentially turns them into 16 bytes of general-purpose random-access memory that can be used arbitrarily for data storage by the host system.

Interrupts

Interrupts are provided by the INTn output pin. This pin transitions low as soon as any enabled interrupt source becomes active and stays low until the number of active interrupt sources has reached zero after each source has been cleared or reset. All three timers as well as the UART serial port can generate interrupts, as described in their own sections above.