.. | ||
board_tops | ||
boards | ||
constraints | ||
devices | ||
.gitignore | ||
common.mk | ||
filesets.mk | ||
Makefile | ||
PnR_Bit.mk | ||
README.md | ||
synthesis.mk | ||
tools.mk |
Exemplary FPAG Board Setups - Using Open Source Toolchains
This folder provides the infrastructure for generating bitstream for various FPGAs using open-source toolchains. Synthesis is based on ghdl-yosys.
ℹ️ Note that the provided setups just implement very basic SoC configurations. These setups are intended as minimal example (how to synthesize the processor) for a given FPGA + board that can be used as starting point to build more complex user-defined SoCs.
Folder Structure
.
: Main makefile (main entry point) and partial-makefiles for synthesis, place & route and bitstream generationboards
: board-specific partial makefiles (used by main makefile "Makefile
") for generating bitstreamsboard_top
: board-specific top entities (board wrappers; may include FPGA-specific modules)constraints
: physical constraints (mainly pin mappings)devices
: FPGA-specific primitives and optimized processor modules (like memories)
Prerequisites
🚧 TODO 🚧
- local installation of the tools
- using containers
How To Run
🚧 TODO 🚧
The Makefile
in this folder is the main entry point. To run the whole process of synthesis, place & route and bitstream
generation run:
Prototype:
make BOARD=<FPGA_board> <System_Top_HDL>
Example:
make BOARD=Fomu Minimal
<FPGA_board>
specifies the actual FPGA board and implicitly sets the FPGA type. The currently supported FPGA board
targets are listed in the boards/
folder where each partial-makefile corresponds to a supported platform.
<System_Top_HDL>
is used to define the actual SoC top. Available SoCs are located in
rtl/processor_templates
.
Porting to a new FPGA or Board
This sections illustrates how to add a new basic setup for a specific FPGA and board. This tutorial used the iCEBreaker "MinimalBoot" setup as reference.
1. Setup a board- and FPGA-specific top entity
- Write a new top design unit that instantiates one of the provided processor templates from
rtl/processor_templates
. This new top unit can be a Verilog or VHDL file. - Optional: You can also include FPGA-specific primitives like PLLs or block RAMs (but keep it simple). These components
need to be added to a FPGA-specific library in
setups/osflow/devices
. - Try to keep the external IO at a minimum even if the targeted FPGA boards provides cool features. Besides of clock and reset you need to add at least one kind of IO interface like a UART, GPIO or PWM.
- Give your new top entity file a specific name that includes the board's name and the instantiated processor template.
The name scheme is
neorv32_[board-name]_BoardTop_[template-name].[v/vhd]
. - Put this file in
setups/osflow/board_tops
. - Take a look at the iCEBreaker MinimalBoot top entity as a reference:
setups/osflow/board_tops/neorv32_iCEBreaker_BoardTop_MinimalBoot.vhd
2. Pin mapping
- Add a new constraints file to define the mapping between the your top unit's IO and the FPGA's physical pins. You can add all of the FPGA's physical pins even though just a subset is used by the new setup.
- Name the new constraints file according to the board
[board-name].pcf
. - Put this file in
setups/osflow/constraints
. - Take a look at the iCEBreaker pin mapping as a reference:
setups/osflow/constraints/iCEBreaker.pcf
3. Adding a board-specific makefile
- Add a board-specific makefile to the
setups/osflow/boards
folder. Name the new constraints file according to the board[board-name].mk
. - The makefile contains (at least) one target to build the final bitstream:
.PHONY: all
all: bit
echo "! Built $(IMPL) for $(BOARD)"
- Take a look at the iCEBreaker pin mapping as a reference:
setups/osflow/boards/iCEBreaker.mk
4. Adding a new target to index.mk
- Add a new conditional section to the boards management makefile
setups/osflow/boards/index.mk
. - This board-specific section sets variables that are required to run synthesis, mapping, place & route and bitstream generation:
CONSTRAINTS
defines the physical pin mapping filePNRFLAGS
defines the FPGA-specific flags for mapping and place & routeIMPL
defines the setup's implementation name
ifeq ($(BOARD),iCEBreaker)
$(info Setting constraints and implementation args for BOARD iCEBreaker)
CONSTRAINTS ?= $(PCF_PATH)/$(BOARD).pcf
PNRFLAGS ?= --up5k --package sg48 --ignore-loops --timing-allow-fail
IMPL ?= neorv32_$(BOARD)_$(ID)
endif
5. Adding a new target to the main makefile
- As final step add the new setup to the main osflow makefile
setups/osflow/Makefile
. - Use the board's name to create a new makefile target.
- The new target should set the final bitstream's name using the
BITSTREAM
variable. - Alternative memory HDL sources like FPGA-optimized module can be set using the
NEORV32_MEM_SRC
variable.
- The new target should set the final bitstream's name using the
iCEBreaker:
$(eval BITSTREAM ?= neorv32_$(BOARD)_$(DESIGN).bit)
$(eval NEORV32_MEM_SRC ?= devices/ice40/neorv32_imem.ice40up_spram.vhd devices/ice40/neorv32_dmem.ice40up_spram.vhd)
$(MAKE) \
BITSTREAM="$(BITSTREAM)" \
NEORV32_MEM_SRC="$(NEORV32_MEM_SRC)" \
run
6. Optional: Add the new setup to the automatic "Implementation" github workflow
If you like you can add the new setup to the automatic build environment of the project. The project's "Implementation" workflow will generate bitstreams for all configured osflow setups on every repository push. This is used to check for regressions and also to provide up-to-date bitstreams that can be used right away.
- Add the new setup to the job matrix file
.github/generate-job-matrix.py
.
{
'board': 'iCEBreaker',
'design': 'MinimalBoot',
'bitstream': 'neorv32_iCEBreaker_MinimalBoot.bit'
},