The development of High-Level Synthesis (HLS) transformed how developers approach FPGA design. Traditionally, hardware description languages (HDLs) like VHDL or Verilog were the only way to describe digital logic. HLS changes that by allowing engineers to describe hardware behavior using higher-level programming languages like C, C++, or SystemC, significantly streamlining design, testing, and iteration.
What Is High-Level Synthesis (HLS)?
At a broad level, High-Level Synthesis (HLS) is the process of converting high-level algorithmic descriptions written in C, C++, or SystemC into register-transfer level (RTL) code that can be implemented on an FPGA or ASIC.
Instead of thinking in terms of gates, clocks, and flip-flops, engineers can focus on algorithms, control flow, and data movement. The HLS tool handles the rest, mapping the software logic into parallel hardware that meets timing and resource constraints. In other words, HLS bridges the gap between software and hardware design.
Read more on how HLS bridges the gap here.
Benefits of Using HLS
The main benefit of HLS is faster design productivity. Writing and debugging algorithmic code in C or C++ is typically much faster than developing and simulating HDL. That translates to quicker prototyping, faster design space exploration, and fewer errors.
Key advantages include:
- Accelerated development: HLS enables faster iterations, allowing engineers to modify algorithms and quickly regenerate RTL.
- Algorithm reuse: Existing C/C++ software algorithms can be repurposed for hardware acceleration.
- Optimization flexibility: Designers can experiment with different architectures (pipelining, unrolling, or resource sharing) without rewriting low-level HDL.
- Performance and power efficiency: Properly optimized HLS designs can match the performance and efficiency of hand-coded RTL.
HLS is especially useful for teams developing compute-intensive algorithms, such as those found in video processing, radar, image recognition, or AI/ML applications. It’s also beneficial when time-to-market is critical or when software developers need to contribute directly to hardware acceleration.
What Is the AMD Vitis HLS Software?
AMD Vitis HLS is a powerful tool for converting high-level C, C++, or OpenCL code into synthesizable HDL for AMD FPGAs and adaptive SoCs. It provides a structured workflow that guides you from algorithmic code to hardware implementation.
The Vitis HLS Tool Flow
Here’s a typical flow for Vitis HLS:
- C/C++ model development – write your algorithm in C or C++ as a top-level function and validate it via standard software simulation.
- C simulation – use the Vitis HLS tool to simulate the C model to ensure correctness.
- C synthesis – the Vitis HLS tool analyses your C/C++ code (data‐flow, control dependencies), applies HLS directives you’ve inserted (e.g., #pragma HLS pipeline, #pragma HLS dataflow, etc.), and generates RTL (Verilog or VHDL). UG1399 includes “Running C Synthesis” and “Output of C Synthesis” sections.
- C/RTL co‐simulation – you run a co-simulation where the generated RTL is exercised and compared against the C model to confirm functional equivalence. The guide covers “Running C/RTL Co-Simulation”.
- Export RTL (packaging) – once you’re satisfied, you export the modules/IP to downstream tools (such as the Vivado flow or Vitis system platform), integrate into SoC or FPGA design. The guide identifies “Output of RTL Export” and “Running Implementation” steps.
- System integration and implementation – include the IP in a larger system, perform place & route, timing closure, bitstream generation, etc.
Vitis HLS UG – AMD Documentation
What Happens “Under the Hood”
As you run synthesis in Vitis HLS, several important transformations occur:
- Dependency analysis: The tool examines your algorithm’s data and control dependencies (loops, function calls, memory accesses) to determine possible parallelism and hazards.
- Scheduling: Operations are scheduled across clock cycles, based on your target clock period, resource constraints, and directives.
- Binding: The tool maps operations to hardware resources (e.g., adders, multipliers, DSPs, memory blocks) and allocates registers, registers‐files, etc.
- Optimization: Based on your pragmas and directives (e.g., loop unrolling, pipelining, dataflow regions, array partition/reshape), the tool reorganizes the design to meet latency, initiation interval (II), throughput, and area goals. The UG1399 guide provides an entire “Design Principles” section covering pipelining loops, array partitioning, function inlining, etc.
- RTL generation: Finally, synthesizable RTL (Verilog or VHDL) is produced, with interface logic (AXI4, AXI4-Lite, Streams), FIFOs, memory interfaces, clock/reset ports, and optional auto-restart behavior if you specified it. The guide has detailed sections on interface synthesis (AXI4, AXI4-Lite, AXI-Stream) and memory layout rules.
Thus, Vitis HLS provides a robust abstraction: you code in C/C++, you apply pragmas/directives, then the tool handles the heavy lifting of transforming into efficient hardware.
Coding Constructs: Supported vs. Unsupported in Vitis HLS
When working with HLS, especially with Vitis HLS, it’s important to know which C/C++ constructs map well to hardware and which don’t. The AMD UG1399 guide has a dedicated section “Unsupported C/C++ Constructs”.
Supported Constructs
You’ll find good support in Vitis HLS for:
- Standard loops (for, while) and conditionals (if, switch) that have analyzable bounds or static behavior.
- Functions, including inlining via #pragma HLS inline, templates, classes (with certain restrictions). The guide has “Function Inlining” and “C++ Classes and Templates” sections.
- Arrays, structs, classes, fixed‐width and arbitrary precision data types (ap_int, ap_fixed, etc.). The guide’s “Arbitrary Precision Data Types” section details these.
- Streaming constructs (e.g., hls::stream<>), and memory interface constructs targeting AXI/AXI-Stream or FIFO style flow. The guide features “HLS Stream Library” and “Coding Style for Array to Stream”.
- Pragmas/directives for performance: pipeline loops, unroll loops, partition arrays, reshape memories, dataflow regions, etc. UG1399 lists the full set.
Constructs That Are Unsupported or Limited
Some constructs do not map cleanly to hardware and are either not supported or require caution:
- Dynamic memory allocation (new, malloc) – hardware doesn’t dynamically allocate like software. The guide lists “Dynamic Memory Usage” under unsupported features.
- Recursion and function pointers / virtual functions – both introduce unpredictable control flow which complicates scheduling. “Recursive Functions” is listed as unsupported.
- Standard C++ library templates that allocate runtime memory or use complex pointers – e.g., some STL containers may not be supported or synthesizable. “Standard Template Libraries” is listed under unsupported features.
- Complex pointer arithmetic, multiple dereferences, or aliasing may hinder analysis. The guide lists “Pointer Limitations” and “Multi-Access Pointers on the Interface”.
- System calls, OS-level dependencies, standard I/O or file I/O – these aren’t synthesizable hardware constructs. “System Calls” is explicitly listed.
- Undefined behavior in C/C++ (e.g., uninitialized variables, out-of‐bounds access) – this obviously undermines predictable hardware generation.
In short: aim for deterministic control flow, fixed memory footprints, loop bounds you can analyze, and avoid dynamic or highly‐dynamic constructs. The closer your algorithm resembles a data-flow pipeline or streaming processing engine, the better suited it is for HLS.
Analyzing Results and Tuning Performance
Once you’ve run synthesis in Vitis HLS, you’ll want to verify correctness and analyze performance, resource utilization, and timing to ensure your design meets requirements.
Key Outputs and Metrics
Some critical metrics and reports include:
- Latency and Initiation Interval (II): Latency is the number of cycles from input to output; II is the number of cycles between successive inputs. Lower II = higher throughput. The schedule viewer shows this.
- Clock period (target vs achieved): The tool will report whether your design meets the target frequency you specified. The schedule/binding viewer gives this.
- Resource Utilization: Estimates of LUTs, FFs (flip-flops), DSPs, BRAMs used by your design. You’ll need to compare against the target FPGA/SoC budget. The guide’s “Resource Usage” sections help.
- Interface summary: Are your top-level ports mapped correctly (AXI4, AXI4-Lite, Streams)? Are burst transfers or DMA interfaces optimized? The guide has detailed memory/interface modelling.
- Schedule view & dataflow view: Visualizations of how loops and functions have been scheduled, pipelined, or unrolled. These are extremely useful for spotting bottlenecks.
Verification & Co-simulation
After C synthesis you perform C/RTL co-simulation to ensure the generated RTL produces the correct results. The guide includes “Running C/RTL Co-Simulation,” “Cosim Deadlock Detection,” “Timeline Trace Viewer”.
Performance Tuning Tips
- If II is too high or latency unacceptable: apply #pragma HLS pipeline to loops or functions, consider #pragma HLS dataflow to overlapping processing stages.
- If resource usage is too high: try sharing resources (allocation directive), reduce unrolling, or restructure data paths. UG1399 lists “Managing Area and Hardware Resources” in the Design Principles section.
- If memory bandwidth is the bottleneck: partition arrays, reshape memories, increase burst transfer size, or use multiple AXI interfaces. The guide’s “Optimizing AXI System Performance” and “Array Partitioning” are relevant.
- Use the schedule viewer and dataflow analysis to identify idle cycles or dependencies that prevent pipelining/unrolling efficiency.
- Insert pragmas early: for example, #pragma HLS loop_tripcount, #pragma HLS interface, #pragma HLS latency to give the tool better information. These are listed in the directives list.
Why HLS Matters
The benefits of HLS are compelling for the right use-cases:
- Faster design cycles & algorithm reuse
Because you start from C/C++ code, you avoid the steep HDL ramp-up. Software engineers can participate directly, and you iterate logic rapidly. - Design‐space exploration and performance tuning
HLS enables you to try different architectures (loop unrolling, pipelining, data‐flow, memory partitioning) without re‐writing full HDL from scratch. This makes exploring throughput vs. area trade-offs much more practical. - Hardware acceleration of algorithmic kernels
HLS is ideal or image/video processing, machine learning inferencing, signal processing, encryption/decryption, and other compute-intensive tasks. If your algorithm is “software first” but you want the benefits of FPGA hardware acceleration (parallelism, custom data widths, streaming), then HLS is a strong choice. - Lower barrier to hardware entry
Teams that traditionally are software‐centric but pushing into hardware acceleration can adopt HLS to shorten the learning curve and time to prototype.
Who benefits, and when?
You benefit from HLS if you are:
- A software or firmware engineer needing to off-load compute to FPGA or SoC fabric
- A hardware designer who wants faster turnaround for algorithmic blocks
- A system architect that wants to evaluate multiple hardware implementation options quickly
You should consider using HLS when:
- The logic you’re implementing is algorithmically intensive and has regular structure (loops, arrays, streaming)
- You care about performance (throughput, latency) but also want design productivity
- You want to reuse existing C/C++ code or reduce manual HDL work.
- Explore multiple architectures quickly rather than committing to one HDL variant
On the flip‐side: for very low-level glue logic, timing-constrained state machines, or highly optimized custom RTL, traditional HDL may still be preferable.
Summary: When to Use HLS with Vitis HLS
Traditional VHDL and Verilog design remains essential for many FPGA and SoC projects. They produce predictable, efficient, and fully deterministic hardware designs.
HLS has its role when accelerating algorithmic, compute-intensive code written in C or C++. It enables faster exploration of parallelism, pipelining, and hardware acceleration.
Using Vitis HLS, engineers can:
- Start from familiar C/C++ code
- Apply HLS directives to tune performance and resource use
- Generate synthesizable RTL efficiently
- Verify functionality and analyze timing, latency, and utilization
- Integrate the generated IP into a full system
In short, HLS complements HDL. It works best for high-level algorithms that benefit from rapid iteration and parallelism.
BLT’s engineers use tools like Vitis HLS to help clients accelerate development, optimize performance, and bring custom FPGA and SoC designs to market faster. If your team is evaluating HLS or migrating existing algorithms to hardware, contact BLT to see how we can help.
Resources
AMD Vitis High-Level Synthesis User Guide (UG1399)
This comprehensive guide provides detailed information on using the AMD Vitis™ High-Level Synthesis tool, including design principles, supported constructs, and performance tuning.
Obtaining a Vitis HLS License
Provides steps to obtain a license for using the Vitis HLS tool, including host selection and license assignment.
Tutorials and Examples
Offers practical examples and tutorials to help you get started with Vitis HLS, including code samples and walkthroughs.
Vitis HLS Key Documents and Getting Started FAQ
A collection of essential documents and frequently asked questions to assist you in starting with Vitis HLS.
Vitis HLS Introductory Examples on GitHub
A repository of introductory examples covering scripted and command-line migration flows to Vitis Unified IDE.


