::ready_valid::

Struct Rv

pub struct Rv<T> {
_data: Option<T>,
ready: inv bool,
}
Expand

A stream of data with ready/valid handshaking.

Logically, you can view this as a sequence of transactions over time where a transaction only happens when both the sender is sending valid data, and when the receiver is ready. That is, when _data is Some and ready is true.

Implementations

impl<T> Rv<T>
pub fn with_ready(self, ready: bool) -> Option<T>

Converts from an Rv<T> to Option<T> by using the specified ready value to signal readiness upstream.

fn raw_data(self) -> Option<T>

Return the underlying Option<T>. Note that this function is not transaction aware, meaning that it will return a value even if ready is false. Which, in turn, means that it will observe the same value multiple times

If you want to turn the stream of data into an Option<T> that is transaction aware, use with_ready or inspect.

fn inspect(self) -> (Rv<T>, Option<T>)

Return self unmodified along with a view of the transactions occuring on self.

pub entity buffer(self, clk: clock, rst: bool) -> Rv<T>

Transactions Decouples the producer from the consumer by inserting a buffer register between them. This both allows producers and consumers to work in parallel, and also breaks the ready combinational path

However, this decoupling of the ready signal means that the throughput is at most 50% of the time, so for a high throughput stream, this should not be used

pub entity skid_buffer(self, clk: clock, rst: bool) -> Rv<T>
pub fn terminate_unready(self)

Set ready to false and ignore the result

pub fn terminate_ready(self)

Set ready to true and ignore the result

pub entity map<F, O>(self, f: F) -> Rv<O>
where
    F: Fn(T) -> O,
pub entity and_then<F, O>(self, f: F) -> Rv<O>
where
    F: Fn(T) -> Option<O>,
pub entity append_lower_priority(self, other: Rv<T>) -> Rv<T>
pub entity append_higher_priority(self, other: Rv<T>) -> Rv<T>
pub fn gate(self, gate: bool) -> Rv<T>

If gate is false, do not propagate any values

pub entity fsm<State, O>(self, clk: clock, rst: bool, first_state: impl Fn(T) -> State, update_fn: impl Fn(State) -> Option<State>, output_fn: impl Fn(State) -> O) -> Rv<O>

Runs an FSM on each value in the Rv.

The FSM is described by the three functions first_state, update_fn and output_fn. In the first cycle where a new value is present, the first_state function is invoked to convert the value into an internal state reprensetation. On subsequent cycles, the update_fn is called to transform the state. The update_fn returns Some(new_state) if the the value still needs further processing, and None if it is done processing.

When it is done processing, output_fn is used to transform the final state into an output value.

It takes one clock cycle for the FSM to start as the update_fn function is not invoked on the output of first_state.

It takes one clock cycle for a new value to be accepted by the FSM after the output has been accepted. The FSM can start processing new values even if the downstream is not ready, it will hold on to the output when the downstream is not ready.

impl<L> Rv<L>
fn join<R>(self, r: Rv<R>) -> Rv<(L, R)>
impl<L, R> Rv<(L, R)>
fn split_unbuffered(self) -> (Rv<L>, Rv<R>)

Split the Rv into two disjoint streams. Unlike split which contains buffers on the two streams, this requires both stream to have some buffer if they are to be joined later, otherwise they will deadlock.

entity split(self, clk: clock, rst: bool) -> (Rv<L>, Rv<R>)

Split the Rv into two disjoint streams where every element on self results in an element on the left and right streams.

Contains skid buffers on both streams which prevent deadlocks if the two streams are to be joined in the future. If both streams have buffers downstream, split_unbuffered can be used.

impl<T> Rv<T>
pub entity with_minimum_delay<#uint N>(self, clk: clock, rst: bool) -> Rv<T>

Enforces a delay of at least N clock cycles between transactions being completed by disconnecting the producer from the consumer for N cycles after a transaction has been accepted

impl<T> Rv<T>
pub entity cdc_fifo_buffer<#uint Depth>(self, write_clk: clock, write_rst: bool, read_clk: clock, read_rst: bool) -> FifoOut<T>

Buffers the values using a FIFO, which can be used to cross clock domains.

pub entity fifo_buffer<#uint Depth>(self, clk: clock, rst: bool) -> FifoOut<T>
impl Rv<uint<16>>
pub entity split_to_u8(self, clk: clock, rst: bool) -> Rv<uint<8>>
impl<T, #uint N> Rv<[T; N]>
pub entity into_element_stream(self, clk: clock, rst: bool) -> Rv<T>
impl Rv<Escaped<uint<8>>>
entity escape_bytes<F, #uint N>(self, clk: clock, rst: bool, escapees: [uint<8>; N], escape_fn: F, escape_prefix: uint<8>) -> Rv<uint<8>>
where
    F: Fn(uint<8>) -> uint<8>,

Escapes bytes in the escapees list by first emitting an escape prefix, then emitting the the result of the escape_fn function on the escaped byte.

For example, the stream 1, 2, 3, 4 when called with escapees == [3] and escape_fn = fn (byte) {trunc(byte + 10)} and escape_prefix = 0 will result in 1 2 0 13 4