Skip to content

Drive-On-Chip with PLC Design Example for Agilex™ 5 Devices

a. Overview: Software stack functional description

High-level software components for running the OpenPLC runtime in this design example are deployed using Docker and a custom Linux distribution based on YOCTO. By enabling virtualization, Docker, and UIO devices, the high-level software can communicate with custom hardware programmed into the FPGA fabric (Drive-On-Chip, see "Hardware Functional Description"). This example design demonstrates how to interface the OpenPLC runtime with logic programmed in the FPGA fabric, a concept that can be replicated using the software stack with any IP in the FPGA.

The primary software components are summarized in the following figure and described in the subsequent sections:


top-swm.

Software Top Block Diagram.


In summary:

  • A custom distribution of Linux with virtualization enabled, docker, UIO device driver, build based on KAS.
  • Debian-based container to support portability across devices. Cross-compiled for ARM64 architecture.
  • Servo Driver (or Drive-On-Chip) OpenPLC hardware support to interface the OpenPLC Runtime with FPGA IP (in this case the Drive-On-Chip IP/System). This include patches to enable Agilex™ Hardware selection in the OpenPLC Runtime web-server interface.
  • OpenPLC Motion Control Library (Implemented using RT Motion library) based on PLCOpen standard IEC-61131-3. See: PLCopen Motion Control Specification
  • Integration of Ruckig Motion Planner Library, to generate trajectories constrained by velocity, acceleration and other parameters. See: Ruckig: Instantaneous Motion Generation for Robots and Machines
  • OpenPLC Runtime: An Open Source Programmable Logic Controller implementation created in accordance to the IEC 61131-3 standard that defines architecture and basic programming languages for PLCs.
  • The OpenPLC runtime has an in-build webserver that allows basic runtime configuration.
  • An example of how to run an user-specific PLC program in Structured Text (ST) language to control and interface with the Drive-On-Chip System in the FPGA fabric.

b. Custom Linux distribution based on KAS

For the Drive-On-Chip with PLC Design Example for Agilex™ 5 Devices, Altera® provides the files to build the Linux system to run the PLC Software Stack enclosed in a Docker Container. The custom version of linux is built based on KAS (see: agilex-ed-drive-on-chip/sw). An it is compose of two main meta-layers. In this document the files relevant for the "Drive-On-Chip with PLC Design Example for Agilex™ 5 Devices" are highlighted.

FPGA Embedded Layer

Drive-On-Chip Layer

b.1. Necessary elements in the meta-layers to bind Software and Hardware

This section details the various elements included in the meta-layers that facilitate running the PLC application. These elements assist in "binding" the FPGA Soft IP, such as Drive-On-Chip, with the software running on the HPS, which operates on Linux and is containerized using Docker. The following sections explain these elements to clarify the interaction between the HPS software stack and the FPGA IP (soft logic, Drive-On-Chip). This interaction between the PLC and Drive-On-Chip IP serves as an example of how to interface any soft IP in the FPGA fabric with higher-level software, such as the OpenPLC Runtime contained within a Docker image.

b.1.1. Device Tree

Adds a custom .dtsi (device tree fragment) file to the main device tree for Linux kernel boot up stage socfpga_agilex5_socdk.dts. it compiles into a DTB (device tree blob) during kernel compilation and is added to the SD card image during the Yocto build. The recipe device-tree.bb. The specific file for this design example (agilex5_dual_axis.dtsi), is appended using device-tree.bbappend directive. Look for these files in the different meta-layers provided above.


device-tree

Custom Device Tree Fragment.


You expand the device tree by appending the contents of the file agilex5_dual_axis.dtsi, that exposes an additional as UIO device in the RootFS (generic-uio). The figure shows the instance of the device. This definition should match with the devices that the HPS can access in the FPGA soft logic and you can verify the address map in the Platform Designer Project (.qsys).

