Several peripherals are built into this microcontroller.
- in means that the bit represents an input.
- out means that the bit represents an output. (Reads might represent the external value, see the access code).
- i/o od means that the bit represents an I/O pin that is open drain.
- rw means a normal read/write bit.
- rwc means that the bit can be read and written, but that writes have a special control function -- consult the description.
- ro means that the bit is read-only; write values are ignored.
- r0wi means that the bit reads as zero, and write values are ignored. (This is a special case of ro.)
- r1wi means that the bit reads as one, and write values are ignored.
- rw1c means that the bit has a value that is set by hardware. Writes with this bit zero have no effect; writes with this bit set clear the bit.
- rpwd means that the bit reads the value from the pin, and writes a data value to a register. Normally this means that the output is controlled by the written value, but the read-back depends on what is happening externally to the FPGA. For example, an open-drain wire-ORed output might read back zero even after the register has been written to 1, because some other device on the wire is still driving the wire to zero.
Address | Bytes | Name | Description |
---|---|---|---|
0x80000000 | 16 | UART0 |
Simple UART instance 0 |
0x80000010 | 16 | UART1 |
Simple UART instance 1 |
0x80000020 | 16 | I2C |
Simple I2C interface |
0x80000030 | 16 | GPIO |
GPIO Interface |
0x80000040 | 16 | SPI |
Simple SPI interface |
0x80000050 | 16 | CYCLES |
Cycle counter |
Each UART interface operates at a fixed baud rate set in the Verilog code -- check the top-level for your design. Typically this is 230,400 baud.
As is traditional, data bytes are read and written from a UART_DATA
register; control-plane information is accessed via a UART_CSR
register.
The transmit path has a write FIFO (16 bytes deep in the default implementation, but again, check your design to be sure). Software typically writes until the FIFO is full, then waits for the FIFO to drain, polling bits in the UART CSR.
The receive path has no FIFO at all in the current design, but the character buffer is separate from the shift register. It's up to software to keep up, but software has roughly 9 bit times to consume the character before it can be overwritten.
The current microcontroller's implementation is not great about disambiguating reads -- it simply copies whatever appears at the ALU output to the read register, without generating a strobe for the LD instruction. Rather than fix the core, we currently require software to explicitly acknowledge each byte read.
Base address:
- UART0: 0x80000000.
- UART1: 0x80000010.
Offset | Width | Name | Description |
---|---|---|---|
0x0 | 32 | DATA |
Data to/from the UART |
0x4 | 32 | CSR |
Control/status register |
0x8 | 32 | reserved | Not implemented |
0xC | 32 | reserved | Not implemented |
Bit | 31 .. 8 | 7 .. 0 |
---|---|---|
Name | reserved | FIFO |
Reset | 0 | 0 |
Access | r0wi | rwc |
Bit | 31 .. 8 | 7 | 6 .. 2 | 1 | 0 |
---|---|---|---|---|---|
Name | reserved | RXD |
reserved | RXRDY |
TXFULL |
Reset | 0 | 0 | 0 | 0 | 0 |
Access | r0wi | ro | r0wi | rw1c | ro |
The RXRDY
bit has two functions.
- When read, it is 1 if there is valid receive data in the
DATA.FIFO
register. - When written, if this bit is set, it acknowledges the previous character, clearing the
RXRDY
bit until a new character arrives.
The TXFULL
bit is set by hardware whenever the transmit FIFO is full. It is cleared whenever the FIFO drops below full. (Yes, it would be nice to have empty and 50% status bits.)
RXD
represents the current state of the UART's receive pin. On UART0, for the LoRaWAN face-detect demo, it's connected to FACE
, the "face present" signal (1 == face present), a non-inverting input.
The I2C implementation is completely software driven; but it has a dedicated GPIO register to make programming easier and faster.
Two pins, I2C_SCL and I2C_SDA, are controlled by this interface. Both are open-drain signals -- in other words, they alternate between high-impedance (no drive at all), and driving actively to ground. Each pin is in the high-impedance (or "Z") state when the corresponding register bit is set to 1. A pin is in the low-impedance to ground (or "L") state when the corresponding register bit is set to 0.
Base address: 0x80000020.
Offset | Width | Name | Description |
---|---|---|---|
0x0 | 32 | DATA |
Data to/from the pins registers |
0x4 | 32 | reserved | not implemented |
0x8 | 32 | reserved | Not implemented |
0xC | 32 | reserved | Not implemented |
| Bit | 31 .. 2 | 1 | 0 |
|:----------:|:--------:|:-:|:-:|:-:|
| Name | reserved | SDA
| SCL
|
| Reset | 0 | 1 | 1 |
| Type | n/a | i/o od | i/o od |
| Access | r0wi | rpwd | rpwd |
Software is responsible for bit-banging the interface and for implementing the I2C protocol.
Note that the value read back is the current value at the pin of the device, not the last value written to the register.
The GPIOs are architected as classic software-configured GPIOs. They are programmable for input/output direction and (if output) for totem-pole vs open-drain drive. However, in this implementation we remove the programmability; so they're fixed function.
Base address: 0x80000030.
Offset | Width | Name | Description |
---|---|---|---|
0x0 | 32 | DATA |
Data to/from the GPIO registers |
0x4 | 32 | reserved | not implemented |
0x8 | 32 | reserved | Not implemented |
0xC | 32 | reserved | Not implemented |
Bit | 31 .. 6 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Name | reserved | GPIO6 |
GPIO5 |
GPIO4 |
GPIO3 |
GPIO2 |
GPIO1 |
GPIO0 |
Reset | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
Type | n/a | in | in | in | in | in | i/o od | out |
Access | r0wi | ro | ro | ro | ro | ro | rpwd | rpwd |
The GPIO bits are intended to be used as follows:
Bit name | LoRaWAN radio signal | Comments |
---|---|---|
GPIO0 |
CS |
chip select output to radio. |
GPIO1 |
NRST |
reset output to radio. open drain output, active low, set to 1 by reset. |
GPIO2 |
DIO1 |
DIO1 output of radio, non-inverting input. |
GPIO3 |
IRQ |
Interrupt request from radio, non-inverting input. |
GPIO4 |
DIO2 |
DIO2 output of radio, non-invering input. |
GPIO5 |
SPARE4 |
Spare non-inverting input, connected to screw terminal JP3-1 on the LoRaWAN radio board. |
GPIO6 |
SPARE5 |
Spare non-inverting input, connected to screw terminal JP3-2 on the LoRaWAN radio board. |
Due to pin and board-design limitations, GPIO5
and GPIO6
are not available on the MDP implementation of this design, and will always read as zero. Instead, UART0 TX and RX are connected to SPARE_C4
and SPARE_C5
, repectively.
The SPI implementation is completely software driven; but it has a dedicated GPIO register to make programming easier and faster.
Base address: 0x80000040.
Offset | Width | Name | Description |
---|---|---|---|
0x0 | 32 | DATA |
Data to/from the pins registers |
0x4 | 32 | reserved | not implemented |
0x8 | 32 | reserved | Not implemented |
0xC | 32 | reserved | Not implemented |
Bit | 31 .. 3 | 2 | 1 | 0 |
---|---|---|---|---|
Name | reserved | SCK |
MOSI |
MISO |
Reset | 0 | 0 | 0 | 0 |
Type | n/a | out | out | in |
Access | r0wi | rpwd | rpwd | ro |
SCK and MOSI are the classic SPI outputs (to the LoRaWAN radio, in this case). MISO is the classic SPI input. Software is responsible for bit-banging the interface. Software is also responsible for asserting CS
(via the GPIO interface) before a SPI access to the radio, and clearing it afterwards.
A free-running 32-bit counter is provided. It is incremented on every CPU clock cycle. Software can change the value by writing to the data register.
Offset | Width | Name | Description |
---|---|---|---|
0x0 | 32 | DATA |
Counter Data |
0x4 | 32 | reserved | Not implemented |
0x8 | 32 | reserved | Not implemented |
0xC | 32 | reserved | Not implemented |
Bit | 31 .. 0 |
---|---|
Name | COUNT |
Reset | 0 |
Access | rw |
This register is incremented by hardware on every CPU clock cycle. Software may change the value by writing to this register; but note that it will never read back exactly what it wrote, because the value is constantly incrementing.