Skip to content

MIT-OpenCompute/xilinx-flake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

313 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Xilinx for Nix users

forked from https://gitlab.com/asmir.abdulahovic/nix-xilinx - Adapted to run newer vivado versions

This repo is a collection of files that should help Nix and NixOS users install Xilinx’s software tools - Vivado & Vitis imperatively.

This includes the necessary packages containing the necessary linkers to install & run the full software suite.

Install

Like any other distro user, you should first go to your Xilinx account at: https://www.xilinx.com/support/download.html and download the installation .tar file. To extract run tar xvf FPGA*.tar To run this installer, you must enter in the shell. (DO NOT TRY TO RUN THE .BIN YOU WILL NOT HAVE A GOOD TIME) This tarball is rather large after extraction. Make sure you have roughly 300 GB to spare. (don’t worry, you can delete the zip and download folder later)

Run xilinx-shell with stable Nix > 2.3

nix run github:MIT-OpenCompute/xilinx-flake#xilinx-shell

Installation of vivado & vitis themselves

Installing vivado using .bin sucks install the full tarball and install directly in the command line.

./xsetup -b ConfigGen

Go to ~/.Xilinx/install_config.txt and edit the configuration file Here is an example of what I have as my config as I need a certain Vivado tool for my specific FPGA.

#### Vivado ML Standard Install Configuration ####
Edition=Vivado ML Standard

Product=Vivado

# Path where AMD FPGAs & Adaptive SoCs software will be installed.
Destination=/home/kaitotlex/Xilinx

# Choose the Products/Devices the you would like to install.
Modules=xcv80:0,Zynq UltraScale+ MPSoCs:1,Kintex UltraScale+ FPGAs:0,Virtex UltraScale+ 58G FPGAs:0,xcve2202:0,Vitis Model Composer(A toolbox for Simulink):1,Artix-7 FPGAs:0,Install devices for Alveo and edge acceleration platforms:0,Vitis Embedded Development:0,xcvm1102:0,Zynq-7000 All Programmable SoC:0,xcve2002:0,Virtex UltraScale+ HBM FPGAs:0,Spartan UltraScale+:0,xcve2302:0,Vitis Networking P4:0,Kintex UltraScale FPGAs:0,Power Design Manager (PDM):0,Virtex UltraScale+ FPGAs:0,Artix UltraScale+ FPGAs:0,Spartan-7 FPGAs:0,DocNav:1,Versal RF Series ES1:0,Install Devices for Kria SOMs and Starter Kits:0,xcve2102:0,Kintex-7 FPGAs:0

# Choose the post install scripts you'd like to run as part of the finalization step. Please note that some of these scripts may require user interaction during runtime.
InstallOptions=Acquire or Manage a License Key:0

## Shortcuts and File associations ##
# Choose whether Start menu/Application menu shortcuts will be created or not.
CreateProgramGroupShortcuts=1

# Choose the name of the Start menu/Application menu shortcut. This setting will be ignored if you choose NOT to create shortcuts.
ProgramGroupFolder=AMD Adaptive SoC and FPGA Tools

# Choose whether shortcuts will be created for All users or just the Current user. Shortcuts can be created for all users only if you run the installer as administrator.
CreateShortcutsForAllUsers=0

# Choose whether shortcuts will be created on the desktop or not.
CreateDesktopShortcuts=1

# Choose whether file associations will be created or not.
CreateFileAssociation=1

Then, run ./xsetup -a XilinxEULA,3rdPartyEULA,WebTalkTerms -b Install -c $HOME/.Xilinx/install_config.txt to install the entire application.

Adding the executables to your system

With what was done now, you can run vivado / vitis from the command line with:

nix run github:MIT-OpenCompute/xilinx-flake#vivado

Use nix search github:MIT-OpenCompute/xilinx-flake to view all other packages defined.

It’s likely you’d like to make the FHS environment survive garbage collections and add a desktop launcher to your system. To do that you can follow one of the following paths according to your setup.

For NixOS users with a flakes setup

