1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
######################################################
# FPGA make library #
# Original author: Michael Buesch <m@bues.ch> #
# This code is Public Domain. #
# Version 1.0 #
######################################################
# Tools.
YOSYS := yosys
NEXTPNR := nextpnr
ICEPACK := icepack
ICETIME := icetime
ICEPLL := icepll
TINYPROG := tinyprog
PYTHON := python3
CAT := cat
GREP := grep
PRINTF := printf
RM := rm
FALSE := false
TR := tr
TEST := test
TOUCH := touch
GIT := git
# Target name transformations.
TARGET_NAME := $(TARGET)_$(NAME)
TARGET_LOWER := $(shell $(PRINTF) '%s' '$(TARGET)' | $(TR) A-Z a-z)
TARGET_UPPER := $(shell $(PRINTF) '%s' '$(TARGET)' | $(TR) a-z A-Z)
# Target specific options and commands.
ifeq ($(TARGET_LOWER),tinyfpga_bx)
YOSYS_SYNTH_CMD = 'synth_ice40 -top $(TOP_MODULE) -json $(patsubst %.blif,%.json,$@) -blif $@'
PNR_PACKAGE := cm81
NEXTPNR_ARCH := ice40
DEVICE := lp8k
else
$(error TARGET $(TARGET) is unknown)
endif
# Log files.
YOSYS_LOG := $(TARGET_NAME)_yosys.log
NEXTPNR_LOG := $(TARGET_NAME)_nextpnr.log
ICEPACK_LOG := $(TARGET_NAME)_icepack.log
ICETIME_LOG := $(TARGET_NAME)_icetime.log
LOG = >$(1) 2>&1 || ( $(CAT) $(1); $(FALSE) )
# PLL sanity check.
ifneq ($(PLL_MOD_V_FILE),)
ifeq ($(PLL_HZ),)
$(error PLL_HZ is not defined)
endif
endif
# Clock speeds.
ifeq ($(TARGET_LOWER),tinyfpga_bx)
CLK_HZ := 16000000
ifeq ($(PLL_MOD_V_FILE),)
PLL_HZ := $(CLK_HZ)
else
CLK_MHZ := $(shell expr $(CLK_HZ) / 1000000)
PLL_MHZ := $(shell expr $(PLL_HZ) / 1000000)
$(PLL_MOD_V_FILE):
$(ICEPLL) -q -f $@ -m -n pll_module -i $(CLK_MHZ) -o $(PLL_MHZ)
endif
endif
# MyHDL to Verilog
%.v: %.py $(wildcard *.py) $(EXTRA_DEP_PY)
$(PYTHON) -B $<
# Synthesis
%.blif: $(TOP_FILE) $(wildcard *.v) $(GENERATED_V) $(PLL_MOD_V_FILE) $(EXTRA_DEP_V)
$(YOSYS) -p 'read_verilog -DTARGET_$(TARGET_UPPER)=1 -DCLK_HZ=$(CLK_HZ) -DPLL_HZ=$(PLL_HZ) $(if $(filter-out 0,$(DEBUG)),-DDEBUG=1) $<' \
-p $(YOSYS_SYNTH_CMD) \
$(call LOG,$(YOSYS_LOG))
# Place and route
%.asc: $(PCF_FILE) %.blif
$(NEXTPNR)-$(NEXTPNR_ARCH) --$(DEVICE) --package $(PNR_PACKAGE) --json $(TARGET_NAME).json --pcf $< --asc $@ \
$(call LOG,$(NEXTPNR_LOG))
# Binary packing
%.bin: %.asc
ifeq ($(TARGET_LOWER),tinyfpga_bx)
$(ICEPACK) $< $@ $(call LOG,$(ICEPACK_LOG))
endif
# Report generation
%.rpt: %.asc %.bin
ifeq ($(TARGET_LOWER),tinyfpga_bx)
$(ICETIME) -d $(DEVICE) -p $(PCF_FILE) -m -t -r $@ $< \
$(call LOG,$(ICETIME_LOG))
-@$(PRINTF) '\n'
endif
-@$(GREP) -i -e 'Total' $@
-@$(GREP) -i -Ee 'Max frequency|Max delay' $(NEXTPNR_LOG)
-@$(PRINTF) '\n'
-@$(GREP) --color=auto -H -n -i -e 'Warning' $(YOSYS_LOG) $(NEXTPNR_LOG) $(ICEPACK_LOG)
-@$(PRINTF) '\n'
-@$(GREP) -A6 -i -e 'Device utilisation' $(NEXTPNR_LOG)
# Flashing
install: $(TARGET_NAME).bin
ifeq ($(TARGET_LOWER),tinyfpga_bx)
$(TINYPROG) -p $<
endif
# Rebooting
boot:
ifeq ($(TARGET_LOWER),tinyfpga_bx)
$(TINYPROG) -b
endif
# Cleanup
clean:
$(RM) -rf *.blif *.json *.asc *.bin *.rpt __pycache__ $(YOSYS_LOG) $(NEXTPNR_LOG) $(ICEPACK_LOG) $(ICETIME_LOG) $(GENERATED_V) $(PLL_MOD_V_FILE) $(CLEAN_FILES)
# Default goal
all: $(TARGET_NAME).bin $(TARGET_NAME).rpt
.DEFAULT_GOAL := all
.PHONY: all install boot clean
.PRECIOUS: %.json %.blif %.asc $(GENERATED_V)
|