
MSP430 Playground for ULX3S
---------------------

This project contains an interactive "microcontroller" with MSP430 instruction set, based on the FemtoMSP430, which is an original softcore processor design, released here for the first time.

Features and peripherals included:

  - VGA 800x600 textmode with 7-Bit ASCII 8x16 font
  - Random number generator using a ring oscillator defined in logic
  - GPIO registers for PMOD pin access
  - LEDs and buttons
  - UART terminal, 115200 Baud 8N1
  - USB-CDC terminal

Notes on the FemtoMSP430
---------------------  
  
The FemtoMSP430 is a softcore processor executing MSP430 instructions, but with a bus interface similar to the FemtoRV32 processor family, accepting memory busy signaling. Therefore, the FemtoMSP430 is not cycle accurate, but can be combined with peripherals known from other RISC-V designs which are a uncommon pairing with a MSP430 style processor, like driving graphics output.

The main reason for this strange chimera to exist is to enjoy the instruction set in a "phantasy machine", just for fun, doing experiments with MSP430 code in an interactive setup.

Note the FemtoMSP430 supports all MSP430 instructions, but currently offers one interrupt request wire only, and does not really save power when the CPUOFF flag is active :-)

If you came here for either a tiny processor core or performance, absolutely go for the RISC-V based FemtoRV32 cores that offer much better performance using less LUTs. If you want a really well-tested MSP430 clone with the original peripherals, check out OpenMSP430 by Olivier Girard. But if you just want to have fun with the classic instruction set architecture and a fresh take of its implementation, feel welcome.

Memory map and IO
---------------------

As we have no shortage of available memory in the ULX3S, the complete memory map from 0x0000 to 0xFFFF contains 64 kb of initialised RAM, with these specially handled overlays on top:

```
* 0x0000 - 0x00FF: 256 bytes of peripheral IO registers, byte-access only
* 0x0100 - 0x01FF: 256 bytes of peripheral IO registers, word-access only

* 0x6000 - 0x6FFF: 4096 bytes character buffer, 100x37=3700 chars visible, byte access only
* 0x7000 - 0x77FF: 2048 bytes font data, 128 characters, 16 bytes per character, byte access only
```

For using the display, all you have is to write characters into the 3700 bytes starting at 0x6000. The initialised font (starting at 0x7200) contains 96 glyphs (32 to 127), taken from FreeBSD "iso-8x16" bitmap font. The MSB (0x80) selects a "highlight" color.

The first 32 glyphs for ASCII 0 to 31 starting from 0x7000 can be freely used for custom characters.

Both character and font data areas can be read and written using byte access only.

Unlike the memory map of the real MSP430G2755, the RAM memory area between 0x1100-0x20FF is not partially mirrored to 0x0200-0x09FF, but a separate part of RAM memory. Also the initialisation of the memory map as-is does neither contain the info flash calibration constants nor the bootstrap loader BSL ROM.

Peripheral registers
---------------------

The peripheral register set is mostly unique here, but with enough support to run the original Mecrisp Forth for MSP430G2755 unchanged.


```
Implemented "classic" registers with their respective contents:

Word access

* 0x0120: RW  WDTCTL     Resets the processor on writes when violating the watchdog key 0x5Axx

Byte access

* 0x0003: RW  IFG2       [4] USB configured [3] USB TX ready [2] USB RX valid [1] UART TX ready [0] UART RX valid

* 0x0066: RO  UCA0RXBUF  Read character from  UART receive FIFO
* 0x0067: WO  UCA0TXBUF  Send character using UART

* 0x006E: RO  UCB0RXBUF  Read character from  USB-CDC
* 0x006F: WO  UCB0TXBUF  Send character using USB-CDC

* 0x0020: RO  P1IN      [4] oled_clk [3] oled_mosi [2] oled_resn [1] oled_dc [0] oled_csn
* 0x0021: RW  P1OUT     ... Five GPIO wires on the OLED connector:
* 0x0022: RW  P1DIR     ... 1: Output 0: Input

* 0x0028: RO  P2IN      [7:0] Eight LEDs on the ULX3S board
* 0x0029: RW  P2OUT      ...
* 0x002A: RW  P2DIR      ... 1: Output 0: Input

* 0x0018: RO  P3IN      [6] RIGHT    Buttons!
                        [5] LEFT 
                        [4] DOWN 
                        [3] UP 
                        [2] F2 
                        [1] F1 
                        [0] PWR, used as reset button, always reads high
                      
* 0x001C: RO  P4IN      [0] Random bit from ring oscillator

Unique registers not seen in "classic" MSP430 chips:

Byte access

* 0x00F0: RO  ADCIN                                  [0] adc_miso
* 0x00F1: RW  ADCOUT    [2] adc_csn   [1] adc_sclk   [0] adc_mosi
 
* 0x00F2: RO  SDIN                                   [0] sd_d0    // MISO
* 0x00F3: RW  SDOUT     [2] sd_d3     [1] sd_clk     [0] sd_cmd  // CS, SCLK, MOSI

* 0x00F4: RO  SPIIN                                  [0] flash_miso
* 0x00F5: RW  SPIOUT    [2] flash_clk [1] flash_mosi [0] flash_csn

Word access

* 0x01A0: RO  PAIN      First row of GPIO pins, 0+ to 13+
* 0x01A1: RW  PAOUT     ...
* 0x01A2: RW  PADIR     ...

* 0x01B0: RO  PBIN      Second row of GPIO pins, 0- to 13-
* 0x01B1: RW  PBOUT     ...
* 0x01B2: RW  PBDIR     ...

* 0x01C0: RO  PCIN      Third row of GPIO pins, 14+ to 27+
* 0x01C1: RW  PCOUT     ...
* 0x01C2: RW  PCDIR     ...            

* 0x01D0: RO  PDIN      Fourth row of GPIO pins, 14- to 27-
* 0x01D1: RW  PDOUT     ...
* 0x01D2: RW  PDDIR     ...

* 0x01F0: R0  CYCLES    Free running cycle counter for delays

* 0x01F2: RW  TICKS     Read: Ticks counter. Write: Set ticks. Generates interrupt on overflow.
* 0x01F4: RW  RELOAD    Reload value the TICKS counter is set to when overflow occours.

* 0x01F6: RW  ANAOUT    Three 4 Bit "DACs" on [11:8] V output [7:4] R output [3:0] L output
```

The timer consists of a TICKS counting register that triggers an interrupt request on overflow, and is subsequently set to the value in the RELOAD register. The interrupt request is wired to the 0xFFF4 "watchdog" vector table entry here.
  
The design contains a ring oscillator used for random numbers, but wait (a few) 100 clock cycles before capturing the next random bit because one gets correlations between the bits when reading too fast. Just give the ring oscillator a little bit of time to drift away.

Reset the CPU by pressing the button labeled "PWR". This does not, however, reload the bitstream with the memory initialisation. It just re-starts with the memory as left before.

Included firmware
---------------------

A copy of Mecrisp 2.0.7 for MSP430G2755 is included as-is, with the user dictionary containing pre-compiled Forth code for disassembler, assembler, multitasking, textmode terminal handling and memory dumps. Have fun, and see the examples!

How to use
---------------------

For loading the bitstream on the ULX3S with a Lattice ECP5 LFE5U-85F FPGA, use:

`openFPGALoader -b ulx3s ulx3s.bin`

Open terminal with 115200 baud 8N1 on the USB-UART bridge interface available on the US1 port you just used for loading the bitstream, or with much more speed by connecting a second USB cable to the US2 port and opening a terminal with any baud rate (it does not matter) on it. Press the button "PWR" which resets the FemtoMSP430, and the included code will detect the connection to US2 and switch over terminal access accordingly.

How to build
---------------------

Run the "release" script.

As-is, it needs the OSS CAD Suite by the Yosys team, the Freepascal compiler (for compiling the mecrimemu emulator that allows to create memory images containing precompiled Forth sources), and the RISC-V binutils (creatively used for preparing the memory initialisation image) installed.

Toolchain "installation" for FPGA
---------------------

Get the latest package for your computers architecture: [https://github.com/YosysHQ/oss-cad-suite-build/releases](https://github.com/YosysHQ/oss-cad-suite-build/releases)

Unpack the toolchain to a suitable place, and - assuming you use Linux - include the toolchain temporarily to your path with the command `source ~/path/to/oss-cad-suite/environment`. This allows to have multiple versions installed on your computer, but just go for the lastest. One note: Do not try to install packaged Yosys/NextPNR/Icestorm tools that might come with your distro -- the toolchain is advancing very, very quick, and if your distro packaged it three months ago, it is already heavily outdated. The ones in Debian Stable -- Ouch!

Credits & Inspration
---------------------

* OpenMSP430 by Olivier Girard: [https://github.com/olgirard/openmsp430/](https://github.com/olgirard/openmsp430/)
* MSP430 in FPGA by Mike Kohn: [https://github.com/mikeakohn/msp430_fpga](https://github.com/mikeakohn/msp430_fpga)
* FemtoRV32 by Bruno Levy and Matthias Koch: [https://github.com/BrunoLevy/learn-fpga/tree/master/FemtoRV/RTL/PROCESSOR](https://github.com/BrunoLevy/learn-fpga/tree/master/FemtoRV/RTL/PROCESSOR)
* Mecrisp Forth by Matthias Koch: [https://mecrisp.sourceforge.net/](https://mecrisp.sourceforge.net/)
* USB-CDC by Ulixxe: [https://github.com/ulixxe/usb_cdc](https://github.com/ulixxe/usb_cdc)
* TMDS encoder for graphics output: [https://www.fpga4fun.com/HDMI.html](https://www.fpga4fun.com/HDMI.html)
