Skip to content

rfnoc_radio_loopback with rx-timestamps set to true always results in an overflow #956

Closed

Description

@climb4

Issue Description

Connecting radio blocks in a loopback configuration always results in an overflow unless enable_rx_timestamps(false) is called for the receiving end.
This happens for official images and for self-built ones.
In case this is expected behavior, I think it should be documented better, at least in the official example.
I also think the name enable_rx_timestamps should be adjusted, especially with the default being that they are enabled.

Setup Details

USRP X410, UHD 4.9.0.0, Linux

Steps to reproduce the problem

Load any official image, then run the example rfnoc_radio_loopback --rx-timestamps true

Additional Information

The output of running the example always looks like this:

[...]
Issuing start stream cmd...
Wait...
LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLOLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL

Activity

  1. mbr0wn commented on Nov 13, 2026

    @mbr0wn
    Contributor

    This is expected behaviour -- in fact, this use case is why we have that API in the first place. I agree though it's weird to not document that in the example.

  2. climb4 commented on Nov 13, 2026

    @climb4
    Author

    Thank you very much for clarifying.

    As a bit of a follow up, with the RX timestamps disabled I can now successfully run the loopback example (and my own derived code).
    However, as soon as I add blocks in the chain (using my own custom image) to the two radio blocks the overflow issues come back.

    I have now tried pretty much everything that came to mind, my goal is to create a chain of radio -> ddc -> custom OOT block -> duc -> radio, but even with just radio -> ddc -> duc -> radio, an overflow shows up.
    No matter the image's CHDR width, the buffer sizes of the stream endpoints and whether I connect them statically or dynamically.
    Is there something I'm missing? In my current version the CHDR width is 256 and each endpoint has a buffer size of 65536. I then connect everything up dynamically with each block having 2 dedicated stream endpoints (since NUM_PORTS is set to 2 for each of the 3).

  3. climb4 commented on Nov 13, 2026

    @climb4
    Author

    For reference, this is the image_core.yml I'm using:

    schema: rfnoc_imagebuilder_args
    copyright: TODO
    license: TODO
    version: '0.1'
    chdr_width: 256
    image_core_name: 'x4xx_image'
    default_target: 'X410'
    inherit:
    - 'yaml_include/x4xx_x4_base.yml'
    device: 'X410'
    
    parameters:
        RF_BW: 400
        ENABLE_DRAM: False
        NUM_DRAM_BANKS: 0
        NUM_DRAM_CHANS: 0
        DRAM_WIDTH: 64
    
    stream_endpoints:
        ep0:
            ctrl: True
            data: True
            buff_size_bytes: 65536
        ep1:
            ctrl: False
            data: True
            buff_size_bytes: 65536
        ep4:
            ctrl: False
            data: True
            buff_size_bytes: 65536
        ep5:
            ctrl: False
            data: True
            buff_size_bytes: 65536
        ep6:
            ctrl: False
            data: True
            buff_size_bytes: 65536
        ep7:
            ctrl: False
            data: True
            buff_size_bytes: 65536
    
    noc_blocks:
        radio0:
            block_desc: 'radio.yml'
            parameters:
                NUM_PORTS: 2
            ctrl_clock: _device_.rfnoc_ctrl
            timebase_clock: _device_.radio
        duc0:
            block_desc: 'duc.yml'
            parameters:
                NUM_PORTS: 2
        ddc0:
            block_desc: 'ddc.yml'
            parameters:
                NUM_PORTS: 2
    
    connections:
        - { srcblk: radio0,     srcport: ctrlport,  dstblk: _device_,   dstport: ctrlport_radio0    }
        - { srcblk: _device_,   srcport: radio0,    dstblk: radio0,     dstport: radio              }
        - { srcblk: _device_,   srcport: time,      dstblk: radio0,     dstport: time               }
    
        - { srcblk: ep0,    srcport: out0,  dstblk: radio0, dstport: in_0   }
        - { srcblk: radio0, srcport: out_0, dstblk: ep0,    dstport: in0    }
    
        - { srcblk: ep1,    srcport: out0,  dstblk: radio0, dstport: in_1   }
        - { srcblk: radio0, srcport: out_1, dstblk: ep1,    dstport: in0    }
    
        - { srcblk: ep4,    srcport: out0,  dstblk: duc0,   dstport: in_0   }
        - { srcblk: duc0,   srcport: out_0, dstblk: ep4,    dstport: in0    }
    
        - { srcblk: ep5,    srcport: out0,  dstblk: duc0,   dstport: in_1   }
        - { srcblk: duc0,   srcport: out_1, dstblk: ep5,    dstport: in0    }
    
        - { srcblk: ep1,    srcport: out0,  dstblk: radio0, dstport: in_1   }
        - { srcblk: radio0, srcport: out_1, dstblk: ep1,    dstport: in0    }
    
        - { srcblk: ep6,    srcport: out0,  dstblk: ddc0,   dstport: in_0   }
        - { srcblk: ddc0,   srcport: out_0, dstblk: ep6,    dstport: in0    }
    
        - { srcblk: ep7,    srcport: out0,  dstblk: ddc0,   dstport: in_1   }
        - { srcblk: ddc0,   srcport: out_1, dstblk: ep7,    dstport: in0    }
    
    clk_domains:
        - { srcblk: _device_,   srcport: radio, dstblk: radio0, dstport: radio  }
        - { srcblk: _device_,   srcport: ce,    dstblk: duc0,   dstport: ce     }
        - { srcblk: _device_,   srcport: ce,    dstblk: ddc0,   dstport: ce     }

    And the graphviz dot file for the connected graph:

    digraph rfnoc_graph {
      rankdir=LR
      node [shape=record]
    
      subgraph "cluster_0/Radio#0" {
        label="0/Radio#0"
        "0/Radio#0_in" [label="in|<in_0> 0|<in_1> 1"]
        "0/Radio#0_out" [label="out|<out_0> 0|<out_1> 1"]
      }
      "0/Radio#0_in" -> "0/Radio#0_out" [style=invis]
    
      subgraph "cluster_0/DDC#0" {
        label="0/DDC#0"
        "0/DDC#0_in" [label="in|<in_0> 0|<in_1> 1"]
        "0/DDC#0_out" [label="out|<out_0> 0|<out_1> 1"]
      }
      "0/DDC#0_in" -> "0/DDC#0_out" [style=invis]
    
      subgraph "cluster_0/DUC#0" {
        label="0/DUC#0"
        "0/DUC#0_in" [label="in|<in_0> 0|<in_1> 1"]
        "0/DUC#0_out" [label="out|<out_0> 0|<out_1> 1"]
      }
      "0/DUC#0_in" -> "0/DUC#0_out" [style=invis]
    
    
      "0/Radio#0_out":"out_0" -> "0/DDC#0_in":"in_0" [label="dynamic"]
      "0/DDC#0_out":"out_0" -> "0/DUC#0_in":"in_1" [label="dynamic"]
      "0/DUC#0_out":"out_1" -> "0/Radio#0_in":"in_1" [label="dynamic"]
    }

    Could this be a limitation of the single-sample implementation of DDC and DUC of UHD 4.9.0.0 so I'd have to either update to 4.11.0.0 or lower the bandwidth?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions