69 个版本 (36 个重大更改)

0.46.0 2023年7月2日
0.44.2 2023年3月25日
0.41.1 2022年12月2日
0.38.6 2022年9月15日
0.2.0 2021年11月30日

#277 in 硬件支持

Download history 36/week @ 2024-03-11 33/week @ 2024-03-18 29/week @ 2024-03-25 89/week @ 2024-04-01 18/week @ 2024-04-08 26/week @ 2024-04-15 29/week @ 2024-04-22 39/week @ 2024-04-29 8/week @ 2024-05-06 35/week @ 2024-05-13 29/week @ 2024-05-20 48/week @ 2024-05-27 30/week @ 2024-06-03 26/week @ 2024-06-10 22/week @ 2024-06-17 25/week @ 2024-06-24

每月108 次下载
用于 10 个crates (9直接使用)

MIT 许可证

1MB
18K SLoC

rust-hdl

** 使用 Rust 编写 FPGA 固件!**

RustHDL 是一个 crate,允许您使用 Rust 编写 FPGA 固件!具体来说,rust-hdl 将 Rust 的子集编译成 Verilog,这样您可以使用标准工具为您的 FPGA 生成固件。它还提供了用于模拟、验证和分析的工具,以及强类型接口,以确保您的设计在前往测试台之前能够正常工作。工作流程与 GPU 编程非常相似。您使用 Rust 编写一切,包括编译到硬件上的更新 kernel。您可以在 Rust 环境的安全舒适中模拟和验证一切,然后转到标准综合工具以获取编程 FPGA 的文件。

您可能需要

特性

  • 安全 - 使用 Rust 在编译时通过强类型接口检查固件的合法性,同时在运行时、综合和设备上。
  • 快速 - 直接从 Rust 代码中运行您的设计的模拟,具有相当不错的模拟性能。
  • 可读性 - RustHDL 为综合和实现输出 Verilog 代码,并努力确保代码可读易懂,以防您需要解决时序问题或其他冲突。
  • 可重用性 - RustHDL 支持参数化使用的模板化固件,以及基于结构体的简单组合模型。
  • 内置工具 - RustHDL 包含一系列基本的固件小部件,提供 FIFO、RAM 和 ROM、触发器、SPI 组件、PWM 等,让您可以快速入门。
  • 免费 - 虽然您可以使用 RustHDL 封装现有的 IP 内核,但 RustHDL 代码和固件都是开源的,并且免费使用(即言论自由和啤酒自由)。
  • 经过测试 - RustHDL 已被用于编写在商业产品中发货的固件。这包括相当复杂的设计,这些设计几乎使用了中等大小 FPGA 的所有功能,并利用了 FPGA 本身的专用硬件。

快速入门

FPGA固件领域的 definitive example 是一个简单的LED闪烁器。这通常涉及到一个以预定义的频率馈送到FPGA的时钟,以及一个可以控制LED的输出信号。由于我们不知道使用的是哪种FPGA,我们首先在仿真中这样做。我们希望每秒闪烁250毫秒,时钟速度是(一个滑稽的慢)10kHz。下面是一个最小的可工作Blinky!示例

use std::time::Duration;
use rust_hdl::docs::vcd2svg::vcd_to_svg;
use rust_hdl::prelude::*;

const CLOCK_SPEED_HZ : u64 = 10_000;

#[derive(LogicBlock)]  // <- This turns the struct into something you can simulate/synthesize
struct Blinky {
    pub clock: Signal<In, Clock>, // <- input signal, type is clock
    pulser: Pulser,               // <- sub-circuit, a widget that generates pulses
    pub led: Signal<Out, Bit>,    // <- output signal, type is single bit
}

impl Default for Blinky {
   fn default() -> Self {
       Self {
         clock: Default::default(),
         pulser: Pulser::new(CLOCK_SPEED_HZ, 1.0, Duration::from_millis(250)),
         led: Default::default(),
       }
    }
}

impl Logic for Blinky {
    #[hdl_gen] // <- this turns the update function into an HDL Kernel that can be turned into Verilog
    fn update(&mut self) {
       // v-- write to the .next member     v-- read from .val() method
       self.pulser.clock.next = self.clock.val();
       self.pulser.enable.next = true.into();
       self.led.next = self.pulser.pulse.val();
    }
}

fn main() {
    // v--- build a simple simulation (1 testbench, single clock)
    let mut sim = simple_sim!(Blinky, clock, CLOCK_SPEED_HZ, ep, {
        let mut x = ep.init()?;
        wait_clock_cycles!(ep, clock, x, 4*CLOCK_SPEED_HZ);
        ep.done(x)
    });

    // v--- construct the circuit
    let mut uut = Blinky::default();
    uut.connect_all();
    sim.run_to_file(Box::new(uut), 5 * SIMULATION_TIME_ONE_SECOND, "blinky.vcd").unwrap();
    vcd_to_svg("/tmp/blinky.vcd","images/blinky_all.svg",&["uut.clock", "uut.led"], 0, 4_000_000_000_000).unwrap();
    vcd_to_svg("/tmp/blinky.vcd","images/blinky_pulse.svg",&["uut.clock", "uut.led"], 900_000_000_000, 1_500_000_000_000).unwrap();
}

运行上面的代码(强烈推荐使用发布运行)将生成一个vcd文件(这是FPGA和硬件的一般跟踪文件)。您可以使用例如gtkwave打开此文件。如果您有Alchitry Cu板,您可以通过单次调用为这个例子生成位流。这稍微复杂一些,所以我们将详细说明。它还将把那个vcd文件转换为svg,您可以用普通网页浏览器查看。这是整个模拟的最终结果:blinky_all以下是放大显示LED脉冲的图片:blinky_pulse

RustHDL背后的流程如下

  • 电路使用简单的struct进行建模,由其他电路元素和连接它们的信号线组成。
  • 在结构体上添加#[derive(LogicBlock)]注解,为RustHDL添加自动生成的代码。
  • 在您的struct上实现impl Logic,并提供一个fn update(&mut self)方法,这是HDL更新内核。
  • 它被标注为#[hdl_gen]属性,从Rust代码生成HDL
  • 然后您可以模拟和综合您的设计——无论是通过软件,还是使用适当的BSP和工具链。

其余的都是细节。一些需要注意的最终事项。

  • RustHDL是Rust的一个严格的子集。Rust编译器必须首先满足您的设计。这意味着类型、穷举枚举匹配等。
  • 目标是消除在其他HDL中容易犯的一类错误,通过编译时的检查、运行时的静态分析和测试平台来实现。
  • 尽管性能总是可以改进,但RustHDL相当快,尤其是在发布模式下。

许可证:MIT

依赖项

~8.5MB
~149K SLoC