usrp-users@lists.ettus.com

Discussion and technical support related to USRP, UHD, RFNoC

View all threads

Triggering of Rx synchronously with Tx in RFNoC

P
perper@o2.pl
Tue, Oct 1, 2024 9:09 AM

Hello all,

I know the topic of triggering of transmission and reception has been recurring here on the list over and over. But I haven’t found the answer that is good for my case among the previous threads .

The context: I'm using USRP X410 and I’m transmitting a pulsed radar waveform. I’m able to receive the return signal continuously, but I need to limit the stream of data sent to the PC. The good solution is to send precisely selected part of the received signal after each pulse. This way the radar can focus only on the most interesting area. For example to define: receive ‘N’ samples beginning in ‘R’ samples from the Tx pulse start (where ‘N’ and ‘R’ can be changed but it doesn’t happen often).

My current implementation with continuous reception looks like this: I’m using USRP X410 and in RFNoC I have a ‘Replay’ block connected to the DUC->Radio block. ‘DUC’ has upsampling set to ‘1’ - that make it pass samples without change from ‘Replay’ block. The ‘Replay’ block plays in a loop a pulse followed by zeros. The least significant bit of I part of IQ sample is connected to GPIO port and is used currently to control the RF front-end (switch between transmission and reception). This way I’m loosing one bit of transmitted IQ sample, but I have very precise control over the GPIO, so that it is synchronized with Tx pulse. For example, I can set that line a bit earlier than RF pulse in order to prepare the Tx chain for transmission.

Now in order to achieve what I described (receive ‘N‘ samples after each pulse) I wanted to reuse for triggering the reception the signal that currently controls the GPIO.

And here my question starts: where in RFNoC should I connect the triggering signal and implement the logic that controls passing the samples synchronously with the trigger?

I wanted to implement an RFNoC block that passes the samples synchronously with the trigger. In order to that I'll have to edit manually the RFNoC flowgraph in order to connect the trigger signal to additional input in the block (I can do that). I have doubt if I can trigger an event synchronously with the samples stream this way, but at the moment I have more basic issue. I don’t know yet how to ignore samples for arbitrarily long time with RFNoC use of block. I think the closest thing that exists in UHD to what I'm trying to do is rfnoc_keep_one_in_n. I'm trying to use some ideas from it but I've got no success yet.

Another solution could be use the trigger to control flow of the samples from ADC to the radio block, but I don’t know yet exactly how it could be implemented.

Maybe there is some better solution to that what I’m trying to do? Maybe I can use timed commands? But I don’t want to send them from PC as I would have to do that very often: for each pulse and pulse rate might be i.e. 2kHz.

Trying out each option means loosing more time - so maybe you have some advice which path is most promising?

Best Regards,
Piotr Krysik

Hello all, I know the topic of triggering of transmission and reception has been recurring here on the list over and over. But I haven’t found the answer that is good for my case among the previous threads . The context: I'm using USRP X410 and I’m transmitting a pulsed radar waveform. I’m able to receive the return signal continuously, but I need to limit the stream of data sent to the PC. The good solution is to send precisely selected part of the received signal after each pulse. This way the radar can focus only on the most interesting area. For example to define: receive ‘N’ samples beginning in ‘R’ samples from the Tx pulse start (where ‘N’ and ‘R’ can be changed but it doesn’t happen often). My current implementation with continuous reception looks like this: I’m using USRP X410 and in RFNoC I have a ‘Replay’ block connected to the DUC->Radio block. ‘DUC’ has upsampling set to ‘1’ - that make it pass samples without change from ‘Replay’ block. The ‘Replay’ block plays in a loop a pulse followed by zeros. The least significant bit of I part of IQ sample is connected to GPIO port and is used currently to control the RF front-end (switch between transmission and reception). This way I’m loosing one bit of transmitted IQ sample, but I have very precise control over the GPIO, so that it is synchronized with Tx pulse. For example, I can set that line a bit earlier than RF pulse in order to prepare the Tx chain for transmission. Now in order to achieve what I described (receive ‘N‘ samples after each pulse) I wanted to reuse for triggering the reception the signal that currently controls the GPIO. And here my question starts: where in RFNoC should I connect the triggering signal and implement the logic that controls passing the samples synchronously with the trigger? I wanted to implement an RFNoC block that passes the samples synchronously with the trigger. In order to that I'll have to edit manually the RFNoC flowgraph in order to connect the trigger signal to additional input in the block (I can do that). I have doubt if I can trigger an event synchronously with the samples stream this way, but at the moment I have more basic issue. I don’t know yet how to ignore samples for arbitrarily long time with RFNoC use of block. I think the closest thing that exists in UHD to what I'm trying to do is rfnoc_keep_one_in_n. I'm trying to use some ideas from it but I've got no success yet. Another solution could be use the trigger to control flow of the samples from ADC to the radio block, but I don’t know yet exactly how it could be implemented. Maybe there is some better solution to that what I’m trying to do? Maybe I can use timed commands? But I don’t want to send them from PC as I would have to do that very often: for each pulse and pulse rate might be i.e. 2kHz. Trying out each option means loosing more time - so maybe you have some advice which path is most promising? Best Regards,\ Piotr Krysik
M
mruane@silveredge-gs.com
Thu, Oct 3, 2024 4:41 AM

