| Crates.io | ruverta |
| lib.rs | ruverta |
| version | 0.1.0 |
| created_at | 2024-12-03 04:56:04.880785+00 |
| updated_at | 2024-12-03 04:56:04.880785+00 |
| description | Rust to Verilog: Very Simple Verilog Builder |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1469669 |
| size | 76,272 |
Supports only a simple subset of SystemVerilog.
logic is available. No reg or wire.always_comb is available. No assign.always_ff is available. No always.Table of Contents
$ cargo add ruverta
| Rust | SystemVerilog |
|---|---|
|
|
.input(name, width).output(name, width).inout(name, width).param(name, default_value).lparam(name, value).logic(name, bit, len).instant(inst: Instant).always_comb(stmt: Stmt)Stmt is a class representing a statement.
.always_ff(Sens, Stmt)Sens is a class representing a sensitivity list.
.posedge(wire_name).negedge(wire_name).bothedge(wire_name)Generate Verilog with .verilog(). Since it returns Vec<String>, use .join("\n") to concatenate.
The API design is quite rough, so feel free to request anything~
Extend the builder methods of Module to easily construct various circuits.
When implementing sequential circuits, it is recommended to use sync_ff / async_ff api instead of always_ff.
DFF has several usage patterns depending on the clock and reset settings.
Currently, only the following patterns are supported.
| clock edge | reset logic | reset timing | |
|---|---|---|---|
sync_ff |
posedge | negative | sync |
async_ff |
posedge | negative | async |
Module::new(name)
.input("clk", 1)
.input("rstn", 1)
.input("in0", 8)
.input("in1", 8)
.output("out", 8)
.sync_ff(
"clk",
"rstn",
Stmt::begin().assign("out", "0").end(),
Stmt::begin().assign("out", "in0 + in1").end(),
);
When implementing combinational circuits, it is recommended to use comb instead of always_comb.
Since it always requires a default, there are no omissions in case distinctions.
Module::new(name)
.input("clk", 1)
.input("rstn", 1)
.input("hoge", 1)
.comb(
Comb::new()
.input("in0")
.input("in1")
.output("out0")
.output("out1")
.case("in0==0", "out0=0", "out1=0")
.default("0", "1"),
);
Construct a state machine with a single state variable.
Module::new(name)
.input("clk", 1)
.input("rstn", 1)
.input("hoge", 1)
.sync_fsm(
FSM::new("init", "clk", "rstn")
.state("init")
.jump("hoge == 1", "fuga")
.r#else("init")
.state("fuga")
.jump("hoge == 0", "init")
.r#else("fuga"),
);
| Rust | Verilog | Test | |
|---|---|---|---|
| AXILiteSlave | axi_lite_slave.rs | axi_lite_slave.sv | axi_lite_slave_tb.sv |
| PicoSlave |
Module::new(name)
.input("clk", 1)
.input("rstn", 1)
.axi_lite_slave(
"clk",
"rstn",
AXILiteSlave::new(
"cbus",
MMap::new(32, 32)
.read_write("csr_rw", 8, 2)
.read_only("csr_ro", 8, 1)
.trigger("csr_tw"),
),
);
Tests are located under tests.
$ cargo test
will output sv files under tests/verilog/.
Running make will launch gtkwave.
ruverta/tests/verilog$ make ???
??? is the name of the test case.