From db937403ec9aff71ba8c17f68b62ea40a575f51c Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 18 Jan 2020 10:02:07 +1100 Subject: [PATCH] Initial support for ghdl synthesis A first pass at ghdl synthesis using yosys and nextpnr. It runs hello world or micropython if the FPGA has enough block RAM (eg ECP5 85F). The hello world testcase also loops UART rx to tx in software (ie not a hardware loopback). It uses Docker images, so no software needs to be installed. If you prefer podman you can use that too. Edit Makefile.synth to configure your FPGA, JTAG device etc. To build: make -f Makefile.synth and to program: make -f Makefile.synth prog A few issues: We need to add PLL support. Right now Microwatt runs at whatever the external clock frequency is and the baud rate gets scaled by how far off 50MHz it is. This means on the ecp5-evn with a 12 MHz clock rate the baud rate is a quite strange 27650 (115200 * 50 / 12). On my OrangeCrab with a 50MHz clock the UART is 115200. It uses a large amount of resources, way more than it should. There are still some ghdl/yosys issues to be sorted out. Signed-off-by: Anton Blanchard --- Makefile.synth | 77 +++++++++++++++++++++++++++++++ constraints/ecp5-evn.lpf | 19 ++++++++ constraints/orange-crab.lpf | 19 ++++++++ openocd/LFE5U-25F.cfg | 1 + openocd/LFE5U-45F.cfg | 1 + openocd/LFE5U-85F.cfg | 1 + openocd/LFE5UM-25F.cfg | 1 + openocd/LFE5UM-45F.cfg | 1 + openocd/LFE5UM-85F.cfg | 1 + openocd/LFE5UM5G-25F.cfg | 1 + openocd/LFE5UM5G-45F.cfg | 1 + openocd/LFE5UM5G-85F.cfg | 1 + openocd/ecp5-evn.cfg | 13 ++++++ openocd/olimex-arm-usb-tiny-h.cfg | 17 +++++++ 14 files changed, 154 insertions(+) create mode 100644 Makefile.synth create mode 100644 constraints/ecp5-evn.lpf create mode 100644 constraints/orange-crab.lpf create mode 100644 openocd/LFE5U-25F.cfg create mode 100644 openocd/LFE5U-45F.cfg create mode 100644 openocd/LFE5U-85F.cfg create mode 100644 openocd/LFE5UM-25F.cfg create mode 100644 openocd/LFE5UM-45F.cfg create mode 100644 openocd/LFE5UM-85F.cfg create mode 100644 openocd/LFE5UM5G-25F.cfg create mode 100644 openocd/LFE5UM5G-45F.cfg create mode 100644 openocd/LFE5UM5G-85F.cfg create mode 100644 openocd/ecp5-evn.cfg create mode 100644 openocd/olimex-arm-usb-tiny-h.cfg diff --git a/Makefile.synth b/Makefile.synth new file mode 100644 index 0000000..1e12537 --- /dev/null +++ b/Makefile.synth @@ -0,0 +1,77 @@ +# Use local tools +#GHDLSYNTH = ghdl.so +#YOSYS = yosys +#NEXTPNR = nextpnr-ecp5 +#ECPPACK = ecppack +#OPENOCD = openocd + +# Use Docker images +DOCKER=docker +#DOCKER=podman +# +PWD = $(shell pwd) +DOCKERARGS = run --rm -v $(PWD):/src -w /src +# +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 + + +# Hello world +GHDL_IMAGE_GENERICS=-gMEMORY_SIZE=8192 -gRAM_INIT_FILE=hello_world/hello_world.hex + +# Micropython +#GHDL_IMAGE_GENERICS=-gMEMORY_SIZE=393216 -gRAM_INIT_FILE=micropython/firmware.hex + + +# OrangeCrab with ECP85 +#GHDL_TARGET_GENERICS=-gRESET_LOW=true -gCLK_INPUT=50000000 -gCLK_FREQUENCY=50000000 +#LPF=constraints/orange-crab.lpf +#PACKAGE=CSFBGA285 +#NEXTPNR_FLAGS=--um5g-85k --freq 50 +#OPENOCD_JTAG_CONFIG=openocd/olimex-arm-usb-tiny-h.cfg +#OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg + +# ECP5-EVN +GHDL_TARGET_GENERICS=-gRESET_LOW=true -gCLK_INPUT=12000000 -gCLK_FREQUENCY=12000000 +LPF=constraints/ecp5-evn.lpf +PACKAGE=CABGA381 +NEXTPNR_FLAGS=--um5g-85k --freq 12 +OPENOCD_JTAG_CONFIG=openocd/ecp5-evn.cfg +OPENOCD_DEVICE_CONFIG=openocd/LFE5UM5G-85F.cfg + +VHDL_FILES = wishbone_types.vhdl utils.vhdl fpga/main_bram.vhdl +VHDL_FILES += wishbone_bram_wrapper.vhdl decode_types.vhdl common.vhdl +VHDL_FILES += fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd wishbone_arbiter.vhdl +VHDL_FILES += dmi_dtm_dummy.vhdl wishbone_debug_master.vhdl helpers.vhdl +VHDL_FILES += loadstore1.vhdl crhelpers.vhdl writeback.vhdl ppc_fx_insns.vhdl +VHDL_FILES += countzero.vhdl insn_helpers.vhdl rotator.vhdl logical.vhdl +VHDL_FILES += execute1.vhdl fetch1.vhdl gpr_hazard.vhdl cr_hazard.vhdl +VHDL_FILES += control.vhdl decode2.vhdl cr_file.vhdl cache_ram.vhdl plru.vhdl +VHDL_FILES += dcache.vhdl core_debug.vhdl multiply.vhdl icache.vhdl fetch2.vhdl +VHDL_FILES += register_file.vhdl decode1.vhdl divider.vhdl core.vhdl soc.vhdl +VHDL_FILES += fpga/soc_reset.vhdl fpga/clk_gen_bypass.vhd fpga/toplevel.vhdl + +all: microwatt.bit + +microwatt.json: $(VHDL_FILES) + $(YOSYS) -m $(GHDLSYNTH) -p "ghdl --std=08 $(GHDL_IMAGE_GENERICS) $(GHDL_TARGET_GENERICS) $(VHDL_FILES) -e toplevel; synth_ecp5 -json $@" + +microwatt_out.config: microwatt.json $(LPF) + $(NEXTPNR) --json $< --lpf $(LPF) --textcfg $@ $(NEXTPNR_FLAGS) --package $(PACKAGE) + +microwatt.bit: microwatt_out.config + $(ECPPACK) --svf microwatt.svf $< $@ + +microwatt.svf: microwatt.bit + +prog: microwatt.svf + $(OPENOCD) -f $(OPENOCD_JTAG_CONFIG) -f $(OPENOCD_DEVICE_CONFIG) -c "transport select jtag; init; svf $<; exit" + +clean: + @rm -f work-obj08.cf *.bit *.json *.svf *.config + +.PHONY: clean prog +.PRECIOUS: microwatt.json microwatt_out.config microwatt.bit diff --git a/constraints/ecp5-evn.lpf b/constraints/ecp5-evn.lpf new file mode 100644 index 0000000..6ff60ce --- /dev/null +++ b/constraints/ecp5-evn.lpf @@ -0,0 +1,19 @@ +LOCATE COMP "ext_clk" SITE "A10"; +IOBUF PORT "ext_clk" IO_TYPE=LVCMOS33; + +LOCATE COMP "ext_rst" SITE "P4"; +IOBUF PORT "rst" IO_TYPE=LVCMOS33; + +LOCATE COMP "uart0_txd" SITE "P3"; +LOCATE COMP "uart0_rxd" SITE "P2"; + +IOBUF PORT "uart0_txd" IO_TYPE=LVCMOS33; +IOBUF PORT "uart0_rxd" IO_TYPE=LVCMOS33; + +LOCATE COMP "led_a" SITE "A13"; +LOCATE COMP "led_b" SITE "A12"; +LOCATE COMP "led_c" SITE "B19"; + +IOBUF PORT "led_a" IO_TYPE=LVCMOS25; +IOBUF PORT "led_b" IO_TYPE=LVCMOS25; +IOBUF PORT "led_c" IO_TYPE=LVCMOS25; diff --git a/constraints/orange-crab.lpf b/constraints/orange-crab.lpf new file mode 100644 index 0000000..253d8d2 --- /dev/null +++ b/constraints/orange-crab.lpf @@ -0,0 +1,19 @@ +LOCATE COMP "ext_clk" SITE "A9"; +IOBUF PORT "ext_clk" IO_TYPE=LVCMOS33; + +LOCATE COMP "ext_rst" SITE "J2"; +IOBUF PORT "ext_rst" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4; + +LOCATE COMP "uart0_txd" SITE "N17"; +LOCATE COMP "uart0_rxd" SITE "M18"; + +IOBUF PORT "uart0_txd" IO_TYPE=LVCMOS25; +IOBUF PORT "uart0_rxd" IO_TYPE=LVCMOS25; + +LOCATE COMP "led_a" SITE "V17"; +LOCATE COMP "led_b" SITE "T17"; +LOCATE COMP "led_c" SITE "J3"; + +IOBUF PORT "led_a" IO_TYPE=LVCMOS25; +IOBUF PORT "led_b" IO_TYPE=LVCMOS25; +IOBUF PORT "led_c" IO_TYPE=LVCMOS25; diff --git a/openocd/LFE5U-25F.cfg b/openocd/LFE5U-25F.cfg new file mode 100644 index 0000000..047161a --- /dev/null +++ b/openocd/LFE5U-25F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043 diff --git a/openocd/LFE5U-45F.cfg b/openocd/LFE5U-45F.cfg new file mode 100644 index 0000000..7400d97 --- /dev/null +++ b/openocd/LFE5U-45F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x41112043 diff --git a/openocd/LFE5U-85F.cfg b/openocd/LFE5U-85F.cfg new file mode 100644 index 0000000..98cf6e6 --- /dev/null +++ b/openocd/LFE5U-85F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x41113043 diff --git a/openocd/LFE5UM-25F.cfg b/openocd/LFE5UM-25F.cfg new file mode 100644 index 0000000..b06c81f --- /dev/null +++ b/openocd/LFE5UM-25F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x01111043 diff --git a/openocd/LFE5UM-45F.cfg b/openocd/LFE5UM-45F.cfg new file mode 100644 index 0000000..34afc6e --- /dev/null +++ b/openocd/LFE5UM-45F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x01112043 diff --git a/openocd/LFE5UM-85F.cfg b/openocd/LFE5UM-85F.cfg new file mode 100644 index 0000000..f447f38 --- /dev/null +++ b/openocd/LFE5UM-85F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x01113043 diff --git a/openocd/LFE5UM5G-25F.cfg b/openocd/LFE5UM5G-25F.cfg new file mode 100644 index 0000000..f327706 --- /dev/null +++ b/openocd/LFE5UM5G-25F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x81111043 diff --git a/openocd/LFE5UM5G-45F.cfg b/openocd/LFE5UM5G-45F.cfg new file mode 100644 index 0000000..9d570db --- /dev/null +++ b/openocd/LFE5UM5G-45F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x81112043 diff --git a/openocd/LFE5UM5G-85F.cfg b/openocd/LFE5UM5G-85F.cfg new file mode 100644 index 0000000..94b1aa3 --- /dev/null +++ b/openocd/LFE5UM5G-85F.cfg @@ -0,0 +1 @@ +jtag newtap ecp5 tap -irlen 8 -expected-id 0x81113043 diff --git a/openocd/ecp5-evn.cfg b/openocd/ecp5-evn.cfg new file mode 100644 index 0000000..a4cde22 --- /dev/null +++ b/openocd/ecp5-evn.cfg @@ -0,0 +1,13 @@ +# this supports ECP5 Evaluation Board + +interface ftdi +ftdi_device_desc "Lattice ECP5 Evaluation Board" +ftdi_vid_pid 0x0403 0x6010 +# channel 1 does not have any functionality +ftdi_channel 0 +# just TCK TDI TDO TMS, no reset +ftdi_layout_init 0xfff8 0xfffb +reset_config none + +# default speed +adapter_khz 5000 diff --git a/openocd/olimex-arm-usb-tiny-h.cfg b/openocd/olimex-arm-usb-tiny-h.cfg new file mode 100644 index 0000000..e31515c --- /dev/null +++ b/openocd/olimex-arm-usb-tiny-h.cfg @@ -0,0 +1,17 @@ +# +# Olimex ARM-USB-TINY-H +# +# http://www.olimex.com/dev/arm-usb-tiny-h.html +# + +interface ftdi +ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" +ftdi_vid_pid 0x15ba 0x002a + +ftdi_layout_init 0x0808 0x0a1b +ftdi_layout_signal nSRST -oe 0x0200 +ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 +ftdi_layout_signal LED -data 0x0800 + +# default speed +adapter_khz 5000