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 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 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