diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..7e02ccd --- /dev/null +++ b/examples/README.md @@ -0,0 +1,34 @@ +# examples + +Simple examples showing the usage of this plugin. + +## Contents + +- *ecp5_versa*: Elaborate Mixed-Language ECP5 example with UART, I2C and PLL support. This shows how to include Verilog for synthesis +- *ice40hx8k*: Very simple LED demonstration +- *icestick/leds*: A lot of LED animations and examples +- *icestick/uart*: A loopback UART Transceiver module +- *icezum*: Small demo for the [IceZUM](https://github.com/FPGAwars/icezum) board + +## Usage + +```bash +make all +``` + +All examples use `makefile` for compilation. +Simply run `make` to generate a bitstream. +You can then program a board manually or using `make prog` +Programming from the docker container may only work on linux. +See the repository's main README for more details. + +In case you don't have all tools installed on your machine you can use tools from the official docker container. +Simply use `make USE_DOCKER=1`. +Be aware that currently only images for `amd64` exist. + +The makefiles are split up in a way that each example project only defines variables and imports the `tools.mk` and `common.mk` makefiles in this directory. +These contain all build targets. + +Note: these example project are somewhat opinionated with regard to style, structure, and usage. +Your own projects don't have to follow these examples. +The plugin can be adapted to virtually any yosys workflow. diff --git a/examples/common.mk b/examples/common.mk new file mode 100644 index 0000000..89af2a4 --- /dev/null +++ b/examples/common.mk @@ -0,0 +1,68 @@ +# Common makefile for GHDL synthesis + +PLUGIN_LIB = ../../library + +ifneq ($(VERILOG_FILES),) +MAYBE_READ_VERILOG = read_verilog $(VERILOG_FILES); +endif + +# agnostic synthesis +%.json: $(VHDL_SYN_FILES) + $(YOSYS) -m $(GHDLSYNTH) -p \ + "ghdl $(GHDL_FLAGS) $(GHDL_GENERICS) $^ -e $(TOPLEVEL); \ + $(MAYBE_READ_VERILOG) \ + synth_$(PLATFORM) \ + -top $(TOPLEVEL)$(TOPLEVEL_PARAMETER) -json $@" 2>&1 + +# ECP pouting +%.config: %.json + $(NEXTPNR) --json $< --lpf $(LPF_DEF) \ + --textcfg $@ $(NEXTPNR_FLAGS) --package $(PACKAGE) + +# ECP packing +%.svf: %.config + $(ECPPACK) --svf $*.svf $< $@ + +# ICE routing +%.asc: %.json + $(NEXTPNR) --$(DEVICE) --json $< \ + --package $(PACKAGE) --pcf $(PCF_DEF) \ + --asc $@ $(NEXTPNR_FLAGS) + +# ICE packing +%.bin: %.asc + $(ICEPACK) $< $@ + +ifeq ($(PLATFORM), ecp5) + +# ECP5 bitstream target +bitstream: $(PROJ).svf + +# ECP programming +prog: $(PROJ).svf + $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) \ + -c "transport select jtag; init; svf $<; exit" + +else ifeq ($(PLATFORM), ice40) + +# ICE bitstream target +bitstream: report $(PROJ).bin + +# ICE programming +prog: $(PROJ).bin + $(ICEPROG) $< + +# ICE timing report +report: $(PROJ).asc + $(ICETIME) -d $(DEVICE) -mtr $@.txt $< +endif + +clean: + rm -rf ./*.json ./*.asc ./*.bin ./report.txt ./*.work-obj93.cf \ + ./*.work-obj08.cf ./*.config ./*.svf $(LOCAL_LIB) + +all: bitstream + +.PRECIOUS: %.json %.config +.PHONY: bitstream report clean all +.DEFAULT: all diff --git a/examples/docker.mk b/examples/docker.mk deleted file mode 100644 index dd9acc2..0000000 --- a/examples/docker.mk +++ /dev/null @@ -1,17 +0,0 @@ -# Use Docker images -DOCKER=docker -#DOCKER=podman -# -PWD = $(shell pwd) -DOCKERARGS = run --rm -v $(PWD)/../..:/src \ - -w /src/examples/$(notdir $(PWD)) - - -GHDL = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta ghdl -GHDLSYNTH = ghdl -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 - - diff --git a/examples/ecp5_versa/Makefile b/examples/ecp5_versa/Makefile index 2b54e17..70a0975 100644 --- a/examples/ecp5_versa/Makefile +++ b/examples/ecp5_versa/Makefile @@ -1,50 +1,44 @@ -LIB = ../../library -GHDL ?= ghdl +USE_DOCKER?= -GHDL_FLAGS = -Plib +PROJ ?= versa_ecp5_top +TOPLEVEL ?= versa_ecp5_top -CLK_FREQ = 25000000 +VHDL_SYN_FILES = versa_ecp5_top.vhdl pll_mac.vhd +VHDL_SYN_FILES += soc_iomap_pkg.vhdl +VHDL_SYN_FILES += uart.vhdl uart_tx.vhdl uart_rx.vhdl fifobuf.vhdl -GHDL_GENERICS=-gCLK_FREQUENCY=$(CLK_FREQ) -LPF = versa_ecp5.lpf +LPF_DEF = versa_ecp5.lpf PACKAGE = CABGA381 + NEXTPNR_FLAGS = --um5g-45k --freq 100 NEXTPNR_FLAGS += --lpf-allow-unconstrained + OPENOCD_JTAG_CONFIG = ../../openocd/ecp5-versa.cfg OPENOCD_DEVICE_CONFIG = ../../openocd/LFE5UM5G-45F.cfg -WORKDIR = work -# Files to synthesize: -VHDL_SYN_FILES = versa_ecp5_top.vhdl pll_mac.vhd -VHDL_SYN_FILES += soc_iomap_pkg.vhdl -VHDL_SYN_FILES += uart.vhdl uart_tx.vhdl uart_rx.vhdl fifobuf.vhdl +VERILOG_FILES = $(PLUGIN_LIB)/wrapper/primitives.v +VERILOG_FILES += $(PLUGIN_LIB)/wrapper/bram.v -TOPLEVEL = versa_ecp5_top -TOPLEVEL_PARAMETER = +GHDL_FLAGS = -Plib +PLATFORM = ecp5 -VERILOG_FILES = $(LIB)/wrapper/primitives.v -VERILOG_FILES += $(LIB)/wrapper/bram.v +LOCAL_LIB=./lib -SVFFILE = versa_ecp5_top.svf -DEPENDENCIES = lib/ecp5um-std93.cf +include ../tools.mk +include ../common.mk -all: $(SVFFILE) +# this project requires verilog wrappers to enable vendor black-box components +# these are defined in project-root/library +# the following targets compile these wrappers into a project specific directory -include ../docker.mk -include ../ghdlsynth.mk +# NOTE: if you're using VHDL-2008 you MUST rename the file suffix to "-std08.cf" lib: mkdir $@ -lib/ecp5um-std93.cf: $(LIB)/ecp5u/components.vhdl | lib +$(LOCAL_LIB)/ecp5um-std93.cf: $(PLUGIN_LIB)/ecp5u/components.vhdl | lib $(GHDL) -i --workdir=$(dir $@) --work=ecp5um $< +DEPENDENCIES = $(LOCAL_LIB)/ecp5um-std93.cf pll_mac.vhd: $(DEPENDENCIES) - -prog: $(SVFFILE) - $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) \ - -c "transport select jtag; init; svf $<; exit" - -clean: - rm -fr lib work *.json *.svf *.config *-report.txt diff --git a/examples/ghdlsynth.mk b/examples/ghdlsynth.mk deleted file mode 100644 index d53a57c..0000000 --- a/examples/ghdlsynth.mk +++ /dev/null @@ -1,34 +0,0 @@ -# Common makefile for GHDL synthesis - -# Specify: -# -# VHDL_SYN_FILES = VHDL files for synthesis, unordered -# VERILOG_FILES = auxiliary verilog wrappers that might be needed -# PLATFORM: 'ecp5' for now -# TOPLEVEL: top level entity name -# TOPLEVEL_PARAMETER: top level entity name parameters, when passed a generic -# LPF: I/O constraints file - -PLATFORM ?= ecp5 - -ifneq ($(VERILOG_FILES),) -MAYBE_READ_VERILOG = read_verilog $(VERILOG_FILES); -endif - -%.json: $(VHDL_SYN_FILES) - $(YOSYS) -m $(GHDLSYNTH) -p \ - "ghdl $(GHDL_FLAGS) $(GHDL_GENERICS) $^ -e $(TOPLEVEL); \ - $(MAYBE_READ_VERILOG) \ - synth_$(PLATFORM) \ - -top $(TOPLEVEL)$(TOPLEVEL_PARAMETER) -json $@" 2>&1 | tee $*-report.txt - -%.config: %.json - $(NEXTPNR) --json $< --lpf $(LPF) \ - --textcfg $@ $(NEXTPNR_FLAGS) --package $(PACKAGE) - -%.svf: %.config - $(ECPPACK) --svf $*.svf $< $@ - - -.PRECIOUS: %.json %.config - diff --git a/examples/ice40hx8k/Makefile b/examples/ice40hx8k/Makefile new file mode 100644 index 0000000..8efb38c --- /dev/null +++ b/examples/ice40hx8k/Makefile @@ -0,0 +1,20 @@ + +USE_DOCKER?= + +PROJ ?= leds +TOPLEVEL ?= leds + +VHDL_SYN_FILES = leds.vhdl + +# choose one implementation +VHDL_SYN_FILES += spin1.vhdl +# VHDL_SYN_FILES += spin2.vhdl + +PCF_DEF = pinmap.pcf +PACKAGE = ct256 + +PLATFORM = ice40 +DEVICE = hx8k + +include ../tools.mk +include ../common.mk diff --git a/examples/icestick/leds/Makefile b/examples/icestick/leds/Makefile index 77a610d..9ecf2ed 100644 --- a/examples/icestick/leds/Makefile +++ b/examples/icestick/leds/Makefile @@ -1,4 +1,8 @@ -PROJ = blink + +USE_DOCKER?= + +# choose one project to build +PROJ ?= blink #PROJ = fixed1 #PROJ = multi1 #PROJ = multi2 @@ -9,26 +13,15 @@ PROJ = blink #PROJ = spin1 #PROJ = spin2 -PIN_DEF = leds.pcf -DEVICE = hx1k - -all: $(PROJ).bin +TOPLEVEL ?= leds -%.json: leds.vhdl %.vhdl - yosys -m ghdl -p 'ghdl $^ -e leds; synth_ice40 -json $@' +VHDL_SYN_FILES = leds.vhdl ./*.vhdl -%.asc: %.json - nextpnr-ice40 --package $(DEVICE) --pcf $(PIN_DEF) --json $< --asc $@ +PCF_DEF = leds.pcf +PACKAGE = tq144 -%.bin: %.asc - icepack $< $@ - -prog: $(PROJ).bin - iceprog $< - -clean: - rm -f $(PROJ).json $(PROJ).asc $(PROJ).bin - -.SECONDARY: +PLATFORM = ice40 +DEVICE = hx1k -.PHONY: all prog clean +include ../../tools.mk +include ../../common.mk diff --git a/examples/icestick/uart/Makefile b/examples/icestick/uart/Makefile new file mode 100644 index 0000000..02d5270 --- /dev/null +++ b/examples/icestick/uart/Makefile @@ -0,0 +1,18 @@ + +USE_DOCKER?= + +PROJ ?= uart +TOPLEVEL ?= uart_top + +VHDL_SYN_FILES = ./hdl/*.vhd + +PCF_DEF = ./syn/constraints/uart.pcf +PACKAGE = tq144 + +PLATFORM = ice40 +DEVICE = hx1k + +NEXTPNR_FLAGS=--pcf-allow-unconstrained + +include ../../tools.mk +include ../../common.mk diff --git a/examples/icestick/uart/README.md b/examples/icestick/uart/README.md index b53def6..11a9731 100755 --- a/examples/icestick/uart/README.md +++ b/examples/icestick/uart/README.md @@ -7,5 +7,5 @@ Configuration: 115200 8N1 - syn: Contains the scripts and constraints for synthesis. ## Usage -- `cd syn && ./synth.sh` -- configure and open putty or another serial terminal and type something \ No newline at end of file +- `make all prog` +- configure and open putty or another serial terminal and type something diff --git a/examples/icestick/uart/syn/synth.sh b/examples/icestick/uart/syn/synth.sh deleted file mode 100755 index 884f1b6..0000000 --- a/examples/icestick/uart/syn/synth.sh +++ /dev/null @@ -1,15 +0,0 @@ -set -e - -ROOT="$(pwd)/.." - -rm -rf build -mkdir -p build -cd build - -ghdl -a "$ROOT"/hdl/uart_rx.vhd -ghdl -a "$ROOT"/hdl/uart_tx.vhd -ghdl -a "$ROOT"/hdl/uart_top.vhd -yosys -m ghdl -p 'ghdl uart_top; synth_ice40 -json uart_top.json' -nextpnr-ice40 --hx1k --json uart_top.json --pcf ../constraints/uart.pcf --asc uart_top.asc --pcf-allow-unconstrained -icepack uart_top.asc uart_top.bin -iceprog uart_top.bin diff --git a/examples/icezum/Makefile b/examples/icezum/Makefile index ab6f5d7..a109541 100644 --- a/examples/icezum/Makefile +++ b/examples/icezum/Makefile @@ -1,23 +1,16 @@ -PROJ ?= blink -PIN_DEF = icezum.pcf -DEVICE = hx1k - -all: report bin -json: $(PROJ).vhdl - yosys -m ghdl -p 'ghdl $(PROJ).vhdl -e $(PROJ); synth_ice40 -json $@' +USE_DOCKER?= -asc: $(PIN_DEF) json - nextpnr-ice40 --$(DEVICE) --json json --pcf $(PIN_DEF) --asc $@ +PROJ ?= blink +TOPLEVEL ?= blink -bin: asc - icepack $< $@ +VHDL_SYN_FILES = ./*.vhdl -report: asc - icetime -d $(DEVICE) -mtr $@ $< +PCF_DEF = icezum.pcf +PACKAGE = tq144 -clean: - rm -f json asc bin report work-obj93.cf +PLATFORM = ice40 +DEVICE = hx1k -.SECONDARY: -.PHONY: all prog clean +include ../tools.mk +include ../common.mk diff --git a/examples/tools.mk b/examples/tools.mk new file mode 100644 index 0000000..363a550 --- /dev/null +++ b/examples/tools.mk @@ -0,0 +1,36 @@ + +ifneq ($(USE_DOCKER),) +# Use Docker tools + +DOCKER=docker +#DOCKER=podman + +PWD = $(shell pwd) +DOCKERARGS = run --rm -v $(PWD)/../..:/src \ + -w /src/examples/$(notdir $(PWD)) + +GHDL = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta ghdl +GHDLSYNTH = ghdl +YOSYS = $(DOCKER) $(DOCKERARGS) ghdl/synth:beta yosys +NEXTPNR = $(DOCKER) $(DOCKERARGS) ghdl/synth:nextpnr-$(PLATFORM) nextpnr-$(PLATFORM) +ECPPACK = $(DOCKER) $(DOCKERARGS) ghdl/synth:trellis ecppack +ICEPACK = $(DOCKER) $(DOCKERARGS) ghdl/synth:trellis icepack +OPENOCD = $(DOCKER) $(DOCKERARGS) --device /dev/bus/usb ghdl/synth:prog openocd + +ICEPORG = # ? +ICETIME = # ? + +else +# Use local tools + +GHDL = ghdl +GHDLSYNTH = ghdl +YOSYS = yosys +NEXTPNR = nextpnr-$(PLATFORM) +ECPPACK = ecppack +ICEPACK = icepack +OPENOCD = openocd +ICEPROG = iceprog +ICETIME = icetime + +endif