Universal Programming Language Extension of Embedded Software on FPGA Hardware

From Denis Vasilik* | Translated by AI 10 min Reading Time

FPGA development using markup languages such as Verilog and VHDL is considered difficult to access. However, software programming languages such as C or C++ are often inadequate for this purpose. A universal language for FPGA/ASIC design with software tools and abstractions such as Livt could close this gap.

FPGAs solve performance bottlenecks, but are considered difficult to program. The universal programming language Livt is intended to lower the hurdle - correct, deterministic and HDL-compatible.(Image: Toby Giessen / VCG)
FPGAs solve performance bottlenecks, but are considered difficult to program. The universal programming language Livt is intended to lower the hurdle - correct, deterministic and HDL-compatible.
(Image: Toby Giessen / VCG)

For decades, FPGA and ASIC development has existed in a world of its own. Hardware description languages like VHDL and Verilog are powerful and precise, but they come with a long learning curve, verbose syntax, and workflows that feel disconnected from modern software engineering practices.

At the same time, embedded software developers often come up against the limits of MCUs and CPUs. Latency, determinism, energy efficiency and parallelism eventually become bottlenecks. Although FPGAs are often the right technical solution, the barrier to entry is so high that many teams avoid them altogether.

Livt was developed to fill this gap. Livt is a general-purpose programming language for FPGA and ASIC design that brings abstraction, tools and software-style workflows to the hardware domain without compromising correctness, determinism or interoperability with existing HDL code.

Why Another Language for FPGA Development?

Traditional HDL development forces developers to think in terms of low-level hardware from the first line of code. While this level of control is essential for correct and efficient hardware design, it also means that even simple behaviors often require extensive boilerplate code and a deep understanding of hardware-specific details.

In practice, traditional HDL development requires you to think in the following terms:

  • Signals instead of variables;
  • Processes instead of functions;
  • Explicit bars and resets throughout the design;
  • Handwritten test benches for verification; and
  • Manufacturer-specific tool flows and workflows.

These concepts are powerful, but they complicate FPGA development, slow down iteration and make maintenance difficult - especially for developers with a software background.

Livt takes a different approach. Instead of starting with low-level mechanisms, you describe what a design should do, and the compiler derives a correct and readable VHDL representation from this description. The generated HDL integrates seamlessly into existing toolchains and can coexist with hand-written VHDL or Verilog when deeper control or optimization is required.

Livt was developed to cover all the requirements of modern development:

  • First you describe the behavior.
  • The compiler derives correct VHDL from this.
  • If required, you retain full access to VHDL and Verilog.
  • You will work in a software-oriented ecosystem, including package management, unit testing, CI/CD integration and AI-powered tools.

The result is not "HDL replaced", but "HDL extended" - which is also reflected in the name "Livt". The intention is not to replace hardware description languages, but to increase the level of abstraction at which most of the system is expressed. Hardware engineers retain full control where it matters, while large parts of a design can be developed faster, safer and with significantly improved readability and maintainability.

Hardware-Software Integration via HxS

A key factor in Livt's approach is its close integration with the existing domain-specific language HxS. HxS focuses on the description of hardware-software interfaces, in particular register mappings and CPU-visible control points.

With Livt and HxS together, it becomes easy to link a processor-accessible register to a value within the FPGA or even to a function implemented in the hardware logic. Instead of writing fragile glue logic, you define clear and explicit interfaces between software and hardware.

This fundamentally changes the way in which communication between the processor and FPGA is organized. The hardware logic is no longer controlled passively via registers, but can actively disclose its behavior via clearly defined APIs.

Why MCU Developers Should be Interested in FPGAs

From the perspective of an MCU developer, FPGAs become relevant when software alone can no longer fulfill the system requirements. This is often the case when strict real-time behavior is required, when latency must be reduced to an absolute minimum or when tasks can benefit from massive parallelism.

Typical examples are high-speed sensor interfaces, motor control, protocol processing, signal pre-processing or energy-efficient data processing. In many of these cases, implementing part of the functionality in hardware is the technically correct solution.

