#verilator #bindings #attr #build

ferrilator

A tool intended to simplify writing Verilator tests in Rust

5 releases (breaking)

Uses new Rust 2024

0.5.0 Oct 16, 2025
0.4.0 Oct 14, 2025
0.3.0 Oct 3, 2025
0.2.0 Sep 9, 2025
0.1.0 Sep 8, 2025

#860 in Procedural macros

Download history 1518/week @ 2025-12-17 976/week @ 2025-12-24 757/week @ 2025-12-31 381/week @ 2026-01-07 295/week @ 2026-01-14 268/week @ 2026-01-21 1043/week @ 2026-01-28 991/week @ 2026-02-04 1075/week @ 2026-02-11 1080/week @ 2026-02-18 678/week @ 2026-02-25 1092/week @ 2026-03-04 1931/week @ 2026-03-11 2003/week @ 2026-03-18 1521/week @ 2026-03-25 946/week @ 2026-04-01

6,663 downloads per month

MIT license

30KB
709 lines

Ferrilator

For writing Verilator tests in Rust.

There are two main parts; binding generation and build orchestration.

Bindings for your top module can be generated like this:

use ferrilator::attr::ferrilate;

#[ferrilate(counter)]
struct Counter {
    #[clock]
    #[input]
    clk: bool,

    #[input]
    reset: bool,

    #[input]
    enable: bool,

    #[output]
    value: u8,

    #[output]
    overflow: bool,
}

and tests can then be written like this:

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_counter() {
        let mut dut = Counter::new();
        dut.set_enable(true);

        dut.tick();
        assert_eq!(0, dut.get_value());
        assert_eq!(false, dut.get_overflow());

        dut.tick();
        assert_eq!(1, dut.get_value());
        assert_eq!(false, dut.get_overflow());

        dut.tick();
        assert_eq!(2, dut.get_value());
        assert_eq!(false, dut.get_overflow());

        dut.set_reset(true);
        dut.tick();
        assert_eq!(0, dut.get_value());
        assert_eq!(false, dut.get_overflow());

        dut.set_reset(false);
        dut.set_enable(false);

        for _ in 0..10 {
            dut.tick();
            assert_eq!(0, dut.get_value());
            assert_eq!(false, dut.get_overflow());
        }

        dut.set_enable(true);

        for i in 0..255 {
            assert_eq!(i, dut.get_value());
            assert_eq!(false, dut.get_overflow());
            dut.tick();
        }

        dut.tick();
        assert_eq!(0, dut.get_value());
        assert_eq!(true, dut.get_overflow());

        dut.tick();
        assert_eq!(1, dut.get_value());
        assert_eq!(false, dut.get_overflow());
    }
}

The full Verilator build can be run from your build.rs like this:


fn main() {
    ferrilator::build("Counter", "src/counter.rs", &["src/hdl/counter.sv"]).unwrap();
}

Dependencies

~300–720KB
~17K SLoC