rules_vivado
Bazel rules for Xilinx Vivado FPGA synthesis, placement, routing, and bitstream generation.
Overview
rules_vivado wires Xilinx Vivado into Bazel as a set of ordinary build
and test rules. HDL sources flow in through
rules_verilog
(VerilogInfo) and
rules_vhdl
(VhdlInfo); the same *_library targets can be reused for simulation
and synthesis. The build phases are each their own rule
(vivado_synthesize,
vivado_placement,
vivado_routing,
vivado_write_bitstream, …) so checkpoints are
cached between phases, or you can chain the whole flow with the
vivado_flow macro.
The Xilinx install itself is resolved via a registered
vivado_toolchain — there is no per-target install
path to configure once a toolchain is in place.
Quick start
The walkthrough below takes a Verilog top module from source to
bitstream with the vivado_flow macro.
MODULE.bazel
bazel_dep(name = "rules_verilog", version = "1.1.1")
bazel_dep(name = "rules_vhdl", version = "0.1.1")
bazel_dep(name = "rules_vivado", version = "{version}")
register_toolchains("//tools/vivado:vivado_toolchain")
A vivado_toolchain is mandatory — every vivado_* rule resolves
the Xilinx install through it. See Toolchains for
how to author one.
tools/vivado/vivado.sh
#!/usr/bin/env bash
exec /opt/Xilinx/Vivado/2024.2/bin/vivado "$@"
Mark it executable: chmod +x tools/vivado/vivado.sh.
tools/vivado/BUILD.bazel
load("@rules_vivado//vivado:toolchain.bzl", "vivado_toolchain")
vivado_toolchain(
name = "vivado_local",
vivado = "vivado.sh",
env = {
"XILINXD_LICENSE_FILE": "2100@license.example.com",
"HOME": "/tmp",
},
)
toolchain(
name = "vivado_toolchain",
toolchain = ":vivado_local",
toolchain_type = "@rules_vivado//vivado:toolchain_type",
)
See Toolchains for license-server and multi-version setup.
hello/hello.sv
module hello (
input wire clk,
input wire rst,
output reg led
);
always_ff @(posedge clk) begin
if (rst) led <= 1'b0;
else led <= ~led;
end
endmodule
hello/BUILD.bazel
load("@rules_verilog//verilog:defs.bzl", "verilog_library")
load("@rules_vivado//vivado:defs.bzl", "vivado_flow")
verilog_library(
name = "hello",
srcs = ["hello.sv"],
data = ["hello.xdc"],
)
vivado_flow(
name = "hello_bitstream",
module = ":hello",
module_top = "hello",
part_number = "xczu28dr-ffvg1517-2-e",
)
Build it
$ bazel build //hello:hello_bitstream
$ ls bazel-bin/hello/
hello_bitstream.bit hello_bitstream_route.dcp ...
vivado_flow is a convenience macro — it expands to the per-phase
rules below so each checkpoint is cached on its own:
hello_bitstream_synth— synthesis (.dcp)hello_bitstream_synth_opt— post-synthesis optimizationhello_bitstream_placement— placementhello_bitstream_place_opt— post-placement optimizationhello_bitstream_route— routinghello_bitstream— final.bit
Build any one of them directly to stop the flow early or to inspect intermediate reports.
Going further
- Toolchains — author a
vivado_toolchain, register multiple versions, gate them with constraints and platforms. - Rules — every public rule, indexed by build phase.