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

Vivado warnings/errors for SLINK AXI stream interface clocks

robhancocksed opened this issue Β· comments

Describe the bug
When using the AXI-Lite top-level interface, Vivado 2023.2 produces critical warnings like this for the AXI Stream interfaces for SLINK:

[BD 41-967] AXI interface pin /processor_subsystem/neorv32_SystemTop_ax_0/s1_axis is not associated to any clock pin. It may not work correctly.

This can also lead to block design validation errors when connecting the interfaces to other components such as the Xilinx AXI DMA, since Vivado cannot detect the correct clock frequency for the AXI stream interface (it seems to default to 100 MHz) and detects a mismatch with the other component. It is possible to work around this by manually setting the CLK_DOMAIN and/or FREQ_HZ parameter on the AXI stream interface on the NEORV32 core in the block design. However, it seems that these overridden settings do not always "stick" when exporting the block design back into tcl code for version control, so this is a nuisance to manage.

It looks like adding some dummy clock inputs to the top-level AXI wrapper (rtl/system_integration/neorv32_SystemTop_axi4lite.vhd) avoids this problem, for example:

    -- ------------------------------------------------------------
    -- AXI4-Stream-Compatible Interface --
    -- ------------------------------------------------------------
    -- Source --
    s0_axis_tdata  : out std_logic_vector(31 downto 0);
    s0_axis_tvalid : out std_logic;
    s0_axis_tlast  : out std_logic;
    s0_axis_tready : in  std_logic;
    s0_axis_aclk   : in  std_logic;
    -- Sink --
    s1_axis_tdata  : in  std_logic_vector(31 downto 0);
    s1_axis_tvalid : in  std_logic;
    s1_axis_tlast  : in  std_logic;
    s1_axis_tready : out std_logic;
    s1_axis_aclk   : in  std_logic;

Then if the same clock input used for m_axi_aclk is connected to these new clock ports, Vivado is able to figure out the clock domain for the AXI stream ports properly.

I guess the only downside of doing this is it might create the impression that the core supports using different AXI stream clocks from the main core clock, when it really doesn't. I suppose if you did try to use a mismatched clock it would probably end up with a timing failure, unless you happened to use clocks that were related/divisible which could just cause duplicate data words or something.

Good point. Seems like I have never used the SLINK in a Vivado block design... πŸ™ˆ

s0_axis_aclk : in std_logic;

Shouldn't the clock of the TX link be an output (controlled by the main clock of the CPU)?

s1_axis_aclk : in std_logic;

Hmm this might be a real problem... A real dual-clock FIFO inside the SLINK would be nice here - but this would be quite heavy to implement (in a platform-independent style). πŸ€”

Shouldn't the clock of the TX link be an output (controlled by the main clock of the CPU)?

It's arguable I suppose, but the usual convention for these with the Xilinx components (like their AXI DMA) seems to be to have the clock as an input for both the TX and RX sides, so the user can drive the clock however they want in the block design.

Hmm this might be a real problem... A real dual-clock FIFO inside the SLINK would be nice here - but this would be quite heavy to implement (in a platform-independent style). πŸ€”

I think some Xilinx IPs do some kind of magic to detect if the clocks are synchronous and use different implementations based on that, but that's probably not possible without some custom Xilinx tcl scripting magic. I guess you could have a generic to select between common-clock and cross-clock FIFOs without degrading the implementation for the common-clock use case. But if someone really wants to use a stream on a different clock domain they could already use some Xilinx IP like the AXI Stream Data FIFO to convert it, so I'm not sure it's that necessary. Maybe just documenting the limitation would be enough?

It's arguable I suppose, but the usual convention for these with the Xilinx components (like their AXI DMA) seems to be to have the clock as an input for both the TX and RX sides, so the user can drive the clock however they want in the block design.

This "feels" wrong. But okay, that is up to Vivado πŸ˜…

What do you think would happen if we add the AXIS clocks outputs to the core? Do you think Vivado / IP integrator could handle and resolve that?

But if someone really wants to use a stream on a different clock domain they could already use some Xilinx IP like the AXI Stream Data FIFO to convert it, so I'm not sure it's that necessary

πŸ‘

Maybe just documenting the limitation would be enough?

Absolutely!

Would you propose a PR for this? πŸ˜‰

What do you think would happen if we add the AXIS clocks outputs to the core? Do you think Vivado / IP integrator could handle and resolve that?

If you mean having the AXIS clocks be an output from the core, unfortunately that doesn't seem to work well, since Vivado doesn't know that it is the same clock as input on m_axi_aclk, and so that produces errors when connecting the interface about the CLK_DOMAIN and FREQ_HZ not matching between the two ends of the stream connection.

So it seems like having these as dummy clock inputs may be the best we can do easily.. if you're OK with that I can create a PR for that change?

So it seems like having these as dummy clock inputs may be the best we can do easily.. if you're OK with that I can create a PR for that change?

If that makes Vivado happy then I'm absolutely fine with it. πŸ‘ We should then simply add clear documentation about this.