What has been missing is an accessible way to do this without completely switching to an HDL-centric mindset. Livt fills this gap by providing a programming model that is familiar to embedded developers while producing efficient, synthesizable hardware.

A Software-Oriented Programming Model

Livt deliberately adopts concepts that are familiar from modern programming languages. The code is organized using namespaces and components. The status is expressed by fields. Behavior is encapsulated in functions and processes with clear visibility rules. Constructors describe how components are connected to each other instead of forcing the developer to manually manage low-level signal connections.

Subscribe to the newsletter now

Don't Miss out on Our Best Content

By clicking on „Subscribe to Newsletter“ I agree to the processing and use of my data according to the consent form (please expand for details) and accept the Terms of Use. For more information, please see our Privacy Policy. The consent declaration relates, among other things, to the sending of editorial newsletters by email and to data matching for marketing purposes with selected advertising partners (e.g., LinkedIn, Google, Meta)

Unfold for details of your consent

At the same time, the language remains clear in terms of what is combinatorial and what is sequential and how timing is defined. This ensures that the resulting hardware remains deterministic and predictable, which is crucial for FPGA and ASIC design.

This model allows mixed teams to work effectively. Embedded software developers can implement non-critical or application-specific logic, while FPGA engineers focus on architecture, timing closure and optimization, where their expertise has the greatest impact.

An Example: Triggering the FPGA Logic via a CPU Register

A simple but representative example is a processor that triggers a behavior within the FPGA by writing to a memory-mapped register. In Livt, this limit is expressed directly where the behavior is defined. The following component declares a bus interface and binds a register bit visible to the CPU with HxS annotations to a function call.

An AXI4-Lite bus is used in the following example. Avalon and Wishbone are supported in the same way by selecting a different bus type.

namespace Demo.App
using Livt.HxS
@Interface(BusType="AXI4Lite")
component LedController
{
    led: out logic
    // A write to bit 0 of this register triggers Toggle().
    // Because Toggle() has no parameters and no return value,
    // the compiler infers pure trigger semantics.
    @Register(Id="LedToggleTrigger", Address=0x4000_0000)
    public fn Toggle()
    {
        this.led = !this.led
    }
}

At this point, it is worth noting how compact the Livt code remains. The component expresses only the essential behavior required for the task, while the entire bus-related infrastructure - including register decoding, address mapping, access handshaking and protocol-compliant bus transactions - is automatically generated by the compiler and the underlying framework. This avoids a whole class of bus-related errors that often occur when implementing AXI4-Lite slave interfaces manually.

A write operation to the register at address 0x4000_0000 with bit 0 set causes the function to be executed. From the compiler's point of view, this is clearly a trigger and not a value register, as the function does not accept any parameters and does not return a value.

If the function signature changes in the future, the compiler can automatically adapt the register semantics. A written value can be passed to the function or a return value can be provided for reading back without changing the entire integration concept.

Use on the MCU Side (C, memory-mapped I/O)

From the MCU side, this looks like an ordinary memory-mapped register access.

#include <stdint.h>
#define LED_TOGGLE_TRIGGER_ADDR (0x40000000u)
#define LED_TOGGLE_TRIGGER_BIT (1u << 0)
static inline void Led_Toggle(void)
{
    *(volatile uint32_t*)LED_TOGGLE_TRIGGER_ADDR = LED_TOGGLE_TRIGGER_BIT;
}
int main(void)
{
    while (1)
    {
        Led_Toggle();
        // delay via timer, busy wait, or RTOS service
    }
}

The firmware remains trivial, while the behavior of the hardware is clearly defined and adheres closely to the interface description. This close coupling of behavior and register assignment significantly reduces integration errors and improves maintainability.

A Software Ecosystem for Hardware Design

Livt is not just a language, but a complete ecosystem. Projects follow a clear structure, support unit testing, integrate seamlessly into CI/CD pipelines and benefit from AI-powered tools. This allows hardware projects to adopt workflows that have been standard in software development for years, improving reliability, maintainability and development speed.

