stnolting / neorv32

:desktop_computer: A small, customizable and extensible MCU-class 32-bit RISC-V soft-core CPU and microcontroller-like SoC written in platform-independent VHDL.

Home Page:https://neorv32.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problem with SLINK from V1.9.5.5 onwards

Unike267 opened this issue Β· comments

Hi @stnolting

I'm having problems with SLINK.

The same design in V1.9.5 works and from v1.9.5.5 onwards it doesn't work.

The design is a multiplier added with NEORV32 via SLINK. The FPGA is an ARTY A7 35-t.

It should be noted that I'm not using the tlast signal.

I think that the problems comes in this line L289, because I've simulated both design and I've obtained the following results:

  • In V1.9.5 the signal to write in TX FIFO is tx_fifo.we <= '1' when (bus_req_i.stb = '1') and (bus_req_i.rw = '1') and (bus_req_i.addr(2) = '1') else '0'; and we can see how this condition is satisfied and it is writing in the TX FIFO:

V1 9 5

The data flows through the SLINK (is multiplied 0001 X 0001 = 00000001):

V1 9 5_res

  • From v1.9.5.5 onwards the signal to write in TX FIFO is tx_fifo.we <= '1' when (bus_req_i.stb = '1') and (bus_req_i.rw = '1') and (bus_req_i.addr(3) = '1') else '0'; and this condition is not satisfied:

V1 9 9 5

Therefore, nothing is sent through SLINK.

I've modified the SLINK code replacing tx_fifo.we from tx_fifo.we <= '1' when (bus_req_i.stb = '1') and (bus_req_i.rw = '1') and (bus_req_i.addr(3) = '1') else '0'; to tx_fifo.we <= '1' when (bus_req_i.stb = '1') and (bus_req_i.rw = '1') and (bus_req_i.addr(2) = '1') else '0'; in V1.9.9.5 and it works.

I haven't done a PR because I know that you modified the tx_fifo.we condition for some reason. Could you explain me why? Why do you refer to bus_req_i.addr(3) instead of bus_req_i.addr(2)? Does it have something to do with tlast?

If yes, is it necessary to add this signal to the design?

Thank you so much!

Cheers! πŸ˜ƒ


/cc @umarcor

Hey @Unike267!

Please note that the low-level software access mechanism for the SLINK module has also changed in #815 (v1.9.5.5). The old software interface just used two memory-mapped registers:

typedef volatile struct __attribute__((packed,aligned(4))) {
  uint32_t CTRL;  /**< offset 0: control register (#NEORV32_SLINK_CTRL_enum) */
  uint32_t DATA;  /**< offset 4: data register */
} neorv32_slink_t;

Whereas the new one uses 4 registers with individual regs for RX data, TX data and last-TX data (yes, there is a typo in the comments πŸ™ˆ):

typedef volatile struct __attribute__((packed,aligned(4))) {
  uint32_t CTRL;         /**< offset 0: control register (#NEORV32_SLINK_CTRL_enum) */
  uint32_t RX_DATA;      /**< offset 4: rx data register */
  uint32_t TX_DATA;      /**< offset 8: tx data register */
  uint32_t TX_DATA_LAST; /**< offset 12: tx data register + end-of-stream delimiter */
} neorv32_slink_t;

For the new version you need to write to address SLINK_BASE + 8 to put a data word into the TX FIFO. That's why the HDL code evaluates bit 3 instead of bit 2:

tx_fifo.we <= '1' when (bus_req_i.stb = '1') and (bus_req_i.rw = '1') and (bus_req_i.addr(3) = '1') else '0'

Are you using some kind of hand-crafted low-level accesses for the SLINK module? I have updated the SLINK driver files so the changes in the low-level interface should not be noticeable. πŸ€”

/**********************************************************************//**
* Write data to TX link (non-blocking)
*
* @param[in] tx_data Data to send to link.
**************************************************************************/
inline void __attribute__((always_inline)) neorv32_slink_put(uint32_t tx_data) {
NEORV32_SLINK->TX_DATA = tx_data;
}

Please note that the low-level software access mechanism for the SLINK module has also changed in #815 (v1.9.5.5). The old software interface just used two memory-mapped registers:

Okay, I know what is going on!

The problem was that I hadn't recompiled the program with the new libraries.

Luckily I have an arty 100t in my house (good Christmas), I've generated a new app_image (compiling with container) and it works with the latest version:

res_mult

For the new version you need to write to address SLINK_BASE + 8 to put a data word into the TX FIFO. That's why the HDL code evaluates bit 3 instead of bit 2:

Okey, I understand.

Thank you very much for your quick feedback! πŸ˜„


EDIT:

Note that the tlast signal is not strictly necessary.

The problem was that I hadn't recompiled the program with the new libraries.
Luckily I have an arty 100t in my house (good Christmas), I've generated a new app_image (compiling with container) and it works with the latest version:

That's great! πŸŽ‰

Note that the tlast signal is not strictly necessary.

Right, just tie that input to zero if you do not need it.