mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-23 13:47:33 -04:00
157 lines
10 KiB
Text
157 lines
10 KiB
Text
<<<
|
|
:sectnums:
|
|
==== Stream Link Interface (SLINK)
|
|
|
|
[cols="<3,<3,<4"]
|
|
[grid="none"]
|
|
|=======================
|
|
| Hardware source files: | neorv32_slink.vhd |
|
|
| Software driver files: | neorv32_slink.c | link:https://stnolting.github.io/neorv32/sw/neorv32__slink_8c.html[Online software reference (Doxygen)]
|
|
| | neorv32_slink.h | link:https://stnolting.github.io/neorv32/sw/neorv32__slink_8h.html[Online software reference (Doxygen)]
|
|
| Top entity ports: | `slink_rx_dat_i` | RX link data (32-bit)
|
|
| | `slink_rx_src_i` | RX routing information (4-bit)
|
|
| | `slink_rx_val_i` | RX link data valid (1-bit)
|
|
| | `slink_rx_lst_i` | RX link last element of stream (1-bit)
|
|
| | `slink_rx_rdy_o` | RX link ready to receive (1-bit)
|
|
| | `slink_tx_dat_o` | TX link data (32-bit)
|
|
| | `slink_tx_dst_o` | TX routing information (4-bit)
|
|
| | `slink_tx_val_o` | TX link data valid (1-bit)
|
|
| | `slink_tx_lst_o` | TX link last element of stream (1-bit)
|
|
| | `slink_tx_rdy_i` | TX link allowed to send (1-bit)
|
|
| Configuration generics: | `IO_SLINK_EN` | implement SLINK when _true_
|
|
| | `IO_SLINK_RX_FIFO` | RX FIFO depth (1..32k), has to be a power of two, min 1
|
|
| | `IO_SLINK_TX_FIFO` | TX FIFO depth (1..32k), has to be a power of two, min 1
|
|
| CPU interrupts: | fast IRQ channel 14 | RX SLINK IRQ (see <<_processor_interrupts>>)
|
|
| | fast IRQ channel 15 | TX SLINK IRQ (see <<_processor_interrupts>>)
|
|
|=======================
|
|
|
|
|
|
**Overview**
|
|
|
|
The stream link interface provides independent RX and TX channels for sending and receiving
|
|
stream data. Each channel features a configurable internal FIFO to buffer stream data
|
|
(`IO_SLINK_RX_FIFO` for the RX FIFO, `IO_SLINK_TX_FIFO` for the TX FIFO). The SLINK interface provides higher
|
|
bandwidth and less latency than the external bus interface making it ideally suited for coupling custom
|
|
stream processors or streaming peripherals.
|
|
|
|
.Example Program
|
|
[TIP]
|
|
An example program for the SLINK module is available in `sw/example/demo_slink`.
|
|
|
|
|
|
**Interface & Protocol**
|
|
|
|
The SLINK interface consists of four signals for each channel:
|
|
|
|
* `dat` contains the actual data word
|
|
* `val` marks the current transmission cycle as valid
|
|
* `lst` marks the current transmission cycle as the last element of a stream
|
|
* `rdy` indicates that the receiver is ready to receive
|
|
* `src` and `dst` provide source/destination routing information (optional)
|
|
|
|
.SLINK example transmissions
|
|
[wavedrom, format="svg", align="center"]
|
|
----
|
|
{signal: [
|
|
{name: 'clk', wave: 'p.........'},
|
|
{name: 'dat', wave: 'x345..6x7x', data: ["A", "B", "C", "D", "E"]},
|
|
{name: 'val', wave: '01.....010'},
|
|
{name: 'rdy', wave: '01.0.1...0'},
|
|
{name: 'lst', wave: '0.......10'},
|
|
]}
|
|
----
|
|
|
|
.AXI4-Stream Compatibility
|
|
[NOTE]
|
|
The interface names (except for `src` and `dst`) and the underlying protocol is compatible to the AXI4-Stream protocol standard.
|
|
A processor top entity with a AXI4-Stream-compatible interfaces can be found in `rtl/system_inegration`.
|
|
More information regarding this alternate top entity can be found in the user guide:
|
|
https://stnolting.github.io/neorv32/ug/#_packaging_the_processor_as_vivado_ip_block
|
|
|
|
|
|
**Theory of Operation**
|
|
|
|
The SLINK provides four interface registers. The control register (`CTRL`) is used to configure
|
|
the module and to check its status. Two individual data registers (`DATA` and `DATA_LAST`)
|
|
are used to send and receive the link's actual data stream.
|
|
|
|
The `DATA` register provides direct access to the RX/TX FIFO buffers. Read accesses return data from the RX FIFO.
|
|
After reading data from this register the control register's `SLINK_CTRL_RX_LAST` flag can be checked to determine
|
|
if the according data word has been marked as "end of stream" via the `slink_rx_lst_i` signal (this signal is also
|
|
buffered by the link's FIFO).
|
|
Writing to the `DATA` register will immediately write to the TX link FIFO.
|
|
When writing to the `TX_DATA_LAST` the according data word will also be marked as "end of stream" via the
|
|
`slink_tx_lst_o` signal (this signal is also buffered by the link's FIFO).
|
|
|
|
The configured FIFO sizes can be retrieved by software via the control register's `SLINK_CTRL_RX_FIFO_*` and
|
|
`SLINK_CTRL_TX_FIFO_*` bits.
|
|
|
|
The SLINK is globally activated by setting the control register's enable bit `SLINK_CTRL_EN`. Clearing this bit will
|
|
reset all internal logic and will also clear both FIFOs. The FIFOs can also be cleared manually at any time by
|
|
setting the `SLINK_CTRL_RX_CLR` and/or `SLINK_CTRL_TX_CLR` bits (these bits will auto-clear).
|
|
|
|
.FIFO Overflow
|
|
[NOTE]
|
|
Writing to the TX channel's FIFO while it is _full_ will have no effect. Reading from the RX channel's FIFO while it
|
|
is _empty_ will also have no effect and will return the last received data word. There is no overflow indicator
|
|
implemented yet.
|
|
|
|
The current status of the RX and TX FIFOs can be determined via the control register's `SLINK_CTRL_RX_*` and
|
|
`SLINK_CTRL_TX_*` flags.
|
|
|
|
|
|
**Stream Routing Information**
|
|
|
|
Both stream link interface provide an optional port for routing information: `slink_tx_dst_o` (AXI stream's `TDEST`)
|
|
can be used to set a destination address when using a switch/interconnect to access several stream sinks. `slink_rx_src_i`
|
|
(AXI stream's `TID`) can be used to determine the source when several sources can send data via a switch/interconnect.
|
|
The routing information can be set/read via the `ROUTE` interface registers. Note that all routing information is also
|
|
fully buffered by the internal RX/TX FIFOs. RX routing information has to be read **after** reading the according RX
|
|
data. Vice versa, TX routing information has to be set **before** writing the according TX data.
|
|
|
|
|
|
**Interrupts**
|
|
|
|
The SLINK module provides two independent interrupt channels: one for RX events and one for TX events.
|
|
The interrupt conditions are based on the according link's FIFO status flags and are configured via the control
|
|
register's `SLINK_CTRL_IRQ_*` flags. The according interrupt will fire when the module is enabled (`SLINK_CTRL_EN`)
|
|
and the selected interrupt conditions are met. Note that all enabled interrupt conditions are logically OR-ed per
|
|
channel. If any enable interrupt conditions becomes active the interrupt will become pending until the
|
|
interrupt-causing condition is resolved (e.g. by reading from the RX FIFO).
|
|
|
|
|
|
**Register Map**
|
|
|
|
.SLINK register map (`struct NEORV32_SLINK`)
|
|
[cols="<2,<2,<4,^1,<4"]
|
|
[options="header",grid="all"]
|
|
|=======================
|
|
| Address | Name [C] | Bit(s) | R/W | Function
|
|
.22+<| `0xffec0000` .22+<| `CTRL` <| `0` `SLINK_CTRL_EN` ^| r/w <| SLINK global enable
|
|
<| `1` `SLINK_CTRL_RX_CLR` ^| -/w <| Clear RX FIFO when set (bit auto-clears)
|
|
<| `2` `SLINK_CTRL_TX_CLR` ^| -/w <| Clear TX FIFO when set (bit auto-clears)
|
|
<| `3` _reserved_ ^| r/- <| _reserved_, read as zero
|
|
<| `4` `SLINK_CTRL_RX_LAST` ^| r/- <| Last word read from `RX_DATA` is marked as "end of stream"
|
|
<| `7:5` _reserved_ ^| r/- <| _reserved_, read as zero
|
|
<| `8` `SLINK_CTRL_RX_EMPTY` ^| r/- <| RX FIFO empty
|
|
<| `9` `SLINK_CTRL_RX_HALF` ^| r/- <| RX FIFO at least half full
|
|
<| `10` `SLINK_CTRL_RX_FULL` ^| r/- <| RX FIFO full
|
|
<| `11` `SLINK_CTRL_TX_EMPTY` ^| r/- <| TX FIFO empty
|
|
<| `12` `SLINK_CTRL_TX_HALF` ^| r/- <| TX FIFO at least half full
|
|
<| `13` `SLINK_CTRL_TX_FULL` ^| r/- <| TX FIFO full
|
|
<| `15:14` _reserved_ ^| r/- <| _reserved_, read as zero
|
|
<| `16` `SLINK_CTRL_IRQ_RX_NEMPTY` ^| r/w <| RX interrupt if RX FIFO not empty
|
|
<| `17` `SLINK_CTRL_IRQ_RX_HALF` ^| r/w <| RX interrupt if RX FIFO at least half full
|
|
<| `18` `SLINK_CTRL_IRQ_RX_FULL` ^| r/w <| RX interrupt if RX FIFO full
|
|
<| `19` `SLINK_CTRL_IRQ_TX_EMPTY` ^| r/w <| TX interrupt if TX FIFO empty
|
|
<| `20` `SLINK_CTRL_IRQ_TX_NHALF` ^| r/w <| TX interrupt if TX FIFO not at least half full
|
|
<| `21` `SLINK_CTRL_IRQ_TX_NFULL` ^| r/w <| TX interrupt if TX FIFO not full
|
|
<| `23:22` _reserved_ ^| r/- <| _reserved_, read as zero
|
|
<| `27:24` `SLINK_CTRL_RX_FIFO_MSB : SLINK_CTRL_RX_FIFO_LSB` ^| r/- <| log2(RX FIFO size)
|
|
<| `31:28` `SLINK_CTRL_TX_FIFO_MSB : SLINK_CTRL_TX_FIFO_LSB` ^| r/- <| log2(TX FIFO size)
|
|
.3+<| `0xffec0004` .3+<| `ROUTE` <| `3:0` | r/w | TX destination routing information (`slink_tx_dst_o`)
|
|
<| `7:4` | r/- | RX source routing information (`slink_rx_src_i`)
|
|
<| `31:8` | -/- | _reserved_
|
|
| `0xffec0008` | `DATA` | `31:0` | r/w | Write data to TX FIFO; read data from RX FIFO
|
|
| `0xffec000c` | `DATA_LAST` | `31:0` | r/w | Write data to TX FIFO (and also set "last" signal); read data from RX FIFO
|
|
|=======================
|