diff --git a/Makefile b/Makefile index 2a76672..618c3ca 100644 --- a/Makefile +++ b/Makefile @@ -3,14 +3,16 @@ DOCKER=docker #DOCKER=podman PWD = $(shell pwd) +USBDEVICE ?= /dev/bus/usb DOCKERARGS = run --rm -v $(PWD):/src -w /src VERILATORARGS = run --name verilator --hostname verilator --rm -it --entrypoint= -v $(PWD):/work -w /work -YOSYS = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta yosys -NEXTPNR = $(DOCKER) $(DOCKERARGS) ghdl/synth:nextpnr-ecp5 nextpnr-ecp5 -ECPPACK = $(DOCKER) $(DOCKERARGS) ghdl/synth:trellis ecppack -OPENOCD = $(DOCKER) $(DOCKERARGS) --device /dev/bus/usb ghdl/synth:prog openocd -VERILATOR = $(DOCKER) $(VERILATORARGS) verilator/verilator +YOSYS = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta yosys +NEXTPNR = $(DOCKER) $(DOCKERARGS) ghdl/synth:nextpnr-ecp5 nextpnr-ecp5 +ECPPACK = $(DOCKER) $(DOCKERARGS) ghdl/synth:trellis ecppack +OPENOCD_DEF = $(DOCKER) $(DOCKERARGS) --privileged --device $(USBDEVICE):/dev/bus/usb ghdl/synth:prog openocd +OPENOCD_ULX3S = $(DOCKER) $(DOCKERARGS) --privileged --device $(USBDEVICE):/dev/bus/usb alpin3/ulx3s openocd +VERILATOR = $(DOCKER) $(VERILATORARGS) verilator/verilator # Uncomment to use local tools for synthesis #YOSYS = yosys @@ -34,14 +36,25 @@ LPF=constraints/ecp5-evn.lpf PLL=pll/pll_ehxplll.v PACKAGE=CABGA381 NEXTPNR_FLAGS=--um5g-85k --freq 12 +OPENOCD=$(OPENOCD_DEF) OPENOCD_JTAG_CONFIG=openocd/ecp5-evn.cfg OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg +else ifeq ($(ECP5_BOARD),ulx3s) +# Radiona ULX3S with ECP5-85F +LPF=constraints/ecp5-ulx3s.lpf +PLL=pll/pll_ehxplll_25MHz.v +PACKAGE=CABGA381 +NEXTPNR_FLAGS=--85k --freq 25 +OPENOCD=$(OPENOCD_ULX3S) +OPENOCD_JTAG_CONFIG=openocd/ft231x.cfg +OPENOCD_DEVICE_CONFIG=openocd/LFE5U-85F.cfg else ifeq ($(ECP5_BOARD),orangecrab) # OrangeCrab with ECP85 LPF=constraints/orange-crab.lpf PLL=pll/pll_bypass.v PACKAGE=CSFBGA285 NEXTPNR_FLAGS=--um5g-85k --freq 50 +OPENOCD=$(OPENOCD_DEF) OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg else ifeq ($(ECP5_BOARD),colorlight) @@ -50,6 +63,7 @@ LPF=constraints/colorlight_5A-75B.lpf PLL=pll/pll_ehxplll_25MHz.v PACKAGE=CABGA256 NEXTPNR_FLAGS=--25k --freq 25 +OPENOCD=$(OPENOCD_DEF) OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg OPENOCD_DEVICE_CONFIG=openocd/LFE5U-25F.cfg else @@ -82,10 +96,10 @@ dockerlator: chiselwatt # Mask exit code from verilator on Make @$(VERILATOR) bash || true -synth: test-vars chiselwatt.bit +synth: check-board-vars chiselwatt.bit -test-vars: - @test -n "$(LPF)" || (echo "If synthesizing, use \"synth\" target with ECP5_BOARD variable to either \"evn\", \"orangecrab\", \"colorlight\"\n" ; exit 1) +check-board-vars: + @test -n "$(LPF)" || (echo "If synthesizing or programming, use \"synth\" or \"prog\" targets with ECP5_BOARD variable to either \"evn\", \"ulx3s\", \"orangecrab\", \"colorlight\"\n" ; exit 1) chiselwatt.json: insns.hex $(verilog_files) $(PLL) toplevel.v $(YOSYS) -p "read_verilog -sv $(verilog_files) $(PLL) toplevel.v; synth_ecp5 -json $@ -top toplevel" @@ -98,8 +112,8 @@ chiselwatt.bit: chiselwatt_out.config chiselwatt.svf: chiselwatt.bit -prog: chiselwatt.svf - $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf $<; exit" +prog: check-board-vars chiselwatt.svf + $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf chiselwatt.svf; exit" clean: @rm -f Core.fir firrtl_black_box_resource_files.f Core.v Core.anno.json MemoryBlackBox.v diff --git a/README.md b/README.md index 75a034d..014259d 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ ln -s hello_world/hello_world.hex insns.hex The `Makefile` currently supports the following FPGA boards by defining the `ECP5_BOARD` parameter on make: * Lattice [ECP5 Evaluation Board](http://www.latticesemi.com/ecp5-evaluation) - `evn` +* Radiona [ULX3S](https://radiona.org/ulx3s/) - `ulx3s` * Greg Davill [Orangecrab](https://github.com/gregdavill/OrangeCrab) - `orangecrab` * Q3k [Colorlight](https://github.com/q3k/chubby75/tree/master/5a-75b) - `colorlight` @@ -107,9 +108,17 @@ and to program the FPGA: ```sh make ECP5_BOARD=evn prog + +# or if your USB device has a different path, pass it on USBDEVICE, like: + +make ECP5_BOARD=evn USBDEVICE=/dev/tty.usbserial-120001 prog ``` -If you connect to the serial port of the FPGA at 115200 8n1, you should see "Hello World" +Programming using OpenOCD on Docker does not work on Docker Desktop for Mac since the container is run in a Linux VM and can not see the physical devices connected to the MacOS. + +For the ULX3S board, the current OpenOCD does not support ft232 protocol so to program it, download [ujprog](https://github.com/emard/ulx3s-bin/tree/master/usb-jtag) for your platform and program using `./ujprog chiselwatt.bit` or to persist in the flash, `./ujprog -j FLASH chiselwatt.bit`. + +After programming, if you connect to the serial port of the FPGA at 115200 8n1, you should see "Hello World" and after that all input will be echoed to the output. On Linux, picocom can be used. Another option below is a simple python script. @@ -134,16 +143,16 @@ Then link in the micropython image: ln -s micropython/firmware.hex insns.hex ``` -For example, to build for the Orangecrab, run: +For example, to build for the ULX3S, run: ```sh -make ECP5_BOARD=orangecrab synth` +make ECP5_BOARD=ulx3s synth` ``` and to program the FPGA: ```sh -make ECP5_BOARD=orangecrab prog +make ECP5_BOARD=ulx3s prog ``` ## Simple Python script for reading USB serial port diff --git a/chiselwatt.core b/chiselwatt.core index d8ded00..9208402 100644 --- a/chiselwatt.core +++ b/chiselwatt.core @@ -31,6 +31,11 @@ filesets: - constraints/ecp5-evn.lpf : {file_type : LPF} - pll/pll_ehxplll.v : {file_type : verilogSource} + ecp5-ulx3s: + files: + - constraints/ecp5-ulx3s.lpf : {file_type : LPF} + - pll/pll_ehxplll_25MHz.v : {file_type : verilogSource} + targets: cmod_a7-35: default_tool: vivado @@ -69,6 +74,13 @@ targets: diamond: {part: LFE5U-85F-8BG381I} toplevel : toplevel + ecp5-ulx3s: + default_tool: diamond + filesets: [core, ecp5-ulx3s] + tools: + diamond: {part: LFE5U-85F-8BG381I} + toplevel : toplevel + parameters: RESET_LOW: datatype : bool diff --git a/constraints/ecp5-ulx3s.lpf b/constraints/ecp5-ulx3s.lpf new file mode 100644 index 0000000..77c9469 --- /dev/null +++ b/constraints/ecp5-ulx3s.lpf @@ -0,0 +1,20 @@ +LOCATE COMP "clock" SITE "G2"; +IOBUF PORT "clock" PULLMODE=NONE IO_TYPE=LVCMOS33; +FREQUENCY PORT "clock" 25 MHZ; + +LOCATE COMP "reset" SITE "D6"; +IOBUF PORT "reset" PULLMODE=UP IO_TYPE=LVCMOS33; + +LOCATE COMP "io_tx" SITE "L4"; +LOCATE COMP "io_rx" SITE "M1"; + +IOBUF PORT "io_tx" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "io_rx" PULLMODE=UP IO_TYPE=LVCMOS33; + +LOCATE COMP "io_terminate" SITE "B2"; +LOCATE COMP "io_ledB" SITE "C2"; +LOCATE COMP "io_ledC" SITE "C1"; + +IOBUF PORT "io_terminate" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "io_ledB" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; +IOBUF PORT "io_ledC" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; \ No newline at end of file diff --git a/openocd/ecp5-ulx3s.cfg b/openocd/ecp5-ulx3s.cfg new file mode 100644 index 0000000..dfb2685 --- /dev/null +++ b/openocd/ecp5-ulx3s.cfg @@ -0,0 +1,17 @@ +telnet_port 4444 +gdb_port 3333 + +# JTAG TAPs +#12k +# jtag newtap lfe5 tap -expected-id 0x21111043 -irlen 8 -irmask 0xFF -ircapture 0x5 +#25k +#jtag newtap lfe5 tap -expected-id 0x41111043 -irlen 8 -irmask 0xFF -ircapture 0x5 +#45k +#jtag newtap lfe5 tap -expected-id 0x41112043 -irlen 8 -irmask 0xFF -ircapture 0x5 +#85k +jtag newtap lfe5 tap -expected-id 0x41113043 -irlen 8 -irmask 0xFF -ircapture 0x5 + +init +scan_chain +svf -tap lfe5.tap -quiet -progress chiselwatt.svf +shutdown \ No newline at end of file diff --git a/openocd/ft231x.cfg b/openocd/ft231x.cfg new file mode 100644 index 0000000..253b450 --- /dev/null +++ b/openocd/ft231x.cfg @@ -0,0 +1,11 @@ +interface ft232r +ft232r_vid_pid 0x0403 0x6015 +# ULX3S specific GPIO setting +ft232r_tck_num DSR +ft232r_tms_num DCD +ft232r_tdi_num RI +ft232r_tdo_num CTS +# trst/srst are not used but must have different values than above +ft232r_trst_num RTS +ft232r_srst_num DTR +adapter_khz 1000 \ No newline at end of file