Introduction

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.

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).

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.)

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).

Modern lm32 build environment for MicroPython

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).

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.)

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):

Using the REPL of MicroPython on the FPGA

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:

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:

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.

(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.

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:

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.)

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:

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 anotherlm32gcc 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:

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:

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/....