FPGA design

Koheron SDK V1 documentation. You are reading the documentation for the V1 branch. It uses CFG=.../config.mk, memory.yml, Linux FPGA Manager and device-tree overlays. It is not backward-compatible with 0.x instruments.

Goal

Define the programmable-logic part of an instrument and keep it synchronized with the C++ driver and Linux runtime.

The FPGA flow is driven by three instrument inputs and the board support files selected from config.mk:

  • config.mk: selects the board, constraints and FPGA cores.
  • memory.yml: defines memory regions, registers and generated identifiers.
  • block_design.tcl: creates the Vivado block design.

Build the FPGA design

Build only the FPGA artefacts with:

make -j CFG=examples/alpha250/fft/config.mk fpga

Build the complete instrument archive with:

make -j CFG=examples/alpha250/fft/config.mk

Select the board

The target board is selected in config.mk:

BOARD_PATH := $(SDK_PATH)/boards/alpha250

Board directories contain board-specific make fragments, Vivado presets, constraints, boot files and driver lists.

Add constraints

XDC files are listed in config.mk:

XDC += $(SDK_PATH)/boards/alpha250/config/ports.xdc

Add instrument-specific constraints with additional XDC += lines.

Add FPGA cores

Cores are listed in config.mk with CORES +=. Board-level cores can be included from a board make fragment:

include $(SDK_PATH)/boards/alpha250/cores/cores.mk
CORES += $(SDK_PATH)/fpga/cores/axis_constant_v1_0
CORES += $(SDK_PATH)/fpga/cores/latched_mux_v1_0
CORES += $(SDK_PATH)/fpga/cores/psd_counter_v1_0

The FPGA build imports the listed cores into the Vivado project. In V1, SDK-owned reusable cores live under fpga/cores/; document or add cores with that path convention unless the SDK source is changed.

Create the block design

Each instrument provides a Vivado Tcl script, usually block_design.tcl. This script creates the block design, instantiates IPs, connects clocks and resets, and connects the generated memory/register interfaces.

memory.yml is used to generate memory.tcl, so the block design can refer to memory regions and registers by name.

Define memory and registers

Control and status regions are declared in memory.yml:

memory:
  - name: control
    offset: 0x4000_0000
    range: 4K
    registers:
    - digital_outputs

  - name: status
    offset: 0x5000_0000
    range: 4K
    registers:
    - digital_inputs

The build generates corresponding Tcl, C++ and device-tree identifiers. Use the generated names consistently in the block design and C++ drivers.

Device-tree overlay

The runtime loads instruments with Linux FPGA Manager and a device-tree overlay. The build converts the Vivado bitstream into <instrument>.bit.bin, generates pl.dtbo, and packages both files in the instrument ZIP.

The generated overlay combines:

  • the Vivado/Vitis-generated PL description
  • the memory map generated from memory.yml
  • optional user overrides selected by OVERRIDE_DTSI in config.mk

A typical wrapper includes:

/dts-v1/;
/plugin/;
/include/ "pl.dtsi"
/include/ "memory.dtsi"
/include/ "override.dtsi"

The wrapper source is fpga/pl_wrap.dts; the build rewrites the generated PL include to pl-koheron.dtsi, substitutes the bitstream name with <instrument>.bit.bin, compiles the overlay with dtc, and copies the final pl.dtbo next to the instrument ZIP.

Runtime artefacts

The instrument archive contains the runtime bitstream binary, device-tree overlay and original Vivado bitstream for reference/debugging. At runtime the server copies pl.dtbo and <instrument>.bit.bin into /lib/firmware, prepares configfs overlays, writes pl.dtbo to the overlay path, and checks the FPGA Manager status. This is the V1 runtime path; it is not the old /dev/xdevcfg flow.

See also

[email protected]