inputs = {
  # ...
  nix-xilinx = {
    # Recommended if you also override the default nixpkgs flake, common among
    # nixos-unstable users:
    #inputs.nixpkgs.follows = "nixpkgs";
    url = "github:MIT-OpenCompute/xilinx-flake";
  };
  # ...
  outputs = { self, nixpkgs, nix-xilinx }:
  let
    flake-overlays = [
      nix-xilinx.overlay
    ];
  in {
    nixosConfigurations = (
      HOSTNAME = nixpkgs.lib.nixosSystem {
        modules = [ (import ./configuration.nix flake-overlays) ]
      };
    };
  };
};

And in ./configuration.nix:

# All overlays given by flakes
flake-overlays:

{ config, pkgs, options, lib, ... }:
{
  nixpkgs.overlays = [
    (
      final: prev: {
        # Your own overlays...
      }
    )
  ] ++ flake-overlays;
}

Example evaluated here and here.

For NixOS users without a flakes setup

The following setup should also fit flake NixOS users.

Add to your configration.nix (untested, but should work):

  nixpkgs.overlays = let
    nix-xilinx = import (builtins.fetchTarball "https://gitlab.com/doronbehar/nix-xilinx/-/archive/master/nix-xilinx-master.tar.gz");
  in [
    nix-xilinx.overlay
    (
      final: prev: {
        # Your own overlays...
      }
    )
  ];

Usage in Other Flakes / shell.nix

Some people may wish to not install xilinx' tools globally, and only making it part of the buildInputs of their project. Usually this paradigm follows along with direnv
shell.nix / flake.nix setup. For example you can create in your project a shell.nix, or define devShell in your flake.nix similarly to this:

{ pkgs, nix-xilinx }:

pkgs.mkShell {
  buildInputs = (with nix-xilinx.packages.x86_64-linux; [
    vivado
    vitis
  ]);
  # Define some probably useful environment variables
  shellHook = nix-xilinx.shellHooksCommon;
}

Note that xilinx' tools still need to be installed in a user-writeable location for this shellHook to work, as explained here.

Headless Server Module

This flake also ships a NixOS module that runs the standard Xilinx server daemons as systemd services. Server machines can expose Vivado’s hardware-manager, floating-license, and ChipScope capabilities to the network without installing a full desktop environment.

The three services map directly to what Xilinx ships:

Service Default port Purpose

xilinx-hw-server

3121 TCP

JTAG hardware target server. Remote Vivado Hardware Manager sessions connect here to program and debug FPGAs. This is the same daemon you launch with hw_server on any Linux workstation.

xilinx-lmgrd

27000 TCP + vendor port

FlexLM floating licence server. Clients set XILINXD_LICENSE_FILE=@<server> to check out tool licences from the network.

xilinx-cs-server

3042 TCP

ChipScope / ILA analysis server. Used by Vivado Hardware Manager for in-system logic analysis over a network connection.

Adding the module to a server flake

# flake.nix on the server machine
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    xilinx-flake.url = "github:MIT-OpenCompute/xilinx-flake";
  };

  outputs = { self, nixpkgs, xilinx-flake }: {
    nixosConfigurations.my-fpga-server = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        xilinx-flake.nixosModules.vivado-server
        ./configuration.nix
      ];
    };
  };
}

Configuring the services

Add the following to the server’s configuration.nix (or any imported module):

