[docs] update SLINK documentation

This commit is contained in:
stnolting 2022-06-16 17:29:25 +02:00
parent 1956daadd2
commit eb36f60149
3 changed files with 74 additions and 121 deletions

View file

@ -89,12 +89,14 @@ bits/channels are hardwired to zero.
| `xip_sdi_i` | 1 | in | serial data input
| `xip_sdo_o` | 1 | out | serial data output
4+^| **Stream Link Interface (<<_stream_link_interface_slink,SLINK>>)**
| `slink_tx_dat_o` | 8x32 | out | TX link _n_ data
| `slink_tx_val_o` | 8 | out | TX link _n_ data valid
| `slink_tx_rdy_i` | 8 | in | TX link _n_ allowed to send
| `slink_rx_dat_i` | 8x32 | in | RX link _n_ data
| `slink_rx_val_i` | 8 | in | RX link _n_ data valid
| `slink_rx_rdy_o` | 8 | out | RX link _n_ ready to receive
| `slink_tx_dat_o` | 8x32 | out | TX link _i_ data
| `slink_tx_val_o` | 8 | out | TX link _i_ data valid
| `slink_tx_rdy_i` | 8 | in | TX link _i_ allowed to send
| `slink_tx_lst_o` | 8 | in | TX link _i_ end of packet
| `slink_rx_dat_i` | 8x32 | in | RX link _i_ data
| `slink_rx_val_i` | 8 | in | RX link _i_ data valid
| `slink_rx_rdy_o` | 8 | out | RX link _i_ ready to receive
| `slink_rx_lst_i` | 8 | out | RX link _i_ end of packet
4+^| **General Purpose Inputs & Outputs (<<_general_purpose_input_and_output_port_gpio,GPIO>>)**
| `gpio_o` | 64 | out | general purpose parallel output
| `gpio_i` | 64 | in | general purpose parallel input

View file