For example, the Drive-On-Chip control subsystem debug memory (doc_sys_debug_ram) that is used to interact and provide commands to the Drive-On-Chip control application has the base address 0x0008_0000 in Platform Designer, but from the view of HPS you should add the offset reflecting the HPS-FPGA bridge 0x4000_0000, refer ( System Memory Mapping Scheme in the Hard Processor System Technical Reference Manual: Agilex™ 5 SoCs (24.3)) specifying the address 0x4008_0000 in the agilex5_dual_axis.dtsi file. Components connected to the full HPS to FPGA bridge have an offset of 0x4000_0000 and components connected to lightweight HPS-to-FPGA bridge have an offset of 0x2000_0000.

The Drive-On-Chip component is listed in the .dtsi as compatible generic_uio, which is a way to map devices using generic user IO interface in the Linux kernel and user space. If you modify or add memory mapped devices in Platform Designer, also add the change in the .dtsi file. When the Yocto build refreshes, the Linux system lists the device in the corresponding /dev/uiox and populates the information in /sys/class/uio/uiox. To enable UIO devices two Linux kernel modules must be enabled in uio.cfg file: CONFIG_UIO and CONFIG_UIO_PDRV_GENIRQ The .dtsi and Platform Designer mapping should be consistent to provide the HPS software application to run correctly.

The interaction between the Drive-On-Chip UIO device and the OpenPLC Runtime is achieved by enabling hardware support for the Agilex™ Device. In this example design this is applied using the source file agilex_doc.cpp and the patch file agilex_doc.patch

b.1.2. FPGA Bitstream

Adds the agilex5_modular_dual_axis.core.rbf file to the build. The file is generated after Quartus® Prime compilation. The *core.rbf file is added to the boot partition of the SD card (renamed as top.core.rbf). The HPS configures the FPGA at initialization using u-boot load command in uboot.txt generated into boot.scr.uimg in the boot partition by u-boot-socfpga_%.bbappend (look for the files in the meta-layer).


rbf-program

FPGA configuration during HPS booting process.


Look for the print "..... FPGA reconfiguration OK " during the device booting process, as shown in the previous figure to ensure the FPGA bitstream (top.core.rb) has been properly loaded.

b.1.3. Additional u-boot configuration

An append to the u-boot arguments using IMAGE_BOOT_ARGS and IMAGE_BOOT_ARGS:append:agilex5_modular in different KAS/YOCTO configuration files to enable UIO drivers defined by uio_pdrv_genirq.of_id=generic-uio.

b.2. Necessary elements in the meta-layers to enable Docker deployments

To enable the execution of Docker container-based applications on the SoC FPGA platform, certain additions are required for the custom Linux build based on KAS. These include enabling virtualization through the meta-virtualization layer, configuring the respective kernel settings, and installing Docker in the SD card image.

These customizations are implemented using the docker.yml KAS configuration file, which adds the meta-virtualization layer to the YOCTO build and installs docker and docker-compose into the RootFS. This configuration is included in the includes: section of the main KAS-YOCTO configuration file, kas_dual_axis.yml. The necessary kernel configuration settings to enable Docker and virtualization are contained in the docker.cfg file, wrapped within the virtualization-layer (dynamic layer).


b.3. PREEMPT-RT patch

This example shows the user how to easily "patch" the Linux kernel with PREEMPT_RT patch, which provides soft Real Time characteristics particularly useful for embedded hardware applications. See the file linux-socfpga-rt_6.6.bb


c. Debian-based container image for OpenPLC

