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'
 | |
| },
 | |
| ```
 |