Hi Piotr,

I’m not familiar enough with RFNoC to be of assistance there, but your thought about controlling the flow of samples between the ADC and the radio block seems to have some merit.  We frequently timestamp the sample stream so that we can then tell the radio to, “Give me samples between time A and time B.”  Substituting your trigger for the timestamps, you essentially have the same circuit.  The easiest way to do it might be by editing the x410_ps_rfdc_bd block design in Vivado IP Integrator, and then exporting the new block design back to x410_ps_rfdc_bd.tcl so it will be built when you do a ‘make’.  If you don’t want anything sent to the PC between triggers, the basic implementation would be to put an AXI Stream FIFO between the ADC and radio block.  The input valid signal would be driven by the trigger, such that it would ignore the incoming samples when the trigger was low, and write the samples to the buffer when the trigger was high.  Depending on the configuration of the FIFO buffer, you could use it in ‘packet’ mode to send the whole buffer once there were a certain number of samples in it; OR, if you know that the PC can handle the new reduced rate without flow control, you could just set it to transmit samples as soon as it gets them (i.e. the wr_data_en signal would be equal to the inverted FIFO empty flag).

I’m sorry I don’t have an RFNoC-related answer.  We don’t use RFNoC, and I usually design the data-paths based on the requirements of other processing blocks in the design, and of the downstream equipment, exactly as you described in your question.

I’m happy to elaborate further if you have any questions.

Hope this helps,

Mike

Hi Piotr, I’m not familiar enough with RFNoC to be of assistance there, but your thought about controlling the flow of samples between the ADC and the radio block seems to have some merit. We frequently timestamp the sample stream so that we can then tell the radio to, “Give me samples between time A and time B.” Substituting your trigger for the timestamps, you essentially have the same circuit. The easiest way to do it might be by editing the x410_ps_rfdc_bd block design in Vivado IP Integrator, and then exporting the new block design back to x410_ps_rfdc_bd.tcl so it will be built when you do a ‘make’. If you don’t want anything sent to the PC between triggers, the basic implementation would be to put an AXI Stream FIFO between the ADC and radio block. The input valid signal would be driven by the trigger, such that it would ignore the incoming samples when the trigger was low, and write the samples to the buffer when the trigger was high. Depending on the configuration of the FIFO buffer, you could use it in ‘packet’ mode to send the whole buffer once there were a certain number of samples in it; OR, if you know that the PC can handle the new reduced rate without flow control, you could just set it to transmit samples as soon as it gets them (i.e. the wr_data_en signal would be equal to the inverted FIFO empty flag). I’m sorry I don’t have an RFNoC-related answer. We don’t use RFNoC, and I usually design the data-paths based on the requirements of other processing blocks in the design, and of the downstream equipment, exactly as you described in your question. I’m happy to elaborate further if you have any questions. Hope this helps, Mike
M
mruane@silveredge-gs.com
Thu, Oct 10, 2024 5:02 PM

Hi Piotr,

I just noticed that I had a typo in my reply to you.

Regarding the statement,

you could just set it to transmit samples as soon as it gets them (i.e. the wr_data_en signal would be equal to the inverted FIFO empty flag)