The OpenPLC Runtime is packaged within a Docker image, which includes the necessary applications and libraries to operate the web server, application database, and PLC control application. The Docker container image deployed on the target Agilex™ device is built and cross-compiled for ARM64 architecture, using a Dockerfile provided in the Altera® FPGA PLC repository (https://github.com/altera-fpga/altera-openplc).

The main instructions to build the docker image in the provided Dockerfile are:

  • Specifies the base image for building the container using the Debian 11 "Bullseye" release with a specific update (July 22, 2024) from the docker registry, see: docker-bullseye-20240722
  • Installs necessary build tools (cmake, git, build-essentials, etc).
  • Clones the OpenPLC and installs Ruckig repositories:
  • Installs PLC Motion libraries and applies patches for Agilex™ hardware support.
  • Installs OpenPLC Runtime.
  • Entrypoint is defined as OpenPLC Runtime with the start_openplc.sh script.


d. Servo Driver (Drive-On-Chip) OpenPLC hardware support

This C++ program is designed to interface with a hardware device using the UIO (Userspace I/O) framework in Linux. It primarily focuses on controlling servo motors through the Drive-on-Chip device.

The following definitions and enumerations are enclosed in the namespace called DoC:

Definitions and Enums for servo Driver Program

Definitions and Enums Description
RTMOTION A macro defined at the beginning, likely indicating that the program is
part of the RTmotion library or framework
DRIVE_AXIS_PER_DEVICE, MAX_AXIS_NUM Constants defining the number of axes per device and the
maximum number of axes, respectively
WaveDemoMode, WaveDemoWaveform Enumerations defining different modes and waveforms for a wave demonstration feature
DebugRegister An enumeration listing various registers for debugging and controlling the
device. These registers cover a wide range
of functionalities, from general drive
status to specific control parameters

d.1. "UIODevice" class

Manages the interaction with a UIO device, including memory mapping and register access. The constructor UIODevice initializes the device and axis, checks for device and axis availability, and sets up memory mapping. The destructor ~UIODevice cleans up the memory mapping.

Class Methods

Method Description
Read Reads a value from a specified register
Write Writes a value to a specified register
GetDevicePath Determines the device path for a given device name
IsAxisMapped Checks if a specific axis is mapped for a given device
ReadSysHexVal Reads a hexadecimal value from a system file

d.2. "DoCServo" class

Represents a servo motor controlled by the DoC device. The constructor DoCServo initializes the servo for a specific axis, checking if the axis is mapped and setting up the device. The destructor is empty.

Class Methods

Method Description
setVel Sets the target velocity for the servo
vel Retrieves the current velocity from the device
runCycle Updates the device with the current target
velocity and configures the wave demo settings

d.3. Global variables and functions

Variables and Functions Description
Global Variables
config Array of AxisConfig objects for configuring axes
servo Array of pointers to DoCServo objects
active_drives_num Tracks the number of active drives
Global Functions
initializeHardware Initializes the hardware by setting up axes and servos,
and configuring them
finalizeHardware Cleans up resources by deleting axes and servos
updateBuffersIn Updates input buffers, running the cycle for each
active axis
updateBuffersOut Placeholder function for updating output buffers

In summary the program in agilex_doc.cpp files is structured to manage and control servo motors using a UIO device interface. It sets up memory mapping for device registers, configures axes and servos, and provides functions to initialize and finalize hardware resources. The program also includes mechanisms to read and write to device registers, allowing for real-time control and monitoring of servo motor parameters.


e. PLCOpen Motion Control Standard and RTmotion Motion Control Library

PLCopen is a standards organization that supports automation for PLCs. The PLCopen Motion Control standard defines operations on motor axes using functional blocks. The blocks wrap the complex operations of motor control in a simplified API. The advantages include:

  • A standard interface to different manufacturers motor hardware.
  • Portability of applications.
  • Reduced training required to implement motor control applications.

The figure below is an example of how this can be used to coordinate two motor axes:


plc-motion

Example of PLCOpen Motion control functional block.


  • The Execute input triggers the first function block to move motor Axis X to a defined position X_POS.
  • When the first operation is complete the Done output starts the second function block which moves motor Axis Y to its predefined position Y_POS.

The RTmotion library implements the PLCopen Motion Control functional blocks. The library is released under the open source license Apache V2.0. The RTmotion library has a dependency on the Ruckig library. Ruckig is used for motion planning operations: calculating the optimum speed profile for the axis so the system moves efficiently but within the constraints of maximum acceleration and jerk (rate of change of acceleration). For more details see: Ruckig: Instantaneous Motion Generation for Robots and Machines.

A copy of the RTmotion library is included into the Altera® FPGA PLC repository https://github.com/altera-fpga/altera-openplc.


f. OpenPLC Runtime

OpenPLC is an open-source programmable logic controller (PLC) platform designed to provide a flexible and cost-effective solution for industrial automation and control systems. It is built to be compatible with the IEC 61131-3 standard, which is the international standard for PLC programming languages. OpenPLC supports multiple programming languages defined by this standard, including Ladder Logic (LD), Structured Text (ST), Function Block Diagram (FBD), and Sequential Function Charts (SFC). The runtime includes a web-based interface for programming and monitoring, which simplifies the process of developing and managing PLC projects.

The OpenPLC project consists of Editor and Runtime components. The Editor is used to create and simulate applications written in the IEC 61131 PLC languages. To run the applications on real hardware the OpenPLC Editor converts the programs to Structured Text (ST) format. The OpenPLC Editor supports two deployment options for the resulting Structured Text output:

  • Upload to a Linux target system via the OpenPLC Runtime webserver. The runtime converts Structured Text to C source code and compiles it on the target device to a binary that implements the PLC operations.
  • Use OpenPLC Editor convert and compile the application on the host PC before downloading the resulting binary to a micro-controller.

The Drive-on-Chip with PLC Design Example for Agilex™ 5 Devices uses the first option to build and deploy ST program.

More information about OpenPLC can be found in: OpenPLC Documentation


g. Example of an user-specific PLC program in Structured Text (ST) for DoC control

The example on how to control the Drive-On-Chip IP in the FPGA fabric with an Structured Text program that executes in the OpenPLC Runtime is described in the file agilex_doc.st. The program description is as follows:

g.1. FUNCTION_BLOCK "OnOffIntervalTimer"

This function block is designed to control an on-off interval timer. It has the following components:

Function Block Description.

Variable Description
VAR_INPUT
ON_TIME A TIME variable specifying the duration for which the timer should be active
OFF_TIME A TIME variable specifying the duration for which the timer should be inactive
VAR_OUTPUT
ACTIVE A BOOL variable indicating whether the timer is currently active
VAR
LATCH An RS (Reset-Set) latch used to control the timing logic
ON_INTERVAL A TP (Timer Pulse) block that generates a pulse for the ON_TIME
OFF_INTERVAL A TOF (Timer Off Delay) block that manages the OFF_TIME
Logic
LATCH It is set when the OFF_INTERVAL is not active and reset when the ON_INTERVAL is active
ON_INTERVAL It is triggered by the latch and runs for the ON_TIME
OFF_INTERVAL It starts when the ON_INTERVAL finishes and runs for the OFF_TIME
ACTIVE The output is true when the ON_INTERVAL is active

g.2 PROGRAM "prog0"

This program utilizes the OnOffIntervalTimer function block to control two axes of a motor system. It includes:

Variable Description
VAR
MOTOR_PULSE0 An instance of OnOffIntervalTimer to manage the timing of motor pulses
VAR
AXIS_0_HALT, AXIS_1_HALT Instances of MC_HALT to stop the axes
AXIS_0_SET_VEL, AXIS_1_SET_VEL Instances of MC_MOVEVELOCITY to set the velocity of the axes
AXIS_0_READ_VEL, AXIS_1_READ_VEL Instances of MC_READACTUALVELOCITY to read the actual velocity of the axes
AXIS_0_POWER, AXIS_1_POWER Instances of MC_POWER to control the power state of the axes
VAR
AXIS_0_VELOCITY, AXIS_1_VELOCITY Real variables to store the actual velocity of each axis

g.2.2. Program Logic

  • Powers on both axes with positive and negative enable.
  • Uses MOTOR_PULSE0 to control the execution of velocity setting and halting commands based on its ACTIVE state.
  • Sets the velocity, acceleration, deceleration, and jerk for each axis when the timer is active.
  • Halts the axes when the timer is inactive.
  • Reads and stores the actual velocity of each axis.

g.3. CONFIGURATION "Config0"

This configuration sets up the PLC environment:

  • RESOURCE Res0 ON PLC:
    • Defines a resource named Res0 on the PLC.
    • TASK Main: A task with a 50ms interval and priority 0.
    • PROGRAM Inst0 WITH Main: Associates the prog0 program with the Main task.

In summary, this ST file configures a PLC program to control motor axes using an on-off interval timer, managing power, velocity, and halting based on the timer's state.


Back to Documentation


Last update: May 1, 2025
Created: May 1, 2025