Struct Rv
pub struct Rv<T> {
data: Option<T>,
ready: inv bool,
}Implementations
impl<T> Rv<T>
pub entity buffer(self, clk: clock, rst: bool) -> Rv<T>
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 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, 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>
impl<T> 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