I called the control signal ‘wr_data_en‘, thinking of the enable signal on the downstream block.  From the perspective of the output of the FIFO, it would be the rd_en signal that is equal to the inverted FIFO empty flag.  So, whenever the FIFO has data in it (i.e. “not empty“) the rd_enable will be active.  It will be deactivated when the FIFO is empty.  If you need to generate a data_vld signal (to drive ‘wr_data_en‘ on the downstream block), you can do so by delaying a copy of rd_enable by a clock tick or two, depending on whether the output of the FIFO is registered.

Cheers,

Mike

Hi Piotr, I just noticed that I had a typo in my reply to you. Regarding the statement, > you could just set it to transmit samples as soon as it gets them (i.e. the wr_data_en signal would be equal to the inverted FIFO empty flag) I called the control signal ‘wr_data_en‘, thinking of the enable signal on the downstream block. From the perspective of the output of the FIFO, it would be the rd_en signal that is equal to the inverted FIFO empty flag. So, whenever the FIFO has data in it (i.e. “not empty“) the rd_enable will be active. It will be deactivated when the FIFO is empty. If you need to generate a data_vld signal (to drive ‘wr_data_en‘ on the downstream block), you can do so by delaying a copy of rd_enable by a clock tick or two, depending on whether the output of the FIFO is registered. Cheers, Mike
MB
Martin Braun
Fri, Oct 11, 2024 1:17 PM

Hey Piotr,

it took me a bit to respond because this is tricky question. And I still
don't have a great answer, but I also don't want to let you hang.

A few thoughts:

  • Maybe you just want to write an RFNoC block that drops samples in a
    regular pattern for you. That way you wouldn't rely on timed commands
    coming in all the time.
    • Actually, on the TX side, you might use the same thing. As the ATR pins
      follow the Tx state, you could fall back to not modifying the radio and
      simply using the standard ATR feature if you had a block that produced
      bursts the way you want them. Unless of course you want the TX chain to be
      running continuously, which might be the case here.
  • Timed commands to the radio could also come from the FPGA, although we
    don't have a good example for that. But the radio doesn't care who's
    sending the timed commands. Another RFNoC block could be sending stream
    commands in a regular fashion.

--M

On Tue, Oct 1, 2024 at 11:10 AM perper@o2.pl wrote:

Hello all,

I know the topic of triggering of transmission and reception has been
recurring here on the list over and over. But I haven’t found the answer
that is good for my case among the previous threads .

The context: I'm using USRP X410 and I’m transmitting a pulsed radar
waveform. I’m able to receive the return signal continuously, but I need to
limit the stream of data sent to the PC. The good solution is to send
precisely selected part of the received signal after each pulse. This way
the radar can focus only on the most interesting area. For example to
define: receive ‘N’ samples beginning in ‘R’ samples from the Tx pulse
start (where ‘N’ and ‘R’ can be changed but it doesn’t happen often).

My current implementation with continuous reception looks like this: I’m
using USRP X410 and in RFNoC I have a ‘Replay’ block connected to the
DUC->Radio block. ‘DUC’ has upsampling set to ‘1’ - that make it pass
samples without change from ‘Replay’ block. The ‘Replay’ block plays in a
loop a pulse followed by zeros. The least significant bit of I part of IQ
sample is connected to GPIO port and is used currently to control the RF
front-end (switch between transmission and reception). This way I’m loosing
one bit of transmitted IQ sample, but I have very precise control over the
GPIO, so that it is synchronized with Tx pulse. For example, I can set that
line a bit earlier than RF pulse in order to prepare the Tx chain for
transmission.

Now in order to achieve what I described (receive ‘N‘ samples after each
pulse) I wanted to reuse for triggering the reception the signal that
currently controls the GPIO.

And here my question starts: where in RFNoC should I connect the
triggering signal and implement the logic that controls passing the samples
synchronously with the trigger?

I wanted to implement an RFNoC block that passes the samples synchronously
with the trigger. In order to that I'll have to edit manually the RFNoC
flowgraph in order to connect the trigger signal to additional input in the
block (I can do that). I have doubt if I can trigger an event synchronously
with the samples stream this way, but at the moment I have more basic
issue. I don’t know yet how to ignore samples for arbitrarily long time
with RFNoC use of block. I think the closest thing that exists in UHD to
what I'm trying to do is rfnoc_keep_one_in_n. I'm trying to use some ideas
from it but I've got no success yet.

Another solution could be use the trigger to control flow of the samples
from ADC to the radio block, but I don’t know yet exactly how it could be
implemented.

Maybe there is some better solution to that what I’m trying to do? Maybe I
can use timed commands? But I don’t want to send them from PC as I would
have to do that very often: for each pulse and pulse rate might be i.e.
2kHz.

Trying out each option means loosing more time - so maybe you have some
advice which path is most promising?

Best Regards,
Piotr Krysik


USRP-users mailing list -- usrp-users@lists.ettus.com
To unsubscribe send an email to usrp-users-leave@lists.ettus.com

Hey Piotr, it took me a bit to respond because this is tricky question. And I still don't have a great answer, but I also don't want to let you hang. A few thoughts: - Maybe you just want to write an RFNoC block that drops samples in a regular pattern for you. That way you wouldn't rely on timed commands coming in all the time. - Actually, on the TX side, you might use the same thing. As the ATR pins follow the Tx state, you could fall back to not modifying the radio and simply using the standard ATR feature if you had a block that produced bursts the way you want them. Unless of course you want the TX chain to be running continuously, which might be the case here. - Timed commands to the radio could also come from the FPGA, although we don't have a good example for that. But the radio doesn't care who's sending the timed commands. Another RFNoC block could be sending stream commands in a regular fashion. --M On Tue, Oct 1, 2024 at 11:10 AM <perper@o2.pl> wrote: > Hello all, > > I know the topic of triggering of transmission and reception has been > recurring here on the list over and over. But I haven’t found the answer > that is good for my case among the previous threads . > > The context: I'm using USRP X410 and I’m transmitting a pulsed radar > waveform. I’m able to receive the return signal continuously, but I need to > limit the stream of data sent to the PC. The good solution is to send > precisely selected part of the received signal after each pulse. This way > the radar can focus only on the most interesting area. For example to > define: receive ‘N’ samples beginning in ‘R’ samples from the Tx pulse > start (where ‘N’ and ‘R’ can be changed but it doesn’t happen often). > > My current implementation with continuous reception looks like this: I’m > using USRP X410 and in RFNoC I have a ‘Replay’ block connected to the > DUC->Radio block. ‘DUC’ has upsampling set to ‘1’ - that make it pass > samples without change from ‘Replay’ block. The ‘Replay’ block plays in a > loop a pulse followed by zeros. The least significant bit of I part of IQ > sample is connected to GPIO port and is used currently to control the RF > front-end (switch between transmission and reception). This way I’m loosing > one bit of transmitted IQ sample, but I have very precise control over the > GPIO, so that it is synchronized with Tx pulse. For example, I can set that > line a bit earlier than RF pulse in order to prepare the Tx chain for > transmission. > > Now in order to achieve what I described (receive ‘N‘ samples after each > pulse) I wanted to reuse for triggering the reception the signal that > currently controls the GPIO. > > And here my question starts: where in RFNoC should I connect the > triggering signal and implement the logic that controls passing the samples > synchronously with the trigger? > > I wanted to implement an RFNoC block that passes the samples synchronously > with the trigger. In order to that I'll have to edit manually the RFNoC > flowgraph in order to connect the trigger signal to additional input in the > block (I can do that). I have doubt if I can trigger an event synchronously > with the samples stream this way, but at the moment I have more basic > issue. I don’t know yet how to ignore samples for arbitrarily long time > with RFNoC use of block. I think the closest thing that exists in UHD to > what I'm trying to do is rfnoc_keep_one_in_n. I'm trying to use some ideas > from it but I've got no success yet. > > Another solution could be use the trigger to control flow of the samples > from ADC to the radio block, but I don’t know yet exactly how it could be > implemented. > > Maybe there is some better solution to that what I’m trying to do? Maybe I > can use timed commands? But I don’t want to send them from PC as I would > have to do that very often: for each pulse and pulse rate might be i.e. > 2kHz. > > Trying out each option means loosing more time - so maybe you have some > advice which path is most promising? > > Best Regards, > Piotr Krysik > _______________________________________________ > USRP-users mailing list -- usrp-users@lists.ettus.com > To unsubscribe send an email to usrp-users-leave@lists.ettus.com >
P
perper@o2.pl
Mon, Nov 25, 2024 2:25 PM

Hello Martin,

Somehow I missed your reply.

In the meantime I’ve started from implementing what you described in the first point.

If anyone is interested - it appeared that ‘keep_one_in_n‘ was a very good starting point. I left the last state
machine that is responsible for forming output packets intact and I thrown away the state machines that
are responsible for setting ‘keep_sample‘ signal and written my own. That state machine sets ‘keep_sample’ signal
during some defined interval after sweep starts. This way it can work as long as pulse repetition interval isn’t changed
or there is no loss of synchronization between Tx and Rx RFNoC blocks (I’m still trying to find out if such sync
loss is possible i.e. when there is overflow).

It is also possible to reuse ‘keep_one_in_n‘ testbench to develop my block. For this I thrown away most of the
stuff that is responsible for automatic test stuff and just fed the block incremented integer in the ‘test_…’ task.
Testing is just checking if the right numbers are appearing at the output.

In case synchronization loss is possible I have at least two options:
- couple timestamps with the state machine that generates ‘keep_sample‘ signal,
- try to connect trigger from the replay blocks. As I can see in the specification RFNoC has some support for
connecting miscellaneous signals to RFNoC blocks in YAML.

Probably the best control in case of changes of pulse parameters could be obtained if the blocks passing
the samples and generating pulses for TX side would be combined into one block.

Best Regards,
Piotr Krysik

Hello Martin, Somehow I missed your reply. In the meantime I’ve started from implementing what you described in the first point. If anyone is interested - it appeared that ‘keep_one_in_n‘ was a very good starting point. I left the last state\ machine that is responsible for forming output packets intact and I thrown away the state machines that\ are responsible for setting ‘keep_sample‘ signal and written my own. That state machine sets ‘keep_sample’ signal\ during some defined interval after sweep starts. This way it can work as long as pulse repetition interval isn’t changed\ or there is no loss of synchronization between Tx and Rx RFNoC blocks (I’m still trying to find out if such sync\ loss is possible i.e. when there is overflow). It is also possible to reuse ‘keep_one_in_n‘ testbench to develop my block. For this I thrown away most of the\ stuff that is responsible for automatic test stuff and just fed the block incremented integer in the ‘test_…’ task.\ Testing is just checking if the right numbers are appearing at the output.\ \ In case synchronization loss is possible I have at least two options:\ \- couple timestamps with the state machine that generates ‘keep_sample‘ signal,\ \- try to connect trigger from the replay blocks. As I can see in the specification RFNoC has some support for\ connecting miscellaneous signals to RFNoC blocks in YAML. Probably the best control in case of changes of pulse parameters could be obtained if the blocks passing\ the samples and generating pulses for TX side would be combined into one block. Best Regards,\ Piotr Krysik
P
perper@o2.pl
Thu, Dec 12, 2024 12:28 PM

Hello All,

I’ve got an update regarding synchronization inside of FPGA between Tx and Rx after overflows.

I’ve checked that with measurements and there was no synchronization loss between replay block working on Tx side and our RFNoC block that selects samples on the Rx side, which is inserted between DDC and Rx streamer. Which is great.

Only thing that is not obvious yet is how to deal with data loss on the transport. We have some way to compute number of lost samples based on timestamps and account for that in the program working on the PC. However our RFNoC block doesn’t always set the timestamp correctly - when timestamp is attached to one of dropped samples timestamps are incorrect. So the computation of number of lost samples based on timestamps is not reliable. I think keep_one_in_n block has the same issue.

We can get around this issue with some hack that is good enough for us, but it would be better to have a solution that works in general case.

Best Regards,
Piotr Krysik

Hello All, I’ve got an update regarding synchronization inside of FPGA between Tx and Rx after overflows. I’ve checked that with measurements and there was no synchronization loss between replay block working on Tx side and our RFNoC block that selects samples on the Rx side, which is inserted between DDC and Rx streamer. Which is great. Only thing that is not obvious yet is how to deal with data loss on the transport. We have some way to compute number of lost samples based on timestamps and account for that in the program working on the PC. However our RFNoC block doesn’t always set the timestamp correctly - when timestamp is attached to one of dropped samples timestamps are incorrect. So the computation of number of lost samples based on timestamps is not reliable. I think keep_one_in_n block has the same issue. We can get around this issue with some hack that is good enough for us, but it would be better to have a solution that works in general case. Best Regards,\ Piotr Krysik