Tested platform:
WIN10-WSL (ubuntu 18.04) : yosys / next-pnr-ice40 / icestorm build from latest github
- Note: WSL does not support FTDI usb device, use windows version "iceprog.exe" instead
ubuntu 18.04 : yosys / next_pnr-ice40 / icestorm build from latest github
Msys - mingw64:
toolchain-yosys / toolchain-ice40 from
FPGAWars github
FTDI driver:
- Modify default winusb driver to libusbK (libusb-1.0 support)
Ubuntu 18.04: sudo apt install libftdi-dev
Msys prepare:
Get copy of Msys from https://www.msys2.org/
After Msys successfully installed, follow below steps to make it works smoothly:
change software package source to native ones, the configure file location: msys64/etc/pacman.d/
if pacman timeout, try --disable-download-timeout while run pacman
run msys2_shell.bat: pacman -Sy to update core packages
update core packages:
pacman -S --needed filesystem msys2-runtime bash libreadline libiconv \
libarchive libgpgme libcurl pacman ncurses libintl
then close all MSYS2 shell,run autorebase.bat
update other packages:pacman -Su
Usefull commands:
pacman -Q to list packages installed
pacman -S -g to list package groups
pacman -Q -g base-devel to list packages inside a software
pacman -Q -l vim to list contents of a package
pacman -Q -s nettle to query the package of software
for help:pacman -h ;pacman -S -
it's recommendded to install toolchains by its package group:
pacman -S mingw-w64-i686-toolchain
pacman -S mingw-w64-x86_64-toolchain
pacman -S base-devel
pacman -S vim
We need python3 to run our nmigen platform
pacman -S python3 python3-pip
nMigen & lambdaSoC prepare
git clone https://github.com/nmigen/nmigen
cd nmigen && python3 setup.py install
git clone https://github.com/nmigen/nmigen-soc
cd nmigen-soc && python3 setup.py install
git clone https://github.com/nmigen/nmigen-stdio
cd nmigen-stdio && python3 setup.py install
git clone https://github.com/nmigen/nmigen-boards
cd nmigen-boards && python3 setup.py install
git clone https://github.com/lambdaconcept/minerva
cd minerva && python3 setup.py install
git clone https://github.com/lambdaconcept/lambdasoc
cd lambdasoc && python3 setup.py install
RISCV toolchain prepare
lambdasoc based on Minerva (pure python version) RISCV core, so we needs riscv toochain for soc software building.
there is a prebuild version from sifive which is almost prefect for us (for Windows/Linux/MacOS)
Windows prepare for WSL or Msys
If we use win10/WSL, we can build our own yosys / icestorm / next-pnr from github source,
but as known, WSL do not support native USB device (libusb-1.0), so we needs a windows version "iceprog.exe"
to do program, for all others toolchains, we can use our build version (WSL/ubuntu)
if we use Msys-mingw64, recommeneded to use yosys and iCE40 toolchains released from FPGAwars
After software installed, our bash script should be updated as follow:
.bash_alias for WIN10/WSL, (yosys/next-pnr/icestorm builded and installed to /usr/local/bin)
export DISPLAY=localhost:0.0
export RISCV=/opt/riscv64-elf-x86_64
RISCV32=/opt/lowrisc-rv32imc
PATH=$PATH:$RISCV/bin
PATH=$PATH:$RISCV32/bin
# we just needs iceprog.exe only, so copy it to a new directory
PATH=$PATH:/mnt/d/Software/toolchain-ice40-windows_amd64-2019.12.11/bin/iceprog-win
export PATH
export ICEPROG="iceprog.exe"
.bashrc for Msys - mingw64
# alias cd=cd_func
PATH='/c/openEDA/iverilog/bin':$PATH PATH='/c/openEDA/iverilog/gtkwave/bin':$PATH
PATH='/d/Software/toolchain-ecp5-windows_amd64-2019.12.11/bin':$PATH
PATH='/d/Software/toolchain-ice40-windows_amd64-2019.12.11/bin':$PATH
PATH='/d/Software/toolchain-yosys-windows_amd64-2019.12.11/bin':$PATH
PATH='/d/Software/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-w64-mingw32/bin':$PATH
#PATH='/d/intelFPGA/18.1/quartus/bin64':$PATH
#PATH='/d/Xilinx/Vivado/2018.3/bin':$PATH
#PATH='/d/Software/xc3sprog_win32_rev780':$PATH
#PATH=$PATH:'/c/Program Files (x86)/Vim/vim82'
export PATH
Test nMigen platform
Create a directory for test our nMigen building platform
$mkdir ~/nmigen_test
$cd ~/nmigen_test
$cp ~/projects/nmigen/nmigen-boards/nmigen_boards/upduino_v2.py .
By default, upduino_v2.py build based on upduino_v1.py, which defined default_clk to "SB_HFOSC"
there is no "SB_HFOSC" instance inside upduino_v2.py, so if we try to build, will got error.
to fix the problem, we can add SB_HFOSC instance and modify "sync" domain to output of SB_HFOSC.
But very lucky, upduino_v2 route on-board 12MHz crystall output to J8 which can be coupled with JP6-12
easily with a jumper. so we can define default clock to extenal clock resource "clk12" defined inside upduino_v2.py
modify our upduino_v2.py like this: (care of lines in Bold)
#!/usr/bin/env python3
import os
import subprocess
from nmigen.build import *
from nmigen.vendor.lattice_ice40 import *
from nmigen_boards.resources import *
from nmigen_boards.upduino_v1 import UpduinoV1Platform
from nmigen_boards.test.blinky import Blinky
class myPlatform(UpduinoV1Platform):
default_clk = "clk12"
# Mostly identical to the V1 board, but it has an integrated
# programmer and a 12MHz oscillator which is NC by default.
resources = UpduinoV1Platform.resources + [
# Solder pin 12 to the adjacent 'J8' osc_out pin to enable.
Resource("clk12", 0, Pins("12", dir="i"),
Clock(12e6), Attrs(IO_STANDARD="SB_LVCMOS")),
]
def toolchain_program(self, products, name):
iceprog = os.environ.get("ICEPROG", "iceprog")
with products.extract("{}.bin".format(name)) as bitstream_filename:
subprocess.check_call([iceprog, bitstream_filename])
if __name__ == "__main__":
myPlatform().build(Blinky(), do_program=True)
Now, we can connect upduino_v2 kit to our computer and run "python3 upduino_v2.py"
Just wait and see....
hope there is no any problem.
If everything goes well, it's time to build lambdaSoC for our upduino_v2.
Firstly, Copy example soc from lambdasoc directory:
$cp ~/projects/lambdaconcept/lambdasoc/example/sram_soc.py .
Before start, we should make serveral modification to make it fit our upduino_v2
upduino_v2 has limited ram resouce , so reduced the rom size to fit up5k device
add UART resource definition, which is useful for debug, also needed by example soc
for Msys-mingw64, there is no "glob.h" (posix api) support, which need by lambdsoc build procedure,
here we just disable do_build and do_init of soc to passby the problem.
Finally, upduino_v2.py and sram_soc.py after modification:
# filename: upduino_v2.py
import os
import subprocess
from nmigen.build import *
from nmigen.vendor.lattice_ice40 import *
from nmigen_boards.resources import *
from nmigen_boards.upduino_v1 import UpduinoV1Platform
__all__ = ["UpduinoV2Platform"]
class UpduinoV2Platform(UpduinoV1Platform):
# Mostly identical to the V1 board, but it has an integrated
# programmer and a 12MHz oscillator which is NC by default.
default_clk = "clk12"
resources = UpduinoV1Platform.resources + [
# Solder pin 12 to the adjacent 'J8' osc_out pin to enable.
Resource("clk12", 0, Pins("12", dir="i"),
Clock(12e6), Attrs(IO_STANDARD="SB_LVCMOS")),
UARTResource(0,
rx="6", tx="9", attrs=Attrs(IO_STANDARD="SB_LVTTL", PULLUP=1)),
]
def toolchain_program(self, products, name):
iceprog = os.environ.get("ICEPROG", "iceprog")
with products.extract("{}.bin".format(name)) as bitstream_filename:
subprocess.check_call([iceprog, bitstream_filename])
if __name__ == "__main__":
from nmigen_boards.test.blinky import *
UpduinoV2Platform().build(Blinky(), do_program=True)
Filename: sram_soc.py
# filename: sram_soc.py
import argparse
import importlib
from nmigen import *
from nmigen_soc import wishbone
from lambdasoc.cpu.minerva import MinervaCPU from lambdasoc.periph.intc import GenericInterruptController
from lambdasoc.periph.serial import AsyncSerialPeripheral
from lambdasoc.periph.sram import SRAMPeripheral
from lambdasoc.periph.timer import TimerPeripheral
from lambdasoc.soc.cpu import CPUSoC
# import our modified version
from upduino_v2 import UpduinoV2Platform
__all__ = ["SRAMSoC"]
class SRAMSoC(CPUSoC, Elaboratable):
def __init__(self, *, reset_addr, clk_freq,
rom_addr, rom_size,
ram_addr, ram_size,
uart_addr, uart_divisor, uart_pins,
timer_addr, timer_width):
self._arbiter = wishbone.Arbiter(addr_width=30, data_width=32, granularity=8,
features={"cti", "bte"})
self._decoder = wishbone.Decoder(addr_width=30, data_width=32, granularity=8,
features={"cti", "bte"})
self.cpu = MinervaCPU(reset_address=reset_addr)
self._arbiter.add(self.cpu.ibus)
self._arbiter.add(self.cpu.dbus)
self.rom = SRAMPeripheral(size=rom_size, writable=False)
self._decoder.add(self.rom.bus, addr=rom_addr)
self.ram = SRAMPeripheral(size=ram_size)
self._decoder.add(self.ram.bus, addr=ram_addr)
self.uart = AsyncSerialPeripheral(divisor=uart_divisor, pins=uart_pins)
self._decoder.add(self.uart.bus, addr=uart_addr)
self.timer = TimerPeripheral(width=timer_width)
self._decoder.add(self.timer.bus, addr=timer_addr)
self.intc = GenericInterruptController(width=len(self.cpu.ip))
self.intc.add_irq(self.timer.irq, 0)
self.intc.add_irq(self.uart .irq, 1)
self.memory_map = self._decoder.bus.memory_map
self.clk_freq = clk_freq
def elaborate(self, platform):
m = Module()
m.submodules.arbiter = self._arbiter
m.submodules.cpu = self.cpu
m.submodules.decoder = self._decoder
m.submodules.rom = self.rom
m.submodules.ram = self.ram
m.submodules.uart = self.uart
m.submodules.timer = self.timer
m.submodules.intc = self.intc
m.d.comb += [
self._arbiter.bus.connect(self._decoder.bus),
self.cpu.ip.eq(self.intc.ip),
]
return m
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--baudrate", type=int,
default=9600,
help="UART baudrate (default: 9600)")
args = parser.parse_args()
# here will modify paltform only target for upduino_v2
platform = UpduinoV2Platform()
uart_divisor = int(platform.default_clk_frequency // args.baudrate)
uart_pins = platform.request("uart", 0)
soc = SRAMSoC(
reset_addr=0x00000000, clk_freq=int(platform.default_clk_frequency),
rom_addr=0x00000000, rom_size=0x1000,
ram_addr=0x00004000, ram_size=0x1000,
uart_addr=0x00005000, uart_divisor=uart_divisor, uart_pins=uart_pins,
timer_addr=0x00006000, timer_width=32,
)
# disable soc build/init only for Msys-mingw64
soc.build(do_build=False, do_init=False)
platform.build(soc, do_program=True)
Connect upduino_v2 to computer then start building example soc by run: