163 lines
10 KiB
Text
163 lines
10 KiB
Text
<<<
|
|
:sectnums:
|
|
==== Stream Link Interface (SLINK)
|
|
|
|
[cols="<3,<3,<4"]
|
|
[frame="topbot",grid="none"]
|
|
|=======================
|
|
| Hardware source file(s): | neorv32_slink.vhd |
|
|
| 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 (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 (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
|
|
| | _SLINK_RX_FIFO_ | FIFO depth (1..32k) of RX links, has to be a power of two
|
|
| CPU interrupts: | fast IRQ channel 10 | SLINK RX IRQ (see <<_processor_interrupts>>)
|
|
| | fast IRQ channel 11 | SLINK TX IRQ (see <<_processor_interrupts>>)
|
|
|=======================
|
|
|
|
|
|
**Overview**
|
|
|
|
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.
|
|
|
|
Each link provides an individual internal FIFO for data buffering. The FIFO depth is globally defined
|
|
for all TX links via the _SLINK_TX_FIFO_ generic and for all RX links via the _SLINK_RX_FIFO_ generic.
|
|
The FIFO depth has to be at least 1, which will implement a simple input/output register. The maximum
|
|
value is limited to 32768 entries. Note that the FIFO depth has to be a power of two.
|
|
|
|
The actual number of implemented RX/TX links is configured by the _SLINK_NUM_RX_ and _SLINK_NUM_TX_
|
|
generics, respectively. 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 set to zero.
|
|
|
|
[NOTE]
|
|
The NEORV32 stream link interfaces are compatible to the _AXI Stream_ specs.
|
|
|
|
.Example Program
|
|
[TIP]
|
|
An example program for the SLINK module is available in `sw/example/demo_slink`.
|
|
|
|
|
|
**Theory of Operation**
|
|
|
|
The SLINK provides eight data registers (`DATA[i]`) to access the links (read accesses will access the RX link FIFOs,
|
|
write accesses will access the TX link FIFOs), one control register (`CTRL`), one interrupt configuration register (`IRQ`)
|
|
and two status registers - one for the RX links (`RX_STATUS`) and one for the TX links (`TX_STATUS`).
|
|
|
|
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 FIFOs. The actual data links are accessed by
|
|
reading or writing the according link data registers `DATA[0]` to `DATA[7]`. For example, writing to `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 current link status of each RX and TX channel is accessible via the `*X_STATUS` registers. The FIFO's status
|
|
signals that represent the fill level (empty, at least half full, full) are exposed as read-only flags via those two
|
|
registers.
|
|
|
|
[NOTE]
|
|
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 TX link's "end of packet" signal `slink_tx_lst_o` is controlled by the `TX_STATUS` register's _SLINK_TX_STATUS_LAST_
|
|
bits. Note that these bits are also buffered by the internal TX FIFOs, so setting one of these bits before writing data to
|
|
`DATA` will set the `slink_tx_lst_o` signal when the written data word is actually send from the FIFO. Vice versa, the
|
|
_SLINK_RX_STATUS_LAST_ bits in `RX_STATUS` represent the level of the according `slink_rx_lst_i` input when a new data word
|
|
was samples. These bits are also buffered in the internal RX FIFOs.
|
|
|
|
|
|
**Data Transmission**
|
|
|
|
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_TX_STATUS_LAST_
|
|
bit has to be set _before_ writing `DATA`.
|
|
|
|
Received data (RX) is available when the according link's _SLINK_RX_STATUS_EMPTY_ bit is cleared. To check if the received
|
|
data is marked as "end of packet" the according _SLINK_RX_STATUS_LAST_ bit has to be examined _before_ reading `DATA`.
|
|
|
|
|
|
**Interface & Protocol**
|
|
|
|
The SLINK interface consists of four signals `dat`, `val`, `rdy` and `lst` for each RX and TX link.
|
|
Each signal is constructed as an "array" with eight entries - one for each link. Note that an entry in `slink_*x_dat` is 32-bit
|
|
wide while entries in `slink_*x_val`, `slink_*x_rdy` and `slink_*x_lst` are are just 1-bit wide.
|
|
|
|
* `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"
|
|
|
|
.Exemplary Stream Link Transfer (transferring 5 elements, element "E" is marked as "end of packet")
|
|
image::stream_link_interface.png[width=560,align=center]
|
|
|
|
|
|
**SLINK Interrupts**
|
|
|
|
The stream interface provides two independent CPU interrupt channels - one for RX conditions and one
|
|
for TX conditions. These IRQs can be used to signal specific FIFO conditions (e.g. "data available") to the
|
|
CPU. The specific interrupt conditions are programmed per-link via the `IRQ` register.
|
|
A 2-bit-coded value is used to enable the according link's interrupt and to specify the actual condition.
|
|
|
|
[NOTE]
|
|
Note that all enabled interrupt configurations are logically OR-ed for the CPU RX and TX interrupts, respectively.
|
|
Hence, if **any** link fulfills the according interrupt configuration the according RX/TX interrupt request is
|
|
sent to the CPU.
|
|
|
|
For the TX links (in `IRQ` _SLINK_IRQ_TX_) the following interrupt conditions are supported:
|
|
|
|
* `0-`: off, no interrupt from link
|
|
* `10`: interrupt fires if FIFO _becomes_ not empty
|
|
* `11`: interrupt fires if FIFO _becomes_ at least half full
|
|
|
|
For the RX links (in `IRQ` _SLINK_IRQ_RX_) the following interrupt conditions are supported:
|
|
|
|
* `0-`: off, no interrupt from link
|
|
* `10`: interrupt fires if FIFO _becomes_ empty
|
|
* `11`: interrupt fires if FIFO _becomes_ less than half full
|
|
|
|
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**
|
|
|
|
.SLINK register map (`struct NEORV32_SLINK`)
|
|
[cols="^4,<5,^2,^2,<14"]
|
|
[options="header",grid="all"]
|
|
|=======================
|
|
| Address | Name [C] | Bit(s) | R/W | Function
|
|
.6+<| `0xfffffec0` .6+<| `NEORV32_SLINK.CTRL` <| `0` _SLINK_CTRL_EN_ ^| r/w | SLINK global enable/reset
|
|
<| `7:1` _reserved_ ^| r/- <| _reserved_, returns zero
|
|
<| `19:16` _SLINK_CTRL_RX_NUM_MSB_ : _SLINK_CTRL_RX_NUM_LSB_ ^| r/- <| Number of RX links (_SLINK_NUM_RX_)
|
|
<| `23:20` _SLINK_CTRL_TX_NUM_MSB_ : _SLINK_CTRL_TX_NUM_LSB_ ^| r/- <| Number of TX links (_SLINK_NUM_TX_)
|
|
<| `27:24` _SLINK_CTRL_RX_FIFO_MSB_ : _SLINK_CTRL_RX_FIFO_LSB_ ^| r/- <| RX FIFO depth, log2(_SLINK_RX_FIFO_)
|
|
<| `31:28` _SLINK_CTRL_TX_FIFO_MSB_ : _SLINK_CTRL_TX_FIFO_MSB_ ^| r/- <| TX FIFO depth, log2(_SLINK_TX_FIFO_)
|
|
.2+<| `0xfffffec4` .2+<| `NEORV32_SLINK.IRQ` <|`15:0` _SLINK_IRQ_RX_MSB_ : _SLINK_IRQ_RX_LSB_ ^| r/w <| RX link _i_ interrupt configuration (2 bits per link)
|
|
<|`31:16` _SLINK_IRQ_TX_MSB_ : _SLINK_IRQ_TX_LSB_ ^| r/w <| TX link _i_ interrupt configuration (2 bits per link)
|
|
.4+<| `0xfffffec8` .4+<| `NEORV32_SLINK.RX_STATUS` <|`7:0` _SLINK_RX_STATUS_EMPTY_MSB_ : _SLINK_RX_STATUS_EMPTY_LSB_ ^| r/- <| RX link _i_ FIFO empty
|
|
<|`15:8` _SLINK_RX_STATUS_HALF_MSB_ : _SLINK_RX_STATUS_HALF_LSB_ ^| r/- <| RX link _i_ FIFO at least half full
|
|
<|`23:16` _SLINK_RX_STATUS_FULL_MSB_ : _SLINK_RX_STATUS_FULL_LSB_ ^| r/- <| RX link _i_ FIFO full
|
|
<|`31:24` _SLINK_RX_STATUS_LAST_MSB_ : _SLINK_RX_STATUS_LAST_LSB_ ^| r/- <| Current data word of RX link _i_ is marked as "end of packet"
|
|
.4+<| `0xfffffecc` .4+<| `NEORV32_SLINK.TX_STATUS` <|`7:0` _SLINK_TX_STATUS_EMPTY_MSB_ : _SLINK_TX_STATUS_EMPTY_LSB_ ^| r/- <| TX link _i_ FIFO empty
|
|
<|`15:8` _SLINK_TX_STATUS_HALF_MSB_ : _SLINK_TX_STATUS_HALF_LSB_ ^| r/- <| TX link _i_ FIFO at least half full
|
|
<|`23:16` _SLINK_TX_STATUS_FULL_MSB_ : _SLINK_TX_STATUS_FULL_LSB_ ^| r/- <| TX link _i_ FIFO full
|
|
<|`31:24` _SLINK_TX_STATUS_LAST_MSB_ : _SLINK_TX_STATUS_LAST_LSB_ ^| r/w <| Set to mark next data word of TX link _i_ is "end of packet"
|
|
| `0xfffffed0` : `0xfffffedf` | - |`31:0` | r/- | _reserved_, returns zero
|
|
| `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
|
|
| `0xfffffeec` | `NEORV32_SLINK.DATA[3]` | `31:0` | r/w | Link 3 RX/TX data
|
|
| `0xfffffef0` | `NEORV32_SLINK.DATA[4]` | `31:0` | r/w | Link 4 RX/TX data
|
|
| `0xfffffef4` | `NEORV32_SLINK.DATA[5]` | `31:0` | r/w | Link 5 RX/TX data
|
|
| `0xfffffef8` | `NEORV32_SLINK.DATA[6]` | `31:0` | r/w | Link 6 RX/TX data
|
|
| `0xfffffefc` | `NEORV32_SLINK.DATA[7]` | `31:0` | r/w | Link 7 RX/TX data
|
|
|=======================
|