Expand description
! Prelude module defines common symbols to make importing RustHDL easier.
Re-exports
pub use crate::docs::vcd2svg::vcd_to_svg;
Modules
Macros
- The [clock!] macro is used to connect a set of devices to a common clock. The macro takes a variable number of arguments:
Structs
- A BitSynchronizer is used to move signals that are asynchronous to a clock into that clock domain using a pair of back-to-back flip-flops. While the first flip flop may become metastable, the second one is likely to be stable.
- The BlackBox struct provides a way to wrap a blackbox, externally provided IP core.
- Fundamentally a Clock signal in RustHDL is simply a transparent wrapper around a boolean valued signal. So it could be thought of as a simple 1-bit wide signal. However, semantically, clocks are rarely treated like other signals, and typically connect only to dedicated clock ports on synchronous logic (like [DFF] or [RAM]).
- The Constant wrapper can hold any Synth type and store it in a circuit for use by the HDL kernel. This is the easiest way to compute complex constants in your RustHDL constructors, and then store the results inside the circuit for later use. Unlike Signal, Constant does not have a
.next
field, so you cannot assign to a Constant in the HDL kernel (blocked at compile time). Note that Constant does notimpl Default
. You must construct it with the appropriate value when the circuit is built. - This direction marker is used for a [Signal] that is an input with respect to a circuit. That means that we do not expect to write to the input, but that the value will be set by external components to the circuit.
- This direction marker is used for a [Signal] that leaves a circuit as an output. That means we expect this circuit to drive the signal using its internal logic. It is an error in RustHDL to leave an output undriven.
- The
Sim
struct is used to communicate with a simulation. Every testbench will be provided with a copy of this struct, and will use it to communicate with the core simulation. - This type represents a simulation over a circuit
T
. To simulate a circuit, you will need to construct one of these structs. - A Strobe generates a periodic pulse train, with a single clock-cycle wide pulse at the prescribed frequency. The argument [N] of the generic Strobe
is used to size the counter that stores the internal delay value. Unfortunately, Rust const generics are currently not good enough to compute [N] on the fly. However, a compile time assert ensures that the number of clock cycles between pulses does not overflow the [N]-bit wide register inside the Strobe. - A SyncReceiver works together with a SyncSender to transmit data from one clock domain to another (in one direction). To use a SyncReceiver wire up the [sig_cross], [flag_in] and [ack_out] signals between the two.
- When you need to send many bits between two clock domains, it is risky to use a vector of BitSynchronizer structs. That is because, you cannot guarantee at any given moment that all of the bits of your multi-bit signal will cross into the new clock domain at once. So to synchronize a multi-bit signal, use a SyncSender and SyncReceiver pair. These widgets will use a set of handshake signals to move a value from one clock domain to another safely. Note that while the state machine is executing, the synchronizer will indicate it is busy. Crossing clock domains with greater ease is best done with an [AsynchronousFIFO].
- Tristate Buffer
- A VectorSynchronizer uses a SyncSender and SyncReceiver in a matched pair to transmit a vector of bits (or any Synth type from one clock domain to a second clock domain without metastability or data corruption. You can think of a VectorSynchronizer as a single-element asynchronous FIFO, and indeed [AsynchronousFIFO] uses the VectorSynchronizer internally.
Enums
- The Bits type holds a bit array of size [N].
- The error type returned by a simulation
- The Verilog type is used to represent the Verilog translation of a RustHDL kernel. You will only need it if implementing blackbox cores or wrapping external Verilog code.
Constants
- The number of nanoseconds per femtosecond.
Traits
- The Block trait is required for all circuitry that can be simulated by RustHDL. If you want to be able to simulate a circuit, the corresponding struct must impl Block. Normally, this is done via the
#[derive(LogicBlock)]
construct, and you will rarely, if ever, need to impl the Block trait yourself.
Functions
- Cast from one bit width to another with truncation or zero padding The bit_cast function allows you to convert from one bit width to another. It handles the different widths in the following simplified manner: - if casting to a narrower bit width, the most significant bits are discarded until the new value fits into the specified bits - if casting to a wider bit width, the most significant bits are padded with zeros until the new value occupies the specified bits This may seem a bit counterintuitive, but it fits logical circuitry behavior. Narrowing is usually done by preserving the least significant bits (so that the carry bits are discarded when adding, for example). Widening is also usually done (for unsigned values) by zero extending the most significant bits. The bit_cast operation does both of these operations depending on the arguments.
- This is a helper function used to check a Block for connection, loops, and writes to the inputs.
- Check to see if a circuit is properly connected (no undriven inputs, or multiply-driven outputs). You can call this directly on a circuit of yours if you want to check that it is correctly connected internally.
- Compute the minimum number of bits to represent a container with t items. This is basically
ceil(log2(t))
as a constant (compile time computable) function. You can use it where a const generic (bit width) argument is required. - Convert a frequency in Hz to a period in femtoseconds.
- Update changes to a circuit until it stabilizes
Type Definitions
- A type alias for a simple bool. You can use them interchangeably.
- The LiteralType is used to set the type for literals that appear in RustHDL expressions. Because of how Rust’s type inference currently works, an expression like