An important part of this ecosystem is the Livt base library. It provides basic language functions and reusable building blocks that would otherwise have to be implemented again and again. Instead of starting with raw primitives, developers can fall back on clearly defined, tested abstractions that behave consistently across projects.

The following excerpt provides a brief insight into the namespaces that are available when using Livt:

  • Livt.Protocol namespace o SPI, I2C, UART master/slaves o AXI, Wishbone, Avalon interfaces o Ethernet frame parser/generators o USB packet handler
  • Livt.Math Namespace o Basic operations (Abs, Min, Max, Clamp, Saturate) o Transcendental functions (Sin, Cos, Sqrt, Log, Exp, Pow) o Auxiliary functions for fixed-point arithmetic o Bit manipulation (CountLeadingZeros, PopCount, BitReverse, RotateLeft/Right) o Statistical functions (Average, Median, Variance, StdDev)
  • Livt. signal namespace o FIR/IIR filter implementations o FFT/IFFT o Window functions (Hamming, Hanning, Blackman) o Correlation and convolution o CRC/checksum calculator

This directly addresses a long-standing problem in traditional HDL-based development. VHDL suffers from fragmented and inconsistent custom package ecosystems where each team - and often each developer - creates their own helper functions. This leads to error-prone code duplication, incompatible data type definitions between projects, and significant long-term maintenance overhead. The lack of a comprehensive standard library beyond the basic types forces engineers to reinvent common functions over and over again.

Livt moves away from this model. Instead of promoting ad-hoc utility packages, it provides a coherent base library and a structured package system. In addition, Livt encourages development at the package and framework level, rather than distributing hardware as ready-made, opaque IP blocks with minimal configuration options. Packages and frameworks expose structure and intent, making them easier to understand, customize and extend.

The following example illustrates how these components work together in practice. The "UartController" component is assembled using functions from the "Livt.Protocol" namespace and made available to a processor via an HxS register interface. Instead of integrating a ready-made black box IP, the design is based on the reusable component "BufferedUart" at framework level and adds application-specific behavior with just a few lines of code.

namespace Demo.App
using Livt.HxS
using Livt.Protocol
@Interface(BusType="AXI4Lite")
component UartController
{
    uart: BufferedUart
    new (rx: in logic, tx: out logic)
    {
        this.uart = new BufferedUart(rx, tx)
    }
    @Register(Id="SayHelloWorldTrigger", Address=0x4000_0000)
    public fn SayHelloWorld()
    {
        let greeting = "Hello, World!".Encode()
        this.uart.Send(greeting)
    }
}

This approach significantly reduces the learning curve for new developers, improves reusability across teams and projects and enables hardware development to be scaled in the same way as in modern software ecosystems.

No Replacement for FPGA Engineers

Livt does not make FPGA engineers superfluous, and that is not its goal. Low-level optimization, timing closure, clock domain design, FSM tuning and manufacturer-specific primitives still require in-depth hardware know-how.

Livt ensures that this expertise is used where it really matters. Engineers spend less time on repetitive standard tasks and more time on architecture, performance and correctness.

Concluding Thoughts

Livt is changing the way FPGA and ASIC development is integrated into modern engineering teams. It lowers the barriers for software developers to make a meaningful contribution to hardware logic, while maintaining the precision and reliability required for real hardware.

At the same time, the adoption of modern software concepts is becoming increasingly important in order to take advantage of AI-supported programming and autonomous development agents. These tools are based on a clear structure, explicit intent and consistent abstractions - features that are largely missing in traditional HDL-based workflows. By adopting software-oriented design principles, Livt makes hardware designs more accessible not only to humans, but also to AI-based tools that are fully supported by the Livt ecosystem.

If you've ever reached a point where software alone was no longer enough, but hardware seemed unattainable, Livt is designed for just that moment. (sg)

*Denis Vasilik is CTO of Eccelerators GmbH.