Our office will be closed from August 9, 2021 to August 22, 2021. Orders placed during this time will be processed starting on August 23, 2021.

Minimal instrument with Koheron SDK

LED blinker for the Red Pitaya has the following files:

├── block_design.tcl
├── config.yml
├── constraints.xdc
├── led_blinker.hpp
├── led_blinker.py
├── test.py
└── web
    ├── app.ts
    ├── control.ts
    ├── index.html
    ├── led_blinker.ts
    └── main.css


Memory registers are specified in the instrument configuration file.

  - name: control
    offset: '0x60000000'
    range: 4K
  - name: status
    offset: '0x50000000'
    range: 4K

  - led # defines a control register

  - forty_two # defines a status register

Registers are accessible by their names from Tcl and C++.


Block Design

The Vivado block design is generated by the file block_design.tcl:

# Add PS and AXI Interconnect
set board_preset $board_path/config/board_preset.tcl

source $sdk_path/fpga/lib/starting_point.tcl
#source $sdk_path/fpga/lib/starting_point.tcl

# Add config and status registers
source $sdk_path/fpga/lib/ctl_sts.tcl

# Connect LEDs to config register
create_bd_port -dir O -from 7 -to 0 led_o
connect_port_pin led_o [get_slice_pin [ctl_pin led] 7 0]

# Connect 42 to status register
connect_pins [get_constant_pin 42 32] [sts_pin forty_two]

LED Blinker Vivado Block Design

The control and status IPs (ctl and sts) are connected to the port M_AXI_GP0 of the Zynq Processing System (ps_0) via the AXI Interconnect (axi_mem_intercon_0). This connection is clocked with ps_0/FCLK_0 which has been defined to 50 MHz via the parameter fclk0 in the configuration file.


Cores must be specified in the instrument configuration file.

  - fpga/cores/axi_ctl_register_v1_0
  - fpga/cores/axi_sts_register_v1_0
  - fpga/cores/dna_reader_v1_0

axi_ctl_register and axi_sts_register are used for communication between the Programmable Logic (PL) and the Processing System (PS) running Linux. Both cores are accessible from Linux as memory-mapped regions.

C++ drivers

C++ Drivers must be specified in the instrument configuration file.

Below is the C++ driver led_blinker.hpp:

#include <context.hpp>

class LedBlinker
    LedBlinker(Context& ctx)
    : ctl(ctx.mm.get<mem::control>())
    , sts(ctx.mm.get<mem::status>())

    void set_leds(uint32_t led_value) {

    uint32_t get_leds() {
        return ctl.read<reg::led>();

    void set_led(uint32_t index, bool status) {
        ctl.write_bit_reg(reg::led, index, status);

    uint32_t get_forty_two() {
        return sts.read<reg::forty_two>();

    Memory<mem::control>& ctl;
    Memory<mem::status>& sts;


Python scripts are written in line with the Python API.


from koheron import command

class LedBlinker(object):
    def __init__(self, client):
        self.client = client

    def set_leds(self, led_value):

    def get_leds(self, led_value):
        return self.client.recv_uint32()

    def set_led(self, index, status):

    def get_forty_two(self):
        return self.client.recv_uint32()


from koheron import connect
import os
import time
from led_blinker import LedBlinker

host = os.getenv('HOST','')
client = connect(host, name='led-blinker')
driver = LedBlinker(client)


print('Start blinking...')
for i in range(255):


TypeScript files are written in line with the TypeScript API.


class LedBlinker {
    private driver: Driver;
    private id: number;
    private cmds: HashTable<ICommand>;

    constructor (private client: Client) {
        this.driver = this.client.getDriver('LedBlinker');
        this.id = this.driver.id;
        this.cmds = this.driver.getCmds();

    getLeds(cb: (value: number) => void): void {
        this.client.readUint32(Command(this.id, this.cmds['get_leds']),
                                 (value) => {cb(value)});

    setLed(index:number, status: boolean): void {
        this.client.send(Command(this.id, this.cmds['set_led'], index, status));



class App {
    private driver: LedBlinker;
    public control: Control;

    constructor(window: Window, document: Document, ip: string) {
        let client = new Client(ip, 5);

        window.addEventListener('load', () => {
            client.init( () => {
                this.driver = new LedBlinker(client);
                this.control = new Control(document, this.driver);
        }, false);

        window.onbeforeunload = () => { client.exit(); };

let app = new App(window, document, location.hostname);

See also

[email protected]