The Joy of Ansible
Table of contents
Or how to automate your computing
Preface
During my 4th semester of my 3-Year EE Bachelor, I’ve been introduced to the topic of FPGAs and their programming.
These chips allow EE Engineers to create circuits capable of emulating simple CPUs1 or ASICs, perform precise signal processing in a flexible frequency range while being much less expensive than a conventional DSP2. The catch is that the generated layout can easily be sent to a Silicon Fab (like Intel, TSMC, etc..) to create a discrete chip have the cited functions in-silicon instead of needing to program it.
As an example, I used them during this course to create a simple Siekoo3 display from scratch and a timing circuit for a alarm clock on the DE2-115 board from Terasic4.
While it’s a very capable board, let’s just say the toolchain install procedure and code upload wasn’t as smooth. But more on that later.
What is an FPGA?
If you know what a FPGA is or want to jump to the meat and potatoes of this post, click here.
According to Digikey, an FPGA is :
[…], I like to think of an FPGA as a box of colorful, non-trademarked building blocks for creating digital circuits. I can connect the blocks together any way that I want to fit my application.
To be more specific, an FPGA is a chip containing multiple programmable logic gates that can be arranged to create the program’s functions (if...else, switch ... case, etc...
).
This is often achieved by using a Hardware Markup Language, in which the functions are written and then converted in gate configuration by the Synthesis Middleware. The produced configuration and machine code, called a bitstream5, can then be simulated or sent to a devkit.
The main used languages during this phase are VHSIC Hardware Description Language (VHDL) and Verilog.
The former looks like the Ada language and the latter like C. (I’ll let you choose you poison)
Both languages are used by the two major players in this industrial sector. Xilinx/AMD manufactures the UltraScale+ family which included the Spartan an Artix models, while Altera manufactures the Cyclone and Agilex family.
Both supply a toolchain with an IDE, Synthesis tool and Linker which expects certain specific libraries or versions of the libraries. This can lead to package conflicts and incompatibilities on Linux Systems, specifically on more niche distributions or when using certain drivers for the JTAG/SWD programmer.
In the context of this blog post, we’ll focus on the Altera Quartus IDE version 20.1 since i’ts the one the Hochschule für Technik, Wirtschaft und Medien Offenburg uses during these courses, but bear in mind that most of the problems I’ll list still apply to the latest version at the time (Quartus 24.1).
Quartus IDE & Ansible
The Quartus IDE is the front-end tool used to program Altera FPGAs. From its interface, you can select the target hardware, create the pin layout and associate them with program variables, generate the bitstream and program the FPGA.
While using it versus a text editor and CLI tools has a large amount of benefits, the installation and setup procedure on Linux is riddled with quirks and bugs that make you ask why does it do that?
Problem(s)
First, Quartus isn’t packaged for easy installation on distros like Fedora/Ubuntu. No
*.deb
,.rpm
,*.flatparref
, Intel only gives*.run
executables for ModelSim and Quartus, so if you only used the GUI (GNOME Software/KDE Discover/etc…) to install software, it’s time to learn to use the terminal since you’ll need to install the dependencies by hand and execute the install script.Second, the IDE uses a mix of 32-bit and 64-bit libraries. This means you need which can lead to some breakage on the user’s system and selecting the correct version can be a pain. Most notably
libc
, which contains the C basic system libraries needs to be installed in both x64 and x86 form. As for breakage, it becomes easy to uninstall a library that depends on one used by Quartus since*.run
files do not benefit from the security measures as the other package options give before.Third, Post-setup experience leaves much to be desired. What I mean by that things like nice-to-have (Desktop integration after install) aren’t working and quirks regarding the hardware connection can range from annoying (having to send the program once and retry after disconnecting-and-reconnecting since the toolchain has some … difficulties to talk to the ftdi driver) to simply unusable (OOTB udev rule not correctly installed and in old format, requiring user to manually edit it and reload them) are many.
These are a lot for a student to handle and can be a burden for IT departments to have to manually fix every machine, especially if they recently transitioned from Windows to Linux due to the end of support.
Solution
The solution was to use a container with a supported OS and to automate the installation and fixes in that container using Ansible, preventing the risk of system breakage and allowing its deployment to be scaled across the lab’s PC fleet.
The solution is composed of 2 parts:
- The Wrapper, which in consists of a
*.sh
script which:- Creates the container (here Ubuntu 22.04 LTS) by installing and using toolbx on the user’s OS.
- Installs Ansible and it’s dependencies on the guest and passes the playbook containing the install instructions to it.
- Creates the desktop icon, copies the fixed udev rule and fixes the initial ftdi handshake by copying the install-generated programmer configs after the payload’s execution.
#!/bin/bash
consent_key="y"
echo -e "#################################
# Quartus Auto-Setup script #
# Created for the HS Offenburg #
#################################\n"
echo "This Script allows you to install and configure the Quartus Environnement in an isolated way of your OS (to prevent breakage) and regardless of your OS."
echo -e "\n#################################
# What does it do? #
#################################\n
This Script uses toolbx to create an OS container (here Ubuntu LTS) separated from the host OS.
The dependencies and tools are after that installed in that container.\n"
echo "Do you want to proceed? enter "y" to accept or any other letter to exit."
while true; do
read -n 1 -s key
if [[ $key = $consent_key ]]; then
echo -e "\nYou pressed "y", starting script. "
echo -e "Installing toolbx with your package manager. You will need to enter your sudo password. Please be careful."
if [ -f /etc/os-release ]; then
. /etc/os-release
if [ "$NAME" = "Fedora Linux" ]; then
sudo dnf update --refresh -y
sudo dnf install toolbox -y
fi
if [ "$NAME" = "Ubuntu" ]; then
sudo apt update -y
sudo apt install podman-toolbox -y
fi
echo "Creating Ubuntu Container"
toolbox create quartus --image quay.io/toolbx/ubuntu-toolbox:22.04
echo "Installing Ansible in the container"
echo "(This is the tool used to automate the dependencies and Quartus installation)"
toolbox run -c quartus sudo apt update -y
toolbox run -c quartus sudo apt-get install -y software-properties-common
toolbox run -c quartus sudo add-apt-repository --yes --update ppa:ansible/ansible
toolbox run -c quartus sudo apt install -y ansible
echo "Executing setup playbook"
toolbox run -c quartus ansible-playbook playbook.yml -K -v
echo 'export PATH="$HOME/intelFPGA_lite/20.1/quartus/bin:$PATH"' >> $HOME/.bashrc
source .bashrc
mkdir $HOME/.icons
cp $HOME/intelFPGA_lite/20.1/quartus/adm/quartusii.png $HOME/.icons
cp misc/quartus.desktop ~/.local/share/applications/
update-desktop-database ~/.local/share/applications/
sudo cp misc/51-usbblaster.rules /etc/udev/rules.d/
sudo udevadm control --reload
sudo mkdir /etc/jtagd
sudo cp $HOME/intelFPGA_lite/20.1/quartus/linux64/pgm_parts.txt /etc/jtagd/agd.pgm_parts
exit
else
echo "Distribution is not Fedora or Ubuntu"
fi
break
else
echo -e "\nYou pressed another key than "y", exiting script."
exit
fi
done
- The Payload, which contains the main of the logic:
- It enables the 32-bit architecture and updates the system.
- Checks if the en_US locale exist. If not, it generates it (If absent, the install wizard fails).
- Installs the required dependencies and downloads the required files for installation (Checksum is done on every file to make sure they haven’t been tampered).
- Marks the
*.run
as executable and launches the wizard.
- hosts: localhost
pre_tasks:
- name: Enable 32-bit arch
command: sudo dpkg --add-architecture i386
become: yes
- name: Ensure a locale exists
command: sudo locale-gen en_US.UTF-8
become: yes
- name: Update locale database
command: sudo update-locale
become: yes
- name: Update all packages to their latest version
apt:
name: "*"
state: latest
become: yes
- name: install dependencies
apt:
name:
- libc6:i386
- libncurses5:i386
- libxtst6:i386
- libxft2:i386
- libstdc++6:i386
- libc6-dev-i386
- libxft2
- lib32z1
- lib32ncurses6
- libsm6
update_cache: yes
become: yes
- name: Create Folder to host install files
file:
path: Install_files/
state: directory
- name: Get files
debug:
msg: "This can take some time depending of your internet connection."
- name: Get ModelSim files
get_url:
url: https://downloads.intel.com/akdlm/software/acdsinst/20.1std.1/720/ib_installers/ModelSimSetup-20.1.1.720-linux.run
dest: Install_files/ModelSimSetup-20.1.1.720-linux.run
checksum: sha1:c50f51479de963f4e79a8115dc9200e744b3ab3d
- name: Get Quartus files
get_url:
url: https://downloads.intel.com/akdlm/software/acdsinst/20.1std.1/720/ib_installers/QuartusLiteSetup-20.1.1.720-linux.run
dest: Install_files/QuartusLiteSetup-20.1.1.720-linux.run
checksum: sha1:49012e487889041962575c1cde81863457c105f5
- name: Get Cyclone IV FPGA config files
get_url:
url: https://downloads.intel.com/akdlm/software/acdsinst/20.1std.1/720/ib_installers/cyclone-20.1.1.720.qdz
dest: Install_files/cyclone-20.1.1.720.qdz
checksum: sha1:5447aa416749edf5bae5f68dcc734c43e8db6a67
- name: Get Cyclone V FPGA config files
get_url:
url: https://downloads.intel.com/akdlm/software/acdsinst/20.1std.1/720/ib_installers/cyclonev-20.1.1.720.qdz
dest: Install_files/cyclonev-20.1.1.720.qdz
checksum: sha1:95709f12822c4efed0f70516b1588d43e69ae85b
tasks:
- name: Set Quartus installer executable
command: chmod +x QuartusLiteSetup-20.1.1.720-linux.run
args:
chdir: Install_files/
- name: Set Modelsim installer executable
command: chmod +x ModelSimSetup-20.1.1.720-linux.run
args:
chdir: Install_files/
- name: install Quartus
command: ./QuartusLiteSetup-20.1.1.720-linux.run
args:
chdir: Install_files/
To make it easier to visualize, here is a Mermaid diagram of the PoC:
Conclusion & Next Steps (maybe)
After completing the course, I’ve had the opportunity to talk with the FPGA lab IT chief and to demo the PoC. During that conversation, I learned that the HS Offenburg would migrate some of their PCs to Mageai Linux during the 2025/2026 academic year. Some modifications will be required on the finised product since Mageia doesn’t use DNF but those should be trivial (downloading the rpms instead).
I am really pleased with the final result of the project. What started as a simple bash setup script for some of my fellow students will help the HS Offenburg in the future Linux migration, which I’m really excited to see (Welcome to the Club!). It also allowed me to dable into Ansible, containers and the functionning of the udev subsystem. I’ve learnt a lot during this and added a shiny new tool to my belt, which may or may not be used in a future homelab… ;).
Lastly, I would like the Ansible community for maintaining such a powerfull tool, and to Jeff Geerling for his book Ansible for DevOps for giving me a detailled explanation on system management and playbook configuration.