@ -9,11 +9,13 @@
| Software driver file(s): | neorv32_slink.c |
| | neorv32_slink.h |
| Top entity port: | `slink_tx_dat_o` | TX link data (8x32-bit)
| | `slink_tx_val_o` | TX link data valid (8-bit)
| | `slink_tx_rdy_i` | TX link allowed to send (8-bit)
| | `slink_tx_val_o` | TX link data valid (8x1-bit)
| | `slink_tx_rdy_i` | TX link allowed to send (8x1-bit)
| | `slink_tx_lst_o` | TX link end of packet (8x1-bit)
| | `slink_rx_dat_i` | RX link data (8x32-bit)
| | `slink_rx_val_i` | RX link data valid (8-bit)
| | `slink_rx_rdy_o` | RX link ready to receive (8-bit)
| | `slink_rx_val_i` | RX link data valid (8x1-bit)
| | `slink_rx_rdy_o` | RX link ready to receive (8x1-bit)
| | `slink_rx_lst_i` | RX link end of packet (8x1-bit)
| Configuration generics: | _SLINK_NUM_TX_ | Number of TX links to implement (0..8)
| | _SLINK_NUM_RX_ | Number of RX links to implement (0..8)
| | _SLINK_TX_FIFO_ | FIFO depth (1..32k) of TX links, has to be a power of two
@ -22,9 +24,9 @@
| | fast IRQ channel 11 | SLINK TX IRQ (see <<_processor_interrupts>>)
|=======================
The SLINK component provides up to 8 independent RX (receiving) and TX (sending) links for transmitting
stream data. The interface provides higher bandwidth (and less latency) than the external memory bus
interface, which makes it ideally suited to couple custom stream processing units (like CORDIC, FFTs or
The SLINK component provides up to 8 independent RX (receiving) and TX (sending) links for moving
stream data. The interface provides higher bandwidth and less latency than the external memory bus
interface, which makes it ideally suited to couple custom stream processing units (like CORDICs, FFTs or
cryptographic accelerators).
Each individual link provides an internal FIFO for data buffering. The FIFO depth is globally defined
@ -35,125 +37,79 @@ logic mapping).
The actual number of implemented RX/TX links is configured by the _SLINK_NUM_RX_ and _SLINK_NUM_TX_
generics. The SLINK module will be synthesized only if at least one of these generics is greater than
zero. All unimplemented links are internally terminated and their according output signals are pulled
to low level.
zero. All unimplemented links are internally terminated and their according output signals are set to zero.
[NOTE]
The SLINK interface does not provide any additional tag signals (for example to define a "stream destination
address" or to indicate the last data word of a "package"). Use a custom controller connected
via the external memory bus interface or use some of the processor's GPIO ports to implement custom data
tag signals.
The NEORV32 stream link interfaces are compatible to the _AXI Stream_ specs.
**Theory of Operation**
The SLINK provides eight data registers (`DATA[i]`) to access the links (read accesses will access the RX links, write
accesses will access the TX links), one control register (`CTRL`) and one status register (`STATUS`).
The SLINK provides eight data registers (`DATA[i]`) to access the links (read accesses will access the RX links,
write accesses will access the TX links), one control register (`CTRL`) and one status register (`STATUS`).
The SLINK is globally activated by setting the control register's enable bit _SLINK_CTRL_EN_.
The actual data links are accessed by reading or writing the according link data registers `DATA[0]`
to `DATA[7]`. For example, writing the `DATA[0]` will put the according data into the FIFO of TX link 0.
Accordingly, reading from `DATA[0]` will return one data word from the FIFO of RX link 0.
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 all data FIFOs. The actual data links are accessed by
reading or writing the according link data registers `DATA[0]` to `DATA[7]`. For example, writing the `DATA[0]`
will put the according data into the FIFO of TX link 0. Accordingly, reading from `DATA[0]` will return one data
word from the FIFO of RX link 0.
The configuration (done via the SLINK generics) can be checked by software by evaluating bit fields in the
control register. The _SLINK_CTRL_TX_FIFO_Sx_ and _SLINK_CTRL_RX_FIFO_Sx_ indicate the TX & RX FIFO sizes.
The _SLINK_CTRL_TX_NUMx_ and _SLINK_CTRL_RX_NUMx_ bits represent the absolute number of implemented TX and RX links.
The status register shows the FIFO status flags of each RX and TX link. The _SLINK_CTRL_RXx_AVAIL_ flags indicate
that there is _at least_ one data word in the according RX link's FIFO. The _SLINK_CTRL_TXx_FREE_ flags indicate
there is _at least_ one free entry in the according TX link's FIFO. The _SLINK_STATUS_RXx_HALF_ and
_SLINK_STATUS_RXx_HALF_ flags show if a certain FIFO's fill level has exceeded half of its capacity.
**Blocking Link Access**
When directly accessing the link data registers (without checking the according FIFO status flags) the access
is as _blocking_. That means the CPU access will stall until the accessed link responds. For
example, when reading RX link 0 (via `DATA[0]` register) the CPU will stall, if there is not data
available in the according FIFO yet. The CPU access will complete as soon as RX link 0 receives new data.
Vice versa, writing data to TX link 0 (via `DATA[0]` register) will stall the CPU access until there is
at least one free entry in the link's FIFO.
[WARNING]
The NEORV32 processor ensures that _any_ CPU access to memory-mapped devices (including the SLINK module)
will **time out** after a certain number of cycles (see section <<_bus_interface>>).
Hence, blocking access to a stream link that does not complete within a certain amount of cycles will
raise a _store bus access exception_ when writing to a _full_ TX link's FIFO or a _load bus access exception_
when reading from an _empty_ RX 's FIFO. Hence, this concept should only be used when evaluating the half-full
FIFO condition (for example via the SLINK interrupts) before actual accessing links.
The current link status of each RX and TX channel is accessible via the `STATUS` register. Each link provides a
read-only FIFO status flag in this register: the _SLINK_CTRL_RX_AVAIL_ flags indicate that there is _at least_
one data word available in the according RX link's FIFO. The _SLINK_CTRL_TX_FREE_ flags indicate
there is _at least_ one free entry in the according TX link's FIFO.
[NOTE]
There is no RX FIFO overflow mechanism available yet.
Writing to a TX link's FIFO that is _full_ will have no effect. Reading data from a RX link's FIFO that is
_empty_ will have no effect and will return the last valid data word.
The "end of packet" signal `lst` is controlled by the status register's _SLINK_STATUS_RX_LAST_ and
_SLINK_STATUS_TX_LAST_ bits. Note that the RX/TX `lst` signal is also buffered by the internal FIFOs.
Setting a bit in _SLINK_STATUS_TX_LAST_ before writing data to `DATA` will set the `lst` signal when the
written data word is actually send from the FIFO. Vice versa, a bit in _SLINK_STATUS_RX_LAST_ will be set
if the according data word read from `DATA` was marked as "end of packet".
**Non-Blocking Link Access**
**Data Transmission**
For a non-blocking link access concept, the FIFO status flags in `STATUS` need to be checked _before_
reading/writing the actual link data register. For example, a non-blocking write access to a TX link 0 has
to check _SLINK_STATUS_TX0_FREE_ first. If the bit is set, the FIFO of TX link 0 can take another data word
and the actual data can be written to `DATA[0]`. If the bit is cleared, the link's FIFO is full
and the status flag can be polled until it there is free space in the available.
To send (TX) data the program should ensure there is at least one left in the according link's FIFO by checking
_SLINK_CTRL_TX_FREE_. To mark the current data word to-be-send as "end of packet" the according _SLINK_STATUS_TX_LAST_
bit has to be set _before_ writing `DATA`.
This concept will not raise any exception as there is no "direct" access to the link data registers.
However, non-blocking accesses require additional instructions to check the according status flags prior
to the actual link access, which will reduce performance for high-bandwidth data streams.
Receive (RX) is available when the according link's _SLINK_CTRL_RX_AVAIL_ bit is set. To check if the received data
is marked as "end of packet" the according _SLINK_STATUS_RX_LAST_ has to be checked _before_ reading `DATA`.
**Stream Link Interface & Protocol**
**Interface & Protocol**
The SLINK interface consists of three signals `dat`, `val` and `rdy` for each RX and TX link.
The SLINK interface consists of four signals `dat`, `val`, `rdy` and `lst` for each RX and TX link.
Each signal is an "array" with eight entires (one for each link). Note that an entry in `slink_*x_dat` is 32-bit
wide while entries in `slink_*x_val` and `slink_*x_rdy` are are just 1-bit wide.
The stream link protocol is based on a simple FIFO-like interface between a source (sender) and a sink (receiver).
Each link provides two signals for implementing a simple FIFO-style handshake. The `slink_*x_val` signal is set by
the source if the according `slink_*x_dat` (also set by the source) contains valid data. The stream source has to
ensure that both signals remain stable until the according `slink_*x_rdy` signal is set by the stream sink to
indicate it can accept another data word.
* `dat` contains the actual data word
* `val` marks the current transmission cycle as valid
* `rdy` indicates that the receiving part is ready to receive
* `lst` marks the current data word as "end of packet"
In summary, a data word is transferred if both `slink_*x_val(i)` and `slink_*x_rdy(i)` are high.
.Exemplary stream link transfer
.Exemplary Stream Link Transfer (transferring 5 elements, element "E" is marked as "end of packet")
image::stream_link_interface.png[width=560,align=center]
[TIP]
The SLINK handshake protocol is compatible with the https://developer.arm.com/documentation/ihi0051/a/Introduction/About-the-AXI4-Stream-protocol[AXI4-Stream] base protocol.
**SLINK Interrupts**
The stream interface provides two independent interrupts that are _globally_ driven by the RX and TX link's
FIFO fill level status. Each RX and TX link provides an individual interrupt enable flag and an individual
interrupt type flag that allows to configure interrupts only for certain (or all) links and for application-
specific FIFO conditions. The interrupt configuration is done using the `NEORV32_SLINK.IRQ` register.
Any interrupt can only become pending if the SLINK module is enabled at all.
The stream interface provides two independent CPU interrupts - one for RX conditions (data received) and one
for TX conditions (ready to send). The RX interrupt is controlled per-link by the _SLINK_CTRL_RX_IRQ_EN_
control register bits while the TX interrupt is controlled per-link by the _SLINK_CTRL_TX_IRQ_EN_ control
register bits. If any enabled link fulfills the RX/TX interrupt condition a RX/TX interrupt request is
sent to the CPU. Note that all RX and TX interrupt conditions are logically OR-ed.
[NOTE]
There is no RX FIFO overflow mechanism available yet.
* RX interrupt: if the FIFO of link _i_ changes from status "empty" to "not empty" (data available) and the
according _SLINK_CTRL_RX_IRQ_EN_ bit is set the SLINK RX interrupt is triggered
* TX interrupt: if the FIFO of link _i_ changes from status "full" to "not full" (ready to send) and the
according _SLINK_CTRL_TX_IRQ_EN_ bit is set the SLINK TX interrupt is triggered
The current FIFO fill-level of a specific **RX link** can only raise an interrupt request if it's interrupt enable flag
_SLINK_IRQ_RX_EN_ is set. Vice versa, the current FIFO fill-level of a specific **TX link** can only raise an interrupt
request if it's interrupt enable flag _SLINK_IRQ_TX_EN_ is set.
The **RX link's** _SLINK_IRQ_RX_MODE_ flags define the FIFO fill-level condition for raising an RX interrupt request:
* If a link's interrupt mode flag is `0` an IRQ is generated when the link's FIFO _becomes_ not empty ("RX data available").
* If a link's interrupt mode flag is `1` an IRQ is generated when the link's FIFO _becomes_ at least half-full ("time to get data from RX FIFO to prevent overflow").
The **TX link's** _SLINK_IRQ_TX_MODE_ flags define the FIFO fill-level condition for raising an TX interrupt request:
* If a link's interrupt mode flag is `0` an IRQ is generated when the link's FIFO _becomes_ not full ("space left in FIFO for new TX data").
* If a link's interrupt mode flag is `1` an IRQ is generated when the link's FIFO _becomes_ less than half-full ("SW can send _SLINK_TX_FIFO_/2 data words without checking any flags").
Once the SLINK's RX or TX interrupt has become pending, it has to be explicitly cleared again by writing
zero to the according <<_mip>> CSR bit.
[IMPORTANT]
The interrupt configuration register `NEORV32_SLINK.IRQ` should we written _before_ the SLINK
module is actually enabled.
[NOTE]
If _SLINK_RX_FIFO_ is 1 all _SLINK_IRQ_RX_MODE_ bits are hardwired to one.
If _SLINK_TX_FIFO_ is 1 all _SLINK_IRQ_TX_MODE_ bits are hardwired to one.
Once the SLINK's RX or TX CPU interrupt has become pending, it has to be explicitly cleared again by writing
zero to the according <<_mip>> CSR bit(s).
**Register Map**
@ -163,23 +119,18 @@ If _SLINK_TX_FIFO_ is 1 all _SLINK_IRQ_TX_MODE_ bits are hardwired to one.
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s) | R/W | Function
.6+<| `0xfffffec0` .6+<| `NEORV32_SLINK.CTRL` <| `31` _SLINK_CTRL_EN_ ^| r/w | SLINK global enable
<| `30:16` _reserved_ ^| r/- <| reserved, read as zero
<| `15:12` _SLINK_CTRL_TX_FIFO_S3_ : _SLINK_CTRL_TX_FIFO_S0_ ^| r/- <| TX links FIFO depth, log2 of_SLINK_TX_FIFO_ generic
<| `11:8` _SLINK_CTRL_RX_FIFO_S3_ : _SLINK_CTRL_RX_FIFO_S0_ ^| r/- <| RX links FIFO depth, log2 of_SLINK_RX_FIFO_ generic
<| `7:4` _SLINK_CTRL_TX_NUM3_ : _SLINK_CTRL_TX_NUM0_ ^| r/- <| Number of implemented TX links
<| `3:0` _SLINK_CTRL_RX_NUM3_ : _SLINK_CTRL_RX_NUM0_ ^| r/- <| Number of implemented RX links
| `0xfffffec4` | - |`31:0` | r/- | _reserved_
.4+<| `0xfffffec8` .4+<| `NEORV32_SLINK.IRQ` <|`31:24` _SLINK_IRQ_RX_EN_MSB_ : _SLINK_IRQ_RX_EN_LSB_ ^| r/w <| RX interrupt enable for link 7..0
<|`23:16` _SLINK_IRQ_RX_MODE_MSB_ : _SLINK_IRQ_RX_MODE_LSB_ ^| r/w <| RX IRQ mode for link 7..0: `0` = FIFO rises above half-full; `1` = FIFO not empty
<|`15:8` _SLINK_IRQ_TX_EN_MSB_ : _SLINK_IRQ_TX_EN_LSB_ ^| r/w <| TX interrupt enable for link 7..0
<|`7:0` _SLINK_IRQ_TX_MODE_MSB_ : _SLINK_IRQ_TX_MODE_LSB_ ^| r/w <| TX IRQ mode for link 7..0: `0` = FIFO falls below half-full; `1` = FIFO not full
| `0xfffffeec` | - |`31:0` | r/- | _reserved_
.4+<| `0xfffffed0` .4+<| `NEORV32_SLINK.STATUS` <| `31:24` _SLINK_STATUS_TX7_HALF_ : _SLINK_STATUS_TX0_HALF_ ^| r/- <| TX link 7..0 FIFO fill level is >= half-full
<| `23:16` _SLINK_STATUS_RX7_HALF_ : _SLINK_STATUS_RX0_HALF_ ^| r/- <| RX link 7..0 FIFO fill level is >= half-full
<| `15:8` _SLINK_STATUS_TX7_FREE_ : _SLINK_STATUS_TX0_FREE_ ^| r/- <| At least one free TX FIFO entry available for link 7..0
<| `7:0` _SLINK_STATUS_RX7_AVAIL_ : _SLINK_STATUS_RX0_AVAIL_ ^| r/- <| At least one data word in RX FIFO available for link 7..0
| `0xfffffed4` : `0xfffffedc` | - |`31:0` | r/- | _reserved_
.6+<| `0xfffffec0` .6+<| `NEORV32_SLINK.CTRL` <| `0` _SLINK_CTRL_EN_ ^| r/w | SLINK global enable
<| `7:1` _reserved_ ^| r/- <| reserved, read as zero
<| `11:8` _SLINK_CTRL_TX_FIFO_S3_ : _SLINK_CTRL_TX_FIFO_S0_ ^| r/- <| TX FIFO depth, log2(_SLINK_TX_FIFO_)
<| `15:12` _SLINK_CTRL_RX_FIFO_S3_ : _SLINK_CTRL_RX_FIFO_S0_ ^| r/- <| RX FIFO depth, log2(_SLINK_RX_FIFO_)
<| `23:13` _SLINK_CTRL_RX_IRQ_EN_MSB_ : _SLINK_CTRL_RX_IRQ_EN_LSB_ ^| r/- <| RX interrupt enable for link _i_
<| `23:13` _SLINK_CTRL_TX_IRQ_EN_MSB_ : _SLINK_CTRL_TX_IRQ_EN_LSB_ ^| r/- <| TX interrupt enable for link _i_
| `0xfffffec4` : `0xfffffecf` | - |`31:0` | r/- | _reserved_
.4+<| `0xfffffed0` .4+<| `NEORV32_SLINK.STATUS` <|`7:0` _SLINK_STATUS_RX_AVAIL_MSB_ : _SLINK_STATUS_RX_AVAIL_LSB_ ^| r/- <| RX link _i_ FIFO is NOT empty (data available)
<|`15:8` _SLINK_STATUS_TX_FREE_MSB_ : _SLINK_STATUS_TX_FREE_LSB_ ^| r/- <| TX link _i_ FIFO is NOT full (ready to send)
<|`23:16` _SLINK_STATUS_RX_LAST_MSB_ : _SLINK_STATUS_RX_LAST_LSB_ ^| r/- <| Indicates end of packet for RX link _i_
<|`31:24` _SLINK_STATUS_TX_LAST_MSB_ : _SLINK_STATUS_TX_LAST_LSB_ ^| r/w <| Set to indicate end of packet for TX link _i_
| `0xfffffed4` : `0xfffffedf` | - |`31:0` | r/- | _reserved_
| `0xfffffee0` | `NEORV32_SLINK.DATA[0]` | `31:0` | r/w | Link 0 RX/TX data
| `0xfffffee4` | `NEORV32_SLINK.DATA[1]` | `31:0` | r/w | Link 1 RX/TX data
| `0xfffffee8` | `NEORV32_SLINK.DATA[2]` | `31:0` | r/w | Link 2 RX/TX data

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Before After
Before After