Integrated logic analyzer in Spade that perfectly fits in a mastodon alt-text and took about 3 hours to write :)
You just hook the output up to anything that can consume an `Rv<uint<8>>`. For example a UART driver or UDP streamer
(I think it works at least, my one test case does do the right thing but I haven't tried it in hardware on account of it being 10pm)
![use ready_valid::Rv;
impl<T, #uint N> Rv<[T; N]> {
entity into_element_stream(self, clk: clock, rst: bool) -> Rv<T>{
let Rv(data, ready) = self;
let ds_ready = port;
reg(clk) (array, num_left): ([T; N], uint<{uint_bits_to_fit(N)}>) reset(rst: (std::undef::undef(), 0)) =
match (*data, num_left, *ds_ready#0) {
(Some(data), 0, _) => (data, N),
(_, _, false) => (array, num_left),
(None, 0, _) => (array, num_left),
(Some(data), 1, _) => (data, N),
(_, _, _) => (array[1..N].concat([std::undef::undef()]), trunc(num_left-1))
};
set ready = &(num_left == 0 || num_left == 1 && *ds_ready#0);
Rv(
&match num_left {
0 => None,
_ => Some(array[0]),
},
ds_ready#1
)
}
}
entity quickscope<T, #uint NumBytes, #uint SampleBuffer>(
clk: clock,
rst: bool,
trigger: bool,
data: T,
) -> Rv<uint<8>> {
let empty = port;
let full = port;
reg(clk) triggered reset (rst: false) = {
match (triggered, *empty#0, *full#0) {
(false, true, false) => trigger,
(true, _, true) => false,
(_, _, _) => triggered
}
};
let data_in = if triggered { Some(data) } else { None };
Rv(&data_in, port#1)
.inst fifo_buffer::<SampleBuffer>(clk, rst)
.read_empty(empty#1)
.read_full(full#1)
.data
.inst map(fn (sample) {
unsafe{ std::conv::transmute::<_, [uint<8>; NumBytes]>(sample) }
})
.inst into_element_stream(clk, rst)
}](https://files.mastodon.social/media_attachments/files/115/413/945/037/906/569/original/c129b1ddd8254575.png)