services.vivadoServer = {
  enable = true;

  # Path to the Xilinx imperative installation on this machine
  installDir = "/opt/Xilinx";
  version    = "2025.2";    # must match the installed release directory

  # hw_server — remote JTAG / Hardware Manager
  hwServer = {
    enable      = true;
    port        = 3121;      # Xilinx default, clients expect this
    openFirewall = true;
  };

  # lmgrd — floating licence server
  licenseServer = {
    enable      = true;
    port        = 27000;     # FlexLM default
    vendorPort  = 27001;     # must match "VENDOR xilinxd port=27001" in the .lic
    licenseFile = /etc/xilinx/Xilinx.lic;
    openFirewall = true;
  };

  # cs_server — ChipScope / ILA (optional)
  csServer = {
    enable      = true;
    port        = 3042;
    openFirewall = true;
  };

  # remoteRuns — SSH host for "Launch runs on remote hosts"
  remoteRuns = {
    enable      = true;
    # Paste the SSH public key from each client workstation that will
    # submit synthesis / implementation jobs via the Vivado dialog.
    authorizedKeys = [
      "ssh-ed25519 AAAA... engineer@workstation"
    ];
    # This directory is what you enter in Vivado's "Configure Hosts"
    # dialog under "Remote working directory".
    workDir     = "/var/lib/vivado-remote";
    # "@localhost" works when licenseServer.enable = true on this machine.
    licenseFile = "@localhost";
    openFirewall = true;   # opens port 22 if not already open
  };

  # hdlBuild — CLI batch build host for the ichika workflow
  # (see "ichika CLI workflow" section below)
  hdlBuild = {
    enable      = true;
    # Paste the SSH public key from each developer's machine.
    authorizedKeys = [
      "ssh-ed25519 AAAA... dev@laptop"
    ];
    workDir     = "/var/lib/vivado-remote";
    licenseFile = "@localhost";   # omit or null if no local license server
    openFirewall = true;
  };
};
Note
installDir must point to a Xilinx installation already present on the server’s filesystem. The Nix module does not install Vivado — follow the Install section above to perform the imperative installation first, then point this option at the result.

License file vendor port

The FlexLM vendor daemon (xilinxd) picks its port from the license file. Add a fixed port line so that openFirewall = true can open the right port:

SERVER my-fpga-server 000000000000 27000
VENDOR xilinxd port=27001
...

Connecting from a client workstation

After the server is running, configure client machines:

# Connect Vivado Hardware Manager to a remote hw_server
# In Vivado Tcl console or batch script:
open_hw_manager
connect_hw_server -url my-fpga-server:3121

# Point all Vivado instances at the floating licence server
export XILINXD_LICENSE_FILE=@my-fpga-server

Remote synthesis and implementation (GUI workflow)

This corresponds to the "Launch runs on remote hosts" option in Vivado’s Run Settings dialog (Flow → Run Settings or right-click a run in the Design Runs panel).

  1. Generate an SSH key pair on the client workstation if you do not already have one:

    ssh-keygen -t ed25519 -f ~/.ssh/id_vivado_remote
  2. Add the public key (~/.ssh/id_vivado_remote.pub) to services.vivadoServer.remoteRuns.authorizedKeys in the server’s NixOS configuration and rebuild.

  3. In Vivado, open Tools → Options → Remote Hosts (or click Configure Hosts in the Launch Runs dialog) and add a new host:

    Field Value

    Hostname

    my-fpga-server (or IP address)

    Username

    vivado (value of services.vivadoServer.user)

    SSH private key

    ~/.ssh/id_vivado_remote

    Remote Vivado installation

    Leave blank — the module puts vivado in PATH automatically

    Remote working directory

    Value of services.vivadoServer.remoteRuns.workDir (default: /var/lib/vivado-remote)

  4. Select Launch runs on remote hosts in the Run Settings dialog, choose the host you configured, and click OK. Vivado will SSH into the server and run synthesis/implementation in batch mode there; results are copied back automatically.

Note
Vivado invokes the remote command as bash --login -c "vivado -mode batch …​". The module injects the FHS-wrapped vivado binary into PATH via /etc/profile.d/xilinx-remote-runs.sh, which is sourced by all login shells including non-interactive SSH sessions initiated this way.

ichika CLI workflow

The ichika flake (github:kaitotlex/ichika) provides a lightweight alternative to the Vivado GUI remote-run workflow. Developers write HDL in any editor, and a pair of nix run commands handle all communication with the build server — no Vivado GUI required on the client machine.

Server prerequisites

Enable services.vivadoServer.hdlBuild as shown in the configuration example above and rebuild the server:

nixos-rebuild switch

The module will:

  • Create or update the vivado system user with a login shell.

  • Install the provided SSH public keys as authorized_keys.

  • Place a FHS-wrapped vivado binary in PATH for all login shells.

  • Create the build working directory (workDir).

Client project setup

From any HDL project directory, initialise an ichika-aware flake:

nix flake init -t github:kaitotlex/ichika

Edit the generated flake.nix to set your top module name, FPGA part string, RTL source directories, and server address:

hdlApps = ichika.lib.makeHdlApps {
  inherit pkgs;
  top         = "my_top";               # Verilog top module
  part        = "xczu3eg-sfvc784-1-e";  # FPGA part string
  rtlDirs     = [ "rtl" ];              # relative dirs rsync'd from $PWD
  serverLocal = "10.0.0.228";           # LAN IP
  # serverDns  = "build.example.com";   # optional public DNS name
};

Or add ichika to an existing project’s flake inputs and call makeHdlApps inside eachDefaultSystem.

Running a build

# Run synthesis only (useful for checking for synthesis errors quickly)
nix run .#synthesize

# Run the full pipeline: synthesis → opt → place → route → bitstream
# Copies <top>.bit to the current directory when done
nix run .#run-impl

Both commands rsync whatever is currently in the configured rtlDirs on disk — no nix build is required to pick up source edits.

Switching between local and DNS addresses

# Default: uses serverLocal (LAN IP)
nix run .#run-impl

# Override with an explicit address
ICHIKA_SERVER=build.example.com nix run .#run-impl

# Use serverDns (if configured in the flake)
ICHIKA_USE_DNS=1 nix run .#run-impl

hdlBuild module options

Option Default Description

hdlBuild.enable

false

Enable the SSH-based CLI batch build host.

hdlBuild.authorizedKeys

[]

SSH public keys for developer machines submitting ichika builds.

hdlBuild.workDir

/var/lib/vivado-remote

Base directory for per-project build artifacts. ichika creates a sub-directory per top module name here.

hdlBuild.licenseFile

null

XILINXD_LICENSE_FILE injected into batch Vivado processes. Set to @localhost when licenseServer.enable = true. Falls back to the remoteRuns.licenseFile value if that service is also enabled.

hdlBuild.openFirewall

false

Opens SSH port 22 in the firewall. Shared with remoteRuns.openFirewall — either flag being true opens the port.

Nginx stream proxy

Because hw_server, lmgrd, and cs_server all speak raw TCP (not HTTP), nginx must be configured with the stream module to proxy them. This is useful for TLS termination, access control, or exposing a single public IP.

In NixOS, services.nginx.streamConfig appends raw nginx config inside the stream {} block:

services.nginx = {
  enable = true;

  # The stream block is separate from the http block.
  streamConfig = ''
    # hw_server — Vivado Hardware Manager remote target
    upstream xilinx_hw {
      server 127.0.0.1:3121;
    }
    server {
      listen 3121;
      proxy_pass xilinx_hw;
      proxy_timeout 1d;      # synthesis runs can be long
      proxy_connect_timeout 10s;
    }

    # lmgrd — FlexLM licence daemon
    upstream xilinx_lic {
      server 127.0.0.1:27000;
    }
    server {
      listen 27000;
      proxy_pass xilinx_lic;
    }

    # lmgrd vendor daemon (xilinxd) — must match vendorPort option
    upstream xilinx_vendor {
      server 127.0.0.1:27001;
    }
    server {
      listen 27001;
      proxy_pass xilinx_vendor;
    }

    # cs_server — ChipScope / ILA
    upstream xilinx_cs {
      server 127.0.0.1:3042;
    }
    server {
      listen 3042;
      proxy_pass xilinx_cs;
    }
  '';
};

# Ensure nginx can bind the non-HTTP ports
networking.firewall.allowedTCPPorts = [ 3121 27000 27001 3042 ];
Note
When using nginx as a TCP proxy for lmgrd, both the lmgrd port (27000) and the vendor daemon port (27001) must be proxied. FlexLM clients make two separate connections — one to lmgrd to locate the vendor daemon, and a second directly to the vendor daemon port.

Previous work / Credits

This repository is mostly copy paste from nix-matlab.

About

forked from https://gitlab.com/asmir.abdulahovic/nix-xilinx, adapted for new Vivado versions.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages