Introduction

A couple of months ago I bought a Numato Mimas v2 with the intention of running MicroPython on it.

Today, with a bit of guess work, a lot of CPU time, and some assistance from the #upy-fpga channel on FreeNode I managed to get it going. Below are my notes on how to get MicroPython on FPGAs running on my Numato Mimas v2. This project is very much a work in progress (I am told multiple people were working on it this weekend), so if you are following this guide later I would definitely suggest seeking out updated instructions.

ETA, 2017-05-07: Indeed new getting started instructions were posted a few weeks later; see the update at the end of this post for more details on the later install approach.

ETA, 2018-01-17: Upstream project now called "FPGA MicroPython", and the best build instructions have changed considerably; see FuPy (FPGA MicroPython) on Mimas v2 and Arty for updated build instructions.

Prerequisites

  • Ubuntu 16.04 LTS x86_64 system

  • Numato Mimas V2 Spartan6 FPGA board, with MimasV2Config.py set up to be able to upload "gateware" to the FPGA board (there is also a copy of MimasV2Config.py installed as part of this envvironment setup below which is used for flashing the MicroPython FPGA gateware).

  • USB A to USB Mini B cable, to connect Numato Mimas V2 to the Ubuntu 16.04 LTS system.

  • Xilinx ISE WebPACK installed, reachable from /opt/Xilinx (or optionally installed within the Xilinx directory inside your build directory).

Before you begin it would be a very good idea to check that the Numato Mimas v2 sample.bin example will run on your Mimas v2, and that you can successful replace it with a program of your own (eg, the Numato tutorial synthesis example).

Building the gateware

The "gateware" consists of the compiled FPGA definitions of the soft CPU (lm32) and peripheral devices that you need. For MicroPython a relatively small "base" set is sufficient.

Setup

Clone the upy-fpga-litex-gateware repository, which originated with the HDMI2USB project (hence the dependencies listed):

git clone https://github.com/upy-fpga/upy-fpga-litex-gateware

Install the relevant bits of the environment in two parts, firstly as root:

cd upy-fpga-litex-gateware
sudo bash -x scripts/download-env-root.sh

which will install dozens of packages as direct or indirect dependencies, including some from Tim Ansell's Ubuntu PPA.

And then as a non-root user (eg, your own user) for the remaining parts:

cd upy-fpga-litex-gateware
bash -x scripts/download-env.sh

which will download a bunch more packages, and execute/install them. Among other things it installs lm32 cross build tools (binutils, gcc, etc), as pre-built binary tools. The install process is managed with conda, a Python environment management tool. (It currently actually installs a Python 3.6 environment, and then downgrades it to Python 3.5.1 for compatability, as well as a lot of other old tools.)

It also automatically git clones the relevant Enjoy Digital litex git modules, as listed in the README.

The environment install process will take several minutes, mostly depending on the download speed.

Build

From a terminal which has not entered the Xilinx ISE WebPACK environment, set the desired PLATFORM and TARGET to select what will be built, then enter the upy-fpga environment:

cd upy-fpga-litex-gateware
PLATFORM=mimasv2
TARGET=base
export PLATFORM TARGET
source scripts/enter-env.sh

All going well, it should do some checking, report the directories being used, and then change the prompt to include the PLATFORM and TARGET values. Eg,

(H2U P=mimasv2 T=base R=nextgen)

make help will show you the valid PLATFORM and TARGET values, but cannot be run until after scripts/enter-env.sh has been done; in theory you can change PLATFORM and TARGET after entering the environment, but it might be safest to start with a fresh terminal. (README.targets has some information on the possible TARGET values.)

From there, you can build the "gateware" for your selected PLATFORM/TARGET combination with:

make gateware

which will result in a lot of output, most of it from the Xilinx ISE WebPACK tools. This step will also take a few minutes, and will keep your CPU pretty busy. All going well you should end up with a build/mimasv2_base_lm32/gateware/top.bin file which is the system on a chip to be loaded onto the Mimas V2.

Next you can build the "firmware" to run on the softcore CPU to provide MicroPython on the FPGA. You can build this for your selected PLATFORM/TARGET combination with:

make firmware

This step appears to use a pre-compiled firmware file, and builds quite quickly. It should result in a build/mimasv2_base_lm32/software/firmware/firmware.bin file.

Gateware and Firmware install

Ensure that the Numato Mimas v2 "operation mode" switch (SW7) is set to program mode -- the side nearest the USB connector is program mode (see the Numato Mimas V2 documentation).

Bundle up the gateware, BIOS, and firmware togther with:

make image

(which runs ./mkimage.py), to create build/mimasv2_base_lm32/flash.bin.

Then install the gateware, BIOS and firmware bundle with:

make image-flash

(which effectively runs make image-flash-mimasv2 due to the PLATFORM setting).

Because the upload happens at 19200 bps, this will take a couple of minutes to complete -- it does an erase cycle, a write cycle, and a read-back verification cycle.

The upload process looks something like:

(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$ make gateware-flash-mimasv2
python $(which MimasV2Config.py) /dev/ttyACM0 build/mimasv2_base_lm32//flash.bin
****************************************
* Numato Lab Mimas V2 Configuration Tool *
****************************************
Micron M25P16 SPI Flash detected
Loading file build/mimasv2_base_lm32//flash.bin...
Erasing flash sectors...
Writing to flash 100% complete...
Verifying flash contents...
Flash verification successful...
Booting FPGA...
Done.
(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$

The Mimas v2 will reboot into the default firmware which is not MicroPython (see later in the document on getting MicroPython running).

Modern lm32 build environment for MicroPython

Building MicroPython needs a fairly recent crosscompiler build environment, newer than the one used by the MicroPython gateware.

This step is best done in a terminal which does not have the gateware configuration (above) in it, so start a fresh terminal.

To build this newer crosscompiler environment clone the lm32-build-scripts repository:

git clone https://github.com/shenki/lm32-build-scripts.git

Then build the cross compilers on your system with:

cd lm32-build-scripts
./build-lm32-toolchain.sh

It will download several key Linux build tools (gcc, gmp, mpfr, mpc, binutils, gdb, etc), and then use them to build a crosscompiler for lm32, designed to be installed in /opt/lm32.

This step will take several minutes, partcularly to download the required source to build. Expect your CPU to be very busy for a while as it does a make -j32 when building everything; this also makes the console output fairly tricky to follow, and it fairly difficult to tell how far through the build process it has reached. (Currently there does not seem to be any check that the downloads are complete, or as intended -- nor any stop and continue steps in the build process -- so it is a bit "hope this works". There is partial support for building a Docker environment with the cross-compilers, but it appears to do a one-shot build and then remove them; presumably it is there only for testing the build scripts work.)

Assuming that it finishes without obvious error, and the return code is 0:

echo $?

then we can assume that it worked. The build directory should include a lot of built code (approximately 2GB).

The built code can then be installed somewhere central with:

sudo mkdir /opt/lm32
sudo chown $USER:$USER /opt/lm32
(cd build && make install)

which will also generate a lot of output, but run much quicker.

After this /opt/lm32/bin should contain a bunch of useful cross-compile tools, eg:

ewen@parthenon:/opt/lm32/bin$ ls
lm32-elf-addr2line  lm32-elf-gcc-6.2.0   lm32-elf-gprof    lm32-elf-readelf
lm32-elf-ar         lm32-elf-gcc-ar      lm32-elf-ld       lm32-elf-run
lm32-elf-as         lm32-elf-gcc-nm      lm32-elf-ld.bfd   lm32-elf-size
lm32-elf-c++filt    lm32-elf-gcc-ranlib  lm32-elf-nm       lm32-elf-strings
lm32-elf-cpp        lm32-elf-gcov        lm32-elf-objcopy  lm32-elf-strip
lm32-elf-elfedit    lm32-elf-gcov-tool   lm32-elf-objdump
lm32-elf-gcc        lm32-elf-gdb         lm32-elf-ranlib
ewen@parthenon:/opt/lm32/bin$

MicroPython

MicroPython is also best built in a new terminal, without the gateware build environment variables. It needs to be built from an in-development repository with changes for MicroPython on FPGA and the Mimas v2.

In a fresh terminal, clone the forked MicroPython repository, with Mimas V2 support in it:

git clone https://github.com/upy-fpga/micropython.git

(There are other repositories too; I chose this one to try first as it had been reported as working on the Mimas v2. Apparently the lm32-v2 branch is the main one being worked on at present.)

Enter the repository, and checkout the lm32-mimas2 branch:

cd micropython
git checkout lm32-mimas2

ETA, 2017-03-16: The upy-fpga/micropython has been rebased onto the upstream micropython/micropython, with the lm32 patches merged onto the master branch; it is now best just to use the master branch (and there is no lm32-mimas2 branch any longer).

Change into the lm32 directory, and build with a cross compiler:

cd lm32
PATH="${PATH}:/opt/lm32/bin" make CROSS=1

That should build fairly quickly, and result in a build/firmware.elf file. Convert that into a firmware.bin file that can be uploaded to the Mimas v2 with:

PATH="${PATH}:/opt/lm32/bin" make build/firmware.bin CROSS=1

ETA, 2017-03-13: Apparently one should copy the contents of the build/mimasv2_base_lm32/software/include/generated from the gateware build environment (above) into the micropython/lm32/generated directory before building, to keep them in sync. I did not do this, and presumably it worked due to having an old "compatible enough" version checked in.

Installing MicroPython on the Numato Mimas v2

To actually install MicroPython, we have a few options. Firstly we can build a complete flash image including MicroPython instead of the default firmware. Secondly we can reset the soft CPU running in the default firmware and trigger an upload of MicroPython to run that boot instead of the default firmware. Thirdly we can upload a flash image without any default firmware, and rely on always uploading the application we want to run.

Flash image including MicroPython

Return to the gateware build top directory, with the environment set up, ie as before (possibly you still have a suitable terminal open):

cd upy-fpga-litex-gateware
PLATFORM=mimasv2
TARGET=base
export PLATFORM TARGET
source scripts/enter-env.sh

Make a directory to build up the MicroPython flash image:

mkdir micropython
cd micropython

And then copy over the MicroPython firmware.elf and firmware.bin file:

cp -p .../micropython/lm32/build/firmware.bin .

Run:

python -m litex.soc.tools.mkmscimg -f firmware.bin -o firmware.fbi

to build a firmware.fbi file.

Change back up to the top directory, and then use mkimage to build a complete flash image including MicroPython:

cd ..
rm build/mimasv2_base_lm32/flash.bin
./mkimage.py --override-firmware micropython/firmware.fbi

This should build a new flash image in build/mimasv2_base_lm32/flash.bin. with output something like:

(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$ ./mkimage.py --override-firmware micropython/firmware.fbi

Gateware @ 0x00000000 (    341436 bytes) build/mimasv2_base_lm32/gateware/top.bin                     - Xilinx FPGA Bitstream
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff aa 99 55 66 30 a1 00 07 20 00 31 a1 03 80 31 41 3d 00 31 61 09 ee 31 c2 04 00 10 93 30 e1 00 cf 30 c1 00 81 20 00 20 00 20 00 20 00 20 00 20 00
    BIOS @ 0x00080000 (     19356 bytes) build/mimasv2_base_lm32/software/bios/bios.bin               - LiteX BIOS with CRC
98 00 00 00 d0 00 00 00 78 01 00 08 38 21 00 00 d0 e1 00 00 e0 00 00 3b 34 00 00 00 34 00 00 00 e0 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00
Firmware @ 0x00088000 (    153736 bytes) micropython/firmware.fbi                                     - HDMI2USB Firmware in FBI format (loaded into DRAM)
00 02 58 80 36 67 08 1a 98 00 00 00 d0 00 00 00 78 01 40 00 38 21 00 00 d0 e1 00 00 e0 00 00 3b 34 00 00 00 34 00 00 00 e0 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00
----------------------------------------
       Remaining space    1386360 bytes (10 Megabits, 1.32 Megabytes)
           Total space    2097152 bytes (16 Megabits, 2.00 Megabytes)

Flash image: build/mimasv2_base_lm32/flash.bin
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff aa 99 55 66 30 a1 00 07 20 00 31 a1 03 80 31 41 3d 00 31 61 09 ee 31 c2 04 00 10 93 30 e1 00 cf 30 c1 00 81 20 00 20 00 20 00 20 00 20 00 20 00
(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$

Then this custom flash image can be loaded onto the Numato Mimas v2, by ensuring that the "operation mode" switch (SW7) is in "program mode" (nearest to the USB connector), then running:

MimasV2Config.py /dev/ttyACM0 build/mimasv2_base_lm32/flash.bin

to program MicroPython onto the Mimas v2. This will take a few minutes to write, as it is uploading at 19200 bps.

The result should look something like:

(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$ MimasV2Config.py /dev/ttyACM0 build/mimasv2_base_lm32/flash.bin
****************************************
* Numato Lab Mimas V2 Configuration Tool *
****************************************
Micron M25P16 SPI Flash detected
Loading file build/mimasv2_base_lm32/flash.bin...
Erasing flash sectors...
Writing to flash 100% complete...
Verifying flash contents...
Flash verification successful...
Booting FPGA...
Done.
(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$

Using the REPL of MicroPython on the FPGA

Unplug the Numato Mimas v2, to power it down.

Move the Numato Mimas V2 "operation mode" switch (SW7) to serial port mode (furthest away from the USB port), so that a terminal program on the computer can communicate with the softcore in the FPGA.

Then run:

screen /dev/ttyACM0 19200

to connect to the MicroPython REPL.

(For some reason MicroPython does not work with flterm as the serial console program, hence "make firmware-connect-mimasv2" which uses flterm does not work; thus the use of screen as a simple terminal emulator. ETA, 2017-05-15: Recent builds of flterm fix this issue so it is not necessary to start screen to interact with MicroPython.)

All going well, if you hit enter a couple of times, you should get a prompt, and then be at the Python REPL:

>>>
>>>
>>>
>>> print("Hello World!")
Hello World!
>>>

To get out of the screen session, use ctrl-a \ (backslash) to quit screen.

Uploading MicroPython at boot

The disadvantage of including MicroPython in the flash image is that the whole system needs to be reflashed for every change to MicroPython. As an alternative it is possible to program the Mimas v2 flash with the default application, and then upload the MicroPython firmware application over the serial link, through the BIOS boot loader.

To do this, build the default firmware image as above, and upload that:

make image
make image-flash

then change the operation mode (SW7) to "serial port" (away from the USB connector), and start flterm to upload the MicroPython firmware.bin into RAM on the Mimas v2:

flterm --port=/dev/ttyACM0 --kernel=micropython/firmware.bin --speed=19200

Once flterm is running, press SW6 (button 6, at top right), to send a reset to the soft CPU. (In theory one should be able to type reboot at the H2U> application prompt, but at present on the Mimas v2 that jumps to the wrong address and just hangs.)

You should see the BIOS/boot loader messages appear, and then it should prompt flterm to send the kernel image to run. The upload should start automatically and look something like:

LiteX SoC BIOS (lm32)
(c) Copyright 2012-2017 Enjoy-Digital
(c) Copyright 2007-2017 M-Labs Limited
Built Mar 12 2017 15:39:00

BIOS CRC passed (cdfe4dda)
Initializing SDRAM...
Memtest OK
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
[FLTERM] Received firmware download request from the device.
[FLTERM] Uploading kernel (153728 bytes)...
[FLTERM] Upload complete (1.6KB/s).
[FLTERM] Booting the device.
[FLTERM] Done.
Executing booted program.
MicroPython v1.8.7-38-gafd8920 on 2017-03-12; litex with lm32
Type "help()" for more information.
>>>

Unfortunately the problem of MicroPython and flterm disagreeing about something still exists, so once you reach this point, you need to disconnect flterm (ctrl-c) and reconnect with screen at this point to use the REPL (ETA, 2017-03-15: unless you have a recent build of flterm):

screen /dev/ttyACM0 19200

and then the Python REPL should work:

>>>
>>>
>>>
>>> print("hello world!")
hello world!
>>>

To get out of the screen session, use ctrl-a \ (backslash) to quit screen.

A third option: no default application

It is also possible to build the flash image without a default application, and then simply rely on resetting the Mimas v2 and flterm uploading the application to run.

To do this:

rm build/mimasv2_base_lm32/flash.bin
./mkimage.py --override-firmware none

which should result in something like:

(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$ ./mkimage.py --override-firmware none

Gateware @ 0x00000000 (    341436 bytes) build/mimasv2_base_lm32/gateware/top.bin                     - Xilinx FPGA Bitstream
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff aa 99 55 66 30 a1 00 07 20 00 31 a1 03 80 31 41 3d 00 31 61 09 ee 31 c2 04 00 10 93 30 e1 00 cf 30 c1 00 81 20 00 20 00 20 00 20 00 20 00 20 00
    BIOS @ 0x00080000 (     19356 bytes) build/mimasv2_base_lm32/software/bios/bios.bin               - LiteX BIOS with CRC
98 00 00 00 d0 00 00 00 78 01 00 08 38 21 00 00 d0 e1 00 00 e0 00 00 3b 34 00 00 00 34 00 00 00 e0 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00 34 00 00 00
Firmware @ 0x00088000 (         0 bytes) Skipped                                                      - HDMI2USB Firmware in FBI format (loaded into DRAM)

----------------------------------------
       Remaining space    1540096 bytes (11 Megabits, 1.47 Megabytes)
           Total space    2097152 bytes (16 Megabits, 2.00 Megabytes)

Flash image: build/mimasv2_base_lm32/flash.bin
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff aa 99 55 66 30 a1 00 07 20 00 31 a1 03 80 31 41 3d 00 31 61 09 ee 31 c2 04 00 10 93 30 e1 00 cf 30 c1 00 81 20 00 20 00 20 00 20 00 20 00 20 00
(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$

That can be programmed onto the Mimas v2, by putting the Mimas v2 into programming mode (SW7 to the side nearest the USB connector), then running:

MimasV2Config.py /dev/ttyACM0 build/mimasv2_base_lm32/flash.bin

Once that completes put the "operation mode" switch (SW7) back to the "serial console" mode (furthest from the USB connector), then run flterm as above:

flterm --port=/dev/ttyACM0 --kernel=micropython/firmware.bin --speed=19200

and hit enter a couple of times. You should get a BIOS> prompt. At that prompt you can type serialboot to get it kick off the application upload:

(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$ flterm --port=/dev/ttyACM0 --kernel=micropython/firmware.bin --speed=19200
[FLTERM] Starting...

BIOS>
BIOS>
BIOS>
BIOS> serialboot
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
[FLTERM] Received firmware download request from the device.
[FLTERM] Uploading kernel (153728 bytes)...
[FLTERM] Upload complete (1.6KB/s).
[FLTERM] Booting the device.
[FLTERM] Done.
Executing booted program.
MicroPython v1.8.7-38-gafd8920 on 2017-03-12; litex with lm32
Type "help()" for more information.
>>>
(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$

(or just press SW6 to reset the soft CPU back into the start of the boot loader, once you have flterm running, as with the second option above).

As above, you will need to disconnect flterm (ctrl-c) once the MicroPython banner appears, and start screen to interact with the MicroPython REPL (ETA, 2017-03-15: unless you have a recent build of flterm):

screen /dev/ttyACM0 19200

To get out of the screen session, use ctrl-a \ (backslash) to quit screen.

Other references

ETA, 2017-03-13: Lots of proof reading edits, and tweaks based on advice from Tim Ansell.

ETA, 2017-03-15: A newer version of flterm is now available, which does work with MicroPython, so it is now possible to do both the MicroPython firmware upload and interact with MicroPython from one program (ie, no need to exit out to screen).

To update, after building everything, do conda install flterm, which should install flterm 2.4_15_gd17828f-0 timvideos:

(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$ conda install flterm
Fetching package metadata ...........
Solving package specifications: .

Package plan for installation in environment /home/ewen/work/naos/src/upy-fpga/upy-fpga-litex-gateware/build/conda:

The following packages will be UPDATED:

    flterm: 0+git20160123_1-0 timvideos --> 2.4_15_gd17828f-0 timvideos

flterm-2.4_15_ 100% |################################| Time: 0:00:01   6.17 kB/s
(H2U P=mimasv2 T=base R=nextgen) ewen@parthenon:~/work/naos/src/upy-fpga/upy-fpga-litex-gateware$

Run flterm as usual (eg, as explained above). You can tell that it is working properly if hitting enter at the MicroPython REPL gives you another prompt, and you are able to enter Python programs.

ETA, 2017-03-15: Katie Bell pointed out that there is a not-merged testing branch which enables controlling the LEDs on the Numato Mimas v2 board. It is in the lm32-leds branch of shenki's MicroPython repository on GitHub, with an example given in the lm32: Add leds module commit comment.

I was able to build it:

git clone https://github.com/shenki/micropython micropython-shenki
cd micropython-shenki
git checkout lm32-leds
cd lm32
PATH="${PATH}:/opt/lm32/bin" make CROSS=1
PATH="${PATH}:/opt/lm32/bin" make build/firmware.bin CROSS=1

and then get it working on my Numato Mimas v2 board with:

cd upy-fpga-litex-gateware
PLATFORM=mimasv2
TARGET=base
export PLATFORM TARGET
source scripts/enter-env.sh
cd micropython
mkdir leds
cd leds
cp -p ..../micropython-shenki/lm32/build/firmware.bin .
python -m litex.soc.tools.mkmscimg -f firmware.bin -o firmware.fbi
cd ../..
flterm --port=/dev/ttyACM0 --kernel=micropython/leds/firmware.bin --speed=19200

and then press SW6 (top right) to reset the soft CPU into the boot loader, and load that newer build of MicroPython.

>>>
LiteX SoC BIOS (lm32)
(c) Copyright 2012-2017 Enjoy-Digital
(c) Copyright 2007-2017 M-Labs Limited
Built Mar 12 2017 15:39:00

BIOS CRC passed (cdfe4dda)
Initializing SDRAM...
Memtest OK
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
[FLTERM] Received firmware download request from the device.
[FLTERM] Uploading kernel (180724 bytes)...
[FLTERM] Upload complete (1.6KB/s).
[FLTERM] Booting the device.
[FLTERM] Done.
Executing booted program.
MicroPython v1.8.7-182-gd86a88c on 2017-03-15; litex with lm32
>>>
>>> import litex
>>> leds = [ litex.LED(n) for n in range(1,9) ]
>>> print(leds)
[LED(1), LED(2), LED(3), LED(4), LED(5), LED(6), LED(7), LED(8)]
>>> for led in leds:
...     led.on()
...
>>> for led in leds:
...     led.off()
...
GC: total: 1984, used: 1408, free: 576
 No. of 1-blocks: 7, 2-blocks: 7, max blk sz: 32, max free sz: 8
>>>

During the led.on() loop all the LEDs should turn on; during the led.off() loop, all the LEDs should turn off. But note the GC line indicating that about 75% of the memory resources are in use, just holding those 8 LED objects open -- so this may not be the most memory efficient approach.

(Unfortunately this particular MicroPython build does not have as many features turned on as the MicroPython for the ESP8266, so things like time.sleep() do not seem to be available.)

ETA, 2017-03-16: The upy-fpga/micropython has been rebased onto the upstream micropython/micropython, with the lm32 patches merged onto the master branch; it is now best just to use the master branch (and there is no lm32-mimas2 branch any longer).

ETA, 2017-05-07:

Updated upy-fpga bootstrap instructions

Tim Ansell posted new upy-fpga bootstrap instructions, which simplified the steps to get a working upy-fpga system on the Mimas V2 board.

The instructions point at the upy-fpga-litext-gateware "getting started" document, which uses a curl | sudo bash bootstrap method.

Since I am not that fond of curl | sudo bash, I chose a slightly different way to get started. Firstly I downloaded the bootstrap script to review:

curl -fsS -o hdmi2usb-litex-firmware-bootstrap.sh https://raw.githubusercontent.com/timvideos/HDMI2USB-litex-firmware/master/scripts/bootstrap.sh

Then I looked through te script to check that everything seemed sensible. Similar to the appoach that I followed originally (described above), it does a recursive clone of the git repository:

https://github.com/timvideos/HDMI2USB-litex-firmware.git

which is effectively the upstream of which upy-fpga-litex-firmwware was forked. This results in building from the timvideos/HDMI2USB-litex-firmware GitHub repostory instead of the upy-fpga/upy-fpga-litex-gateware repository. (It is possible to point it at the HDMI2USB-litex-firmware.git repository in another GitHub account by setting GITHUB_USER first, but not obviously at another repository name. GITHUB_USER defaults to timvideos, note the singular "tim", as "timvideos" is something else.)

The recursive clone will pick up a number of third party git repositories as well, including litex and several lite.... component ones. Once the git clone finishes, it will automatically run the scripts/download-env-root.sh script as root, which uses apt-get to install a bunch of additional tools, and then also automatically run the scripts/download-env.sh as your own user, which will use conda to install a bunch more things. The things installed are similar to what I described in my previous blog post, but these scripts are run from the timvideos/HDMI2USB-litex-firmware repository.

Once you are happy with what it is going to do, run the bootstrap.sh script (as a regular non-root user) with something like:

bash -x hdmi2usb-litex-firmware-bootstrap.sh

(You might want to run it inside a script session to get a record of what it is doing.)

When it gets to the point of needing root credentials (to run scripts/ download-env-root.sh), sudo will probably prompt for your password, which gives you a chance to review that what it downloaded in the git clone, is the same as what you expected from the git repository. You should also review the downloaded scripts/download-env.sh script at this point too, to make sure you are happy with that, as it will run immediately afterwards.

If you have already run the download-env-root.sh script from a previous install, it will probably not install anything new at this point. However the download-env.sh script will use conda to install a large number of things, including downloading various lm32 tools very slowly (20-60 kB/s in my case, so well under 1Mbps). The conda installed things appear to end up in build/conda/bin and friends, so as the downloads progress you will see more lm32-... tools in build/conda/bin. Altogether after these steps the build directory contains about 500MB (0.5GB) of programs.

Once you reach the line "Bootstrap: Set up complete, you're good to go!" the gateway build environment bootstrap phase is complete. You might want to make a backup of the build directory at this point to save time if you want to start again later:

cd HDMI2USB-litex-firmware
mkdir -p ../bootstrap
tar -cpzf ../bootstrap/hdmi2usb-litex-firmware-build-after-bootstrap.tar.gz build

After that, you can move onto building MicroPython.

To build MicroPython for the Mimas V2, enter the gateware build environment for the Mimas V2 with:

cd HDMI2USB-litex-firmware
export PLATFORM=mimasv2
export TARGET=base
source scripts/enter-env.sh

and you should get your prompt changed to include "(H2U P=mimasv2 T=base)" at the start. (It appears that scripts/settings.sh, is defaulting the CPU to lm32, otherwise you would also need export CPU=lm32.)

Next, build the gateware (ie, the FPGA logic for the lm32 soft CPU and peripherals):

make gateware

All going well, that should end with "Bitstream generation is complete."

Then you can run the scripts/build-micropython.sh script, which will clone the upy-fpga repository (https://github.com/upy-fpga/micropython.git), and then build a MicroPython binary image for your specified platform. Eg,

bash -x scripts/build-micropython.sh

However, one of the first things that will do is use conda to install another lm32 gcc package -- an elf-newlib variation -- if you do not already have it installed. So be prepared for another bootstrap phase (with another slow download) the first time you run it.

After two long, slow, failed, download attempts failed, I tried grabbing the URL that conda reported unable to download on another system and copying that into build/conda/pkgs trying to avoid conda trying to download it from the network. Unfortunately conda was determined to download the file itself, and just moved my pre-downloaded file out of the way. I eventually managed to make it install, by setting http_proxy and https_proxy to point at a web proxy, at another site, which seemed to be able to keep streaming data fast enough that conda did not time out. (conda seems to have rather short timeouts, and its only recovery mechanism appears to be to delete the download attempt and start again from scratch -- which is an incredibly user and bandwidth hostile measure. At minimum it should be able to resume downloads, or use a download tool, like wget, which will automatically attempt to resume downloads.)

Assuming that (eventually!) works, you should end up with build/mimasv2_base_lm32/software/micropython/firmware.fbi (and .../micropython/firmware.bin) with the MicroPython build, and build/mimasv2_base_lm32/micropython.bin with a ready-to-flash image containing the gateway and firmware.

If the board already has earlier gateware loaded (eg from following the earlier instructions above), you can upload the new MicroPython build temporarily by setting SW7 to the serial interaction mode (right hand side), and then running:

flterm --port=/dev/ttyACM0 --kernel="build/${PLATFORM}_${TARGET}_${CPU}/software/micropython/firmware.bin" --speed=19200

and then press SW6 (top right of the Mimas V2) to cause the Mimas V2 to restart, which should start the upload of the MicroPython software. This should look something like:

(H2U P=mimasv2 T=base) ewen@parthenon:/src/upy-fpga/HDMI2USB-litex-firmware$ flterm --port=/dev/ttyACM0 --kernel=build/${PLATFORM}_${TARGET}_${CPU}/software/micropython/firmware.bin --speed=19200
[FLTERM] Starting...

LiteX SoC BIOS (lm32)
(c) Copyright 2012-2017 Enjoy-Digital
(c) Copyright 2007-2017 M-Labs Limited
Built Mar 12 2017 15:39:00

BIOS CRC passed (cdfe4dda)
Initializing SDRAM...
Memtest OK
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
[FLTERM] Received firmware download request from the device.
[FLTERM] Uploading kernel (167952 bytes)...
[FLTERM] Upload complete (1.6KB/s).
[FLTERM] Booting the device.
[FLTERM] Done.
Executing booted program.
MicroPython v1.8.7-458-gb63852f on 2017-05-07; litex with lm32
>>>
>>>
>>> print("Hello World!")
Hello World!
>>>
(H2U P=mimasv2 T=base) ewen@parthenon:/src/upy-fpga/HDMI2USB-litex-firmware$

It is also possible to flash the Mimas V2 with the new gateware and firmware combination, in build/mimasv2_base_lm32/micropython.bin, by setting SW7 to be in the gateware upload mode (to the left hand side) and then running:

MimasV2Config.py /dev/ttyACM0 "build/${PLATFORM}_${TARGET}_${CPU}/micropython.bin"

which should look something like:

(H2U P=mimasv2 T=base) ewen@parthenon:/src/upy-fpga/HDMI2USB-litex-firmware$ MimasV2Config.py /dev/ttyACM0 "build/${PLATFORM}_${TARGET}_${CPU}/micropython.bin"
****************************************
* Numato Lab Mimas V2 Configuration Tool *
****************************************
Micron M25P16 SPI Flash detected
Loading file build/mimasv2_base_lm32/micropython.bin...
Erasing flash sectors...
Writing to flash 100% complete...
Verifying flash contents...
Flash verification successful...
Booting FPGA...
Done.
(H2U P=mimasv2 T=base) ewen@parthenon:/src/upy-fpga/HDMI2USB-litex-firmware$

Once that you finishes, move SW7 to the serial interaction setting (to the right), and use flterm to connect to the Python REPL:

flterm --port=/dev/ttyACM0 --speed=19200

Press enter a few times until you get a Python REPL prompt:

(H2U P=mimasv2 T=base) ewen@parthenon:/src/upy-fpga/HDMI2USB-litex-firmware$ flterm --port=/dev/ttyACM0 --speed=19200
[FLTERM] Starting...

>>>
>>>
>>>
>>> print("Hello World!")
Hello World!
>>>
>>>
(H2U P=mimasv2 T=base) ewen@parthenon:/src/upy-fpga/HDMI2USB-litex-firmware$

and ctrl-C when you are done.

The now-merged upy-fpga/micropython.git repository includes the Mimas V2 LED support, so the LED example above should work too.

ETA, 2018-01-16: The "MicroPython on FPGA" project has been renamed to "FPGA MicroPython", with a new GitHub organisation, and a set of new GitHub Repos. GitHub will auto-redirect many git repo references, so the above instructions might continue to work, but newer references should point at https://github.com/fupy/....

ETA, 2018-01-17: See new blog post FuPy (FPGA MicroPython) on Mimas v2 and Arty for updated build instructions.