146 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# Exemplary FPAG Board Setups - Using Open Source Toolchains
 | 
						|
 | 
						|
* [Folder Structure](#Folder-Structure)
 | 
						|
* [Prerequisites](#Prerequisites)
 | 
						|
* [How To Run](#How-To-Run)
 | 
						|
* [Porting to a new FPGA or Board](#Porting-to-a-new-FPGA-or-Board)
 | 
						|
 | 
						|
This folder provides the infrastructure for generating bitstream for various FPGAs using
 | 
						|
open-source toolchains. Synthesis is based on [ghdl-yosys](https://github.com/ghdl/ghdl-yosys-plugin).
 | 
						|
 | 
						|
:information_source: 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 generation
 | 
						|
* `boards`: board-specific _partial makefiles_ (used by main makefile "`Makefile`") for generating bitstreams
 | 
						|
* `board_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
 | 
						|
 | 
						|
:construction: TODO :construction:
 | 
						|
 | 
						|
* local installation of the tools
 | 
						|
* using containers
 | 
						|
 | 
						|
 | 
						|
## How To Run
 | 
						|
 | 
						|
:construction: TODO :construction:
 | 
						|
 | 
						|
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`](https://github.com/stnolting/neorv32/tree/master/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
 | 
						|
 | 
						|
1. Write a new top design unit that instantiates one of the provided processor templates from
 | 
						|
[`rtl/processor_templates`](https://github.com/stnolting/neorv32/tree/master/rtl/processor_templates).
 | 
						|
This new top unit can be a Verilog or VHDL file.
 | 
						|
2. _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`](https://github.com/stnolting/neorv32/tree/master/setups/osflow/devices).
 | 
						|
3. 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.
 | 
						|
4. 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]`.
 | 
						|
5. Put this file in `setups/osflow/board_tops`.
 | 
						|
6. Take a look at the iCEBreaker MinimalBoot top entity as a reference:
 | 
						|
[`setups/osflow/board_tops/neorv32_iCEBreaker_BoardTop_MinimalBoot.vhd`](https://github.com/stnolting/neorv32/blob/master/setups/osflow/board_tops/neorv32_iCEBreaker_BoardTop_MinimalBoot.vhd)
 | 
						|
 | 
						|
#### 2. Pin mapping
 | 
						|
 | 
						|
1. 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.
 | 
						|
2. Name the new constraints file according to the board `[board-name].pcf`.
 | 
						|
3. Put this file in `setups/osflow/constraints`.
 | 
						|
4. Take a look at the iCEBreaker pin mapping as a reference:
 | 
						|
[`setups/osflow/constraints/iCEBreaker.pcf`](https://github.com/stnolting/neorv32/blob/master/setups/osflow/constraints/iCEBreaker.pcf)
 | 
						|
 | 
						|
#### 3. Adding a board-specific makefile
 | 
						|
 | 
						|
1. Add a board-specific makefile to the `setups/osflow/boards` folder. Name the new constraints file according to the board `[board-name].mk`.
 | 
						|
2. The makefile contains (at least) one target to build the final bitstream:
 | 
						|
```makefile
 | 
						|
.PHONY: all
 | 
						|
 | 
						|
all: bit
 | 
						|
	echo "! Built $(IMPL) for $(BOARD)"
 | 
						|
```
 | 
						|
3. Take a look at the iCEBreaker pin mapping as a reference:
 | 
						|
[` setups/osflow/boards/iCEBreaker.mk`](https://github.com/stnolting/neorv32/blob/master/setups/osflow/boards/iCEBreaker.mk)
 | 
						|
 | 
						|
#### 4. Adding a new target to `index.mk`
 | 
						|
 | 
						|
1. Add a new conditional section to the boards management makefile `setups/osflow/boards/index.mk`.
 | 
						|
2. This board-specific section sets variables that are required to run synthesis, mapping, place & route and bitstream generation:
 | 
						|
   * `CONSTRAINTS` defines the physical pin mapping file
 | 
						|
   * `PNRFLAGS` defines the FPGA-specific flags for mapping and place & route
 | 
						|
   * `IMPL` defines the setup's implementation name
 | 
						|
```makefile
 | 
						|
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
 | 
						|
 | 
						|
1. As final step add the new setup to the main osflow makefile `setups/osflow/Makefile`.
 | 
						|
2. 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.
 | 
						|
```makefile
 | 
						|
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.
 | 
						|
 | 
						|
1. Add the new setup to the job matrix file `.github/generate-job-matrix.py`.
 | 
						|
```python
 | 
						|
{
 | 
						|
  'board': 'iCEBreaker',
 | 
						|
  'design': 'MinimalBoot',
 | 
						|
  'bitstream': 'neorv32_iCEBreaker_MinimalBoot.bit'
 | 
						|
},
 | 
						|
```
 |