Merge branch 'feature/capture-redesign': Integrate capture redesign (multi-frame DMA + validation)

- Redesigned capture pipeline for multi-frame acquisition
- Added 128-bit packing and correct endianness handling
- Implemented and validated counter-based integrity checks
- Verified bypass, channelizer, and pulsed signal modes
- Validated scaling up to nFrames=1024 on ZCU111
- Added checkCounterSamples.m for end-to-end validation

This establishes a stable and validated acquisition baseline for
future work (timestamping, UDP streaming, FrFT processing).
This commit is contained in:
canisio
2026-04-29 10:15:07 -03:00
78 changed files with 514 additions and 160 deletions

View File

@@ -11,22 +11,35 @@ The system implements a high-throughput signal chain in the FPGA (PL) and perfor
## Current Status
- Tx subsystem: LFM pulse generator (DDS-based, complex output)
- Rx subsystem: fully functional channelizer pipeline (PFB-based)
- Rx subsystem: fully functional channelizer pipeline (PFB-based) or bypass
- PL → PS interface: AXI4-Stream + DMA operational
- PS processing: frame-based algorithm (RMS + peak detection)
- PS processing: frame-based algorithm on a Data Process Window (DPW)
---
## System Architecture
ADC → Channelizer (PFB, 512 bins)
FFT_Capture (frame control)
FIFO Serializer (4 FIFOs → 1 stream)
AXI4-Stream (uint64)
Tx (PL)
Waveform Generator (LFM / CW / Pulsed)
DAC
RF Loopback / Input
Rx (PL)
→ ADC
→ Channelizer (PFB, 512 bins) / Bypass / Counter
→ Capture (frame control)
→ AXI4-Stream (128-bit, 4 samples/clock)
→ DMA (S2MM)
→ PS Memory
→ Processor Algorithm
Post Processing (PS)
→ Triggered Capture
→ Sample Unpacking (I/Q)
→ Data Reshaping → [FrameSize x nFrames x nTriggers]
→ Host Communication / Processing / Visualization
→ One DPW is a windows of FrameSize x nFrames samples
---
## Key Parameters

Binary file not shown.

Binary file not shown.

View File

@@ -6,11 +6,9 @@
## Overview
The Rx subsystem implements a **polyphase filter bank (PFB) channelizer** followed by FFT processing.
The Rx subsystem implements a **polyphase filter bank (PFB) channelizer** followed by FFT processing, a **bypass path**, and a **multi-frame capture pipeline**.
It converts wideband ADC input into frequency-domain channels and streams the result to the PS.
A **bypass path** is also available for raw data inspection and debugging.
It converts wideband ADC input into frequency-domain channels (or raw samples via bypass) and streams the result to the PS.
---
@@ -24,11 +22,9 @@ PFB Channelizer (Decimation + Filtering)
FFT (512 bins)
FFT Capture
Capture (frame control)
FIFO Serializer (4 → 1)
AXI4-Stream
AXI4-Stream (128-bit, 4 samples/clock)
DMA
@@ -40,45 +36,26 @@ ADC
Bypass Path
FIFO / Serializer
Capture (frame control)
AXI4-Stream
AXI4-Stream (128-bit, 4 samples/clock)
DMA
---
## Bypass Functionality
## Capture Pipeline
The bypass allows direct observation of the input signal without channelization.
### Purpose
- Debugging and validation
- Access to raw ADC-domain data
- Comparison with channelized output
- Verification of downstream processing
---
- Multi-frame acquisition (configurable nFrames)
- Frame size: 512 samples
- Supports asynchronous capture start (not frame-aligned)
- TLAST asserted at frame boundaries
### Behavior
- Input data is routed directly to output
- No filtering or FFT applied
- Maintains same output interface (AXI4-Stream)
---
### Selection Mechanism
A selector signal chooses between:
- Channelizer output (normal operation)
- Bypass output (raw data)
Implementation typically uses:
- Parallel paths
- Output switching logic
- First frame may be partial
- Frames may contain ≤ 2 frame indices (expected)
- DPW spans nFrames frames but covers nFrames + 1 frame regions
---
@@ -86,6 +63,7 @@ Implementation typically uses:
### ADC Input
- Sampling rate: 4096 MSPS
- Data type: **fixdt(1,16,15)** (Q1.15)
### PFB Channelizer
- Decimation: 8
@@ -95,35 +73,67 @@ Implementation typically uses:
- Size: 512
- Produces frequency bins
### FFT Capture
- Controls frame boundaries
### Capture
- Defines frame boundaries (512 samples)
- Generates TLAST
### FIFO Serializer
- Converts parallel streams into single stream
---
## Numeric Format and Scaling
### System Standardization
- End-to-end Q1.15 (**fixdt(1,16,15)**)
### Channelizer Output Scaling
- Native: **sFix25_En23**
- Quantized to: **fixdt(1,16,15)** (round + saturate)
---
## Data Packing (Updated)
- 4 samples per clock
- Each sample: complex (16-bit real + 16-bit imag)
- Packed into **128-bit AXI4-Stream word**
Benefits:
- Matches datapath parallelism
- Efficient DMA transfers
- Eliminates need for serializer stage
---
## AXI4-Stream Output
- Data type: uint64
- Packed real/imag
- Width: 128 bits
- Contains 4 complex samples per cycle
- TLAST = frame boundary
---
## Data Format
## Debug / Validation Features
- Frame size: 512 samples
- Complex values packed into uint64
A counter-based debug mode is implemented:
- Real part → sample counter (0..511)
- Imag part → frame index
Used to validate:
- Sample continuity
- Frame boundaries
- DMA ordering and integrity
---
## Key Characteristics
- Fully streaming pipeline
- High throughput
- Deterministic latency
- Supports dual-mode operation (channelizer / bypass)
- High throughput (4 samples/clock)
- Dual-mode operation (channelizer / bypass)
- Validated up to nFrames = 1024
---

View File

@@ -1,4 +1,4 @@
# 🧠 PS Subsystem (Control + Processing)
# 🧠 PS Subsystem (Control + Capture + Processing)
[🏠 Project Home](../README.md)
@@ -8,73 +8,128 @@
The PS subsystem is responsible for:
- System initialization
- Configuring PL subsystems
- Triggering captures
- Receiving data via DMA
- Performing frame-based processing
- Preparing data for processing and visualization
The current implementation acts as a **placeholder for post-processing**, focusing on reliable data acquisition and host interaction.
---
## Responsibilities
### Control
### Control & Initialization
- Writes parameters to PL registers:
- Tx generator configuration
- Generates TxPulseStart trigger
- Configure PL parameters:
- Tx waveform configuration
- Capture parameters (nFrames, etc.)
- Initialize DMA and memory buffers
- Manage system startup
---
### Trigger & Capture
- Generates capture trigger (software-controlled)
- Controls DPW acquisition timing
- Each trigger initiates one DPW capture
---
### DMA Handling
- AXI4-Stream → DMA (S2MM)
- Data stored in PS DDR
- Receives **128-bit stream** (4 samples per clock)
- Stores data in PS DDR memory
Configuration:
- Frame size: 512
- Buffers: 16
- Frame size: 512 samples
- nFrames: configurable (validated up to 1024)
---
### Processing Pipeline
## Data Format
DMA → uint64[512]
→ unpack real/imag
→ convert to complex
→ RMS + peak detection
### Raw DMA Data
- Packed complex samples
- 16-bit real + 16-bit imag per sample
- 4 samples per 128-bit word
---
### Processing Representation
Data is unpacked and reshaped into:
```
[FrameSize x nFrames x nTriggers]
```
---
## Processing Pipeline (Current)
DMA
→ Unpack samples (I/Q separation)
→ Convert to complex representation
→ Reshape into 3D structure
→ Visualization / basic analysis
---
## Validation Support
Uses counter-based validation:
- Real part → sample counter
- Imag part → frame index
Enables verification of:
- Data continuity
- Frame alignment
- Correct ordering from DMA
---
## Execution Model
- Event-driven (DMA trigger)
- No buffering queue
- Frames may be dropped
- Triggered (event-based)
- Burst capture (DPW)
- Not continuous real-time streaming
---
## Performance Notes
- Bottleneck: unpacking + conversion
- Cannot sustain full-rate input
- Designed for correctness and validation (not optimized)
- Bottleneck: unpacking + data movement
- Full-rate continuous processing not supported
---
## Interaction with PL
## Role in System
### Tx Control
- Low-rate trigger (~Hz)
- Starts burst generation
The PS currently serves as:
### Rx Data
- Continuous high-rate stream
- Control interface
- Data acquisition manager
- Pre-processing stage
Future implementations will replace the current processing with advanced algorithms (e.g., FrFT).
---
## Future Work
- Replace processing with FrFT
- NEON optimization
- Throughput improvements
- FrFT-based processing
- Timestamp integration
- UDP streaming
- Optimization (NEON / vectorization)
- Metadata extraction (move complexity to PL)
---

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="TBc_lfm_fracF.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="fracF_cg.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="bizinter.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="fracF_ref.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="TBm_lfm_fracF.slx" type="File"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="post_processing" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="bypass_block" Type="Relative"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="088fd74d-4620-4cf8-826f-495fb91d19ae" type="Reference"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="block_pulsegen" Type="Relative"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="6a9c972f-52d5-42e0-8c82-940b26905df7" type="Reference"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="capture_block" Type="Relative"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="14d75155-da33-4258-97c9-15567dccec3d" type="Reference"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="block_bypass" Type="Relative"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="f7229047-4926-407b-902a-a25e790af1a9" type="Reference"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="pulsegen_block" Type="Relative"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="e221a7ac-a0f0-4b2d-8909-e0ce275dca2e" type="Reference"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="block_capture" Type="Relative"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="c26ab781-2c03-423c-8199-bc6903e4e4f7" type="Reference"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="utilities/post_processing" Type="Relative"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="5bfc0575-1eef-448a-a3a2-ced40deb5860" type="Reference"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="frft_codegen" Type="Relative"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="7b5b7cf9-d79f-4236-86f3-d37f9b8a15b3" type="Reference"/>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="design"/>
</Category>
</Info>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info File="gm_soc_rfsoc_top_sw.slx" GroupUUID="default" Icon="" Name="Open Interface model" Type="Basic" Visible="1"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="881a1955-5626-41b7-9355-a04f7db84232" type="EntryPoint"/>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="design"/>
</Category>
</Info>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="checkTimeSamples.m" type="File"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="checkFreqSamples.m" type="File"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="checkCounterSamples.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="capture_block" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="frft_codegen" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="bypass_block" type="File"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="block_pulsegen" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="pulsegen_block" type="File"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="block_capture" type="File"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="block_bypass" type="File"/>

Binary file not shown.

View File

@@ -0,0 +1,116 @@
%% =========================================================
% Data
% =========================================================
clc;
X = raw_DPW.Data; % [512 x nFrames x nTime]
% Remove first DPW if needed (initialization artifact)
X = X(:,:,2:end);
[nSamples, nFrames_cfg, nTime] = size(X);
%% =========================================================
% PARAMETERS
% =========================================================
COUNTER_MAX = 511; % counter: 0..511
%% =========================================================
% VALIDATION
% =========================================================
for t = 1:nTime
fprintf('\n=== Checking DPW %d ===\n', t);
X_dpw = X(:,:,t);
% Flatten stream
x_seq = reshape(X_dpw, [], 1);
% Extract stored integers
real_seq = double(storedInteger(real(x_seq))); % sample counter
frame_seq = double(storedInteger(imag(x_seq))); % frame index
%% -----------------------------------------------------
% 1. Sample progression
% -----------------------------------------------------
d_real = diff(real_seq);
valid_steps = (d_real == 1) | (d_real == -COUNTER_MAX);
if all(valid_steps)
fprintf(' Sample progression OK\n');
else
idx = find(~valid_steps, 1);
fprintf(' Sample progression ERROR at index %d\n', idx);
end
%% -----------------------------------------------------
% 2. Detect counter wraps (511 0)
% -----------------------------------------------------
wrap_idx = find(real_seq(1:end-1) == COUNTER_MAX & real_seq(2:end) == 0);
fprintf('Detected wraps: %d (configured: %d)\n', ...
length(wrap_idx), nFrames_cfg);
if length(wrap_idx) == nFrames_cfg
fprintf(' Wrap count matches configuration\n');
else
fprintf(' Wrap count mismatch\n');
end
%% -----------------------------------------------------
% 3. Check frame increment at wraps (no wrap logic)
% -----------------------------------------------------
ok_wrap = true;
for k = 1:length(wrap_idx)
i = wrap_idx(k);
f_before = frame_seq(i);
f_after = frame_seq(i+1);
if f_after ~= f_before + 1
fprintf(' Frame increment error at idx %d (%d %d)\n', ...
i, f_before, f_after);
ok_wrap = false;
break;
end
end
if ok_wrap
fprintf(' Frame increments correctly at all wraps\n');
end
%% -----------------------------------------------------
% 4. Informative: frame regions (+1 effect)
% -----------------------------------------------------
d_frame = diff(frame_seq);
nFrames_detected = sum(d_frame == 1) + 1;
fprintf('Frame regions (including partial): %d (expected: %d + 1)\n', ...
nFrames_detected, nFrames_cfg);
%% -----------------------------------------------------
% 5. Optional: per-frame sanity (2 indices)
% -----------------------------------------------------
frame_idx_matrix = storedInteger(imag(X_dpw));
frame_ok = true;
for f = 1:nFrames_cfg
u = unique(frame_idx_matrix(:,f));
if length(u) > 2
fprintf(' Frame %d has >2 frame indices\n', f);
frame_ok = false;
break;
end
end
if frame_ok
fprintf(' Frame structure OK (2 indices per frame)\n');
end
end

View File

@@ -0,0 +1,87 @@
%% =========================================================
% Data
% =========================================================
X = single(raw_DPW.Data); % [512 x nFrames x nTime]
X = X(:,:,2:end); % First DPW is zeroed
X = 2*X; % Rescale (see channelizer block on PL)
[nSamples, nFrames, nTime] = size(X);
N = nSamples;
%% =========================================================
% Parameters
% =========================================================
Fs = 512e6; % Hz
f_axis = (-N/2 : N/2-1) * (Fs/N) / 1e6; % MHz
%% =========================================================
% Apply fftshift per frame (dim = 1)
% =========================================================
X_shift = fftshift(X, 1);
%% =========================================================
% Convert to power
% =========================================================
P = abs(X_shift).^2;
%% =========================================================
% OPTION 1 Mean Spectrum (over frames AND time)
% =========================================================
P_mean = mean(P, [2 3]); % average over frames and triggers
P_mean = squeeze(P_mean); % [512 x 1]
figure;
plot(f_axis, 10*log10(P_mean + 1e-12), 'LineWidth', 1.5);
grid on;
xlabel('Frequency (MHz)');
ylabel('Power (dB)');
title('Mean Channelized Spectrum (Frames + Time)');
%% =========================================================
% OPTION 2 Max Spectrum (detect intermittent peaks)
% =========================================================
P_max = max(P, [], [2 3]);
P_max = squeeze(P_max);
figure;
plot(f_axis, 10*log10(P_max + 1e-12), 'LineWidth', 1.5);
grid on;
xlabel('Frequency (MHz)');
ylabel('Power (dB)');
title('Max Channelized Spectrum (Frames + Time)');
%% =========================================================
% OPTION 3 Time-Frequency Visualization
% =========================================================
% Collapse frames keep time evolution
P_time = squeeze(mean(P, 2)); % [512 x nTime]
figure;
surf(1:nTime, f_axis, 10*log10(P_time + 1e-12), 'EdgeColor','none');
view(2);
axis tight;
xlabel('Trigger Index');
ylabel('Frequency (MHz)');
title('Channelizer Output Over Time');
colorbar;
%% =========================================================
% OPTIONAL Frame evolution inside a single trigger
% =========================================================
t_sel = nTime; % pick last capture
P_frame = squeeze(P(:,:,t_sel)); % [512 x nFrames]
figure;
surf(1:nFrames, f_axis, 10*log10(P_frame + 1e-12), 'EdgeColor','none');
view(2);
axis tight;
xlabel('Frame Index');
ylabel('Frequency (MHz)');
title(['Channelizer Output Within DPW (Trigger ', num2str(t_sel), ')']);
colorbar;

View File

@@ -0,0 +1,84 @@
%% =========================================================
% Data
% =========================================================
X = single(raw_DPW.Data);
X = X(:,:,1:end); % first DPW useless (zeroed)
%% =========================================================
% Parameters
% =========================================================
Fs = 512e6; % Sampling rate (Hz)
N = 512; % Frame size
% Your data variable (rename if needed)
% Expected size: [512 x 4 x 8]
% X(frameSamples, frameIndex, timeIndex)
% Example: X = your_workspace_variable;
[nSamples, nFrames, nTime] = size(X);
%% =========================================================
% FFT Computation
% =========================================================
FFT_all = zeros(N, nFrames*nTime);
idx = 1;
for t = 1:nTime
for f = 1:nFrames
x = X(:, f, t);
% Optional window (uncomment if needed)
% w = hann(N);
% x = x .* w;
Xf = fftshift(fft(x));
FFT_all(:, idx) = abs(Xf);
idx = idx + 1;
end
end
%% =========================================================
% Axes
% =========================================================
f_axis = (-N/2 : N/2-1) * (Fs/N) / 1e6; % MHz
t_axis = 1:(nFrames*nTime); % frame index
%% =========================================================
% Spectrogram-like view (BEST)
% =========================================================
figure;
surf(t_axis, f_axis, 20*log10(FFT_all + 1e-12), 'EdgeColor', 'none');
view(2);
axis tight;
xlabel('Frame index');
ylabel('Frequency (MHz)');
title('FFT over time (per frame)');
colorbar;
%% =========================================================
% 3D Visualization (optional)
% =========================================================
figure;
surf(t_axis, f_axis, FFT_all, 'EdgeColor', 'none');
xlabel('Frame index');
ylabel('Frequency (MHz)');
zlabel('Magnitude');
title('3D FFT evolution');
%% =========================================================
% Single frame debug (optional)
% =========================================================
figure;
x_dbg = X(:,end,end);
Xf_dbg = fftshift(fft(x_dbg));
plot(f_axis, 20*log10(abs(Xf_dbg)+1e-12));
grid on;
xlabel('Frequency (MHz)');
ylabel('Magnitude (dB)');
title('Single Frame FFT');

View File

@@ -23,22 +23,26 @@ NCOCountIncDT = numerictype(1,NCOAccumWL*2,NCOAccumWL);
%% Test signal parameters
% Pulse width
pulseWidth = 4e-6;
% Pulse start/end frequencies
pulseCentFreq = 100e6;
pulseBw = 5e6; % Pulse bandwidth
pulseCentFreq = 0e6;
pulseBw = 50e6; % Pulse bandwidth
% Number of pulses
numPulses = 10;
% Pulse repetition interval
PRF = 20e3;
PRF = 7.5e3;
PRI = 1/PRF;
% Pulse time duration
%pulseT = 10; % use very long pulse help emulate CW
pulseT = 10e-6;
% CW mode (bypass pulse generation)
CwMode = true;
CwMode = false;
% Counter mode (bypass pulse and CW generation)
CounterMode = true;
% Output gain
pulseGenGain = 1;
@@ -46,12 +50,12 @@ pulseGenGain = 1;
%% Software parameters
% Signal generator update rate
TsSW = 0.5e-3;
TsSW = 0.5;
%% Simulation parameters
% Sim run time
stoptime = 10*TsSW;
%stoptime = TsFPGA*(9 + 1*348 + 1 + 2*128 + 1); %10*TsSW; %TsFPGA*(1*128+348)
%% Channelizer parameters
@@ -74,8 +78,8 @@ channelizerCoeffs = channelizer.coeffs.Numerator;
%Starting frequency for each channel
%chanFStart = chanBW/2:chanBW:(fs/2-chanBW/2);
%Number of frames out of channelzier
nFrames = nChan/SamplesPerCycle;
%Number of frames in the DPW
nFrames = 1024;%nChan/SamplesPerCycle;
% Frame size after serializing x2
%frameSize = SamplesPerCycle/2;

View File

@@ -1,5 +1,10 @@
%% Check if top model is loaded
if ~bdIsLoaded('soc_rfsoc_top')
load_system('soc_rfsoc_top');
end
%% Get parameters configured on the block
IntDecFactor = str2double(get_param([bdroot '/RF Data Converter'], ...
IntDecFactor = str2double(get_param(['soc_rfsoc_top' '/RF Data Converter'], ...
'interpolationMode')); % Interpolation and decimation factor
SamplesPerCycle = str2double(get_param([bdroot '/RF Data Converter'], ...
SamplesPerCycle = str2double(get_param(['soc_rfsoc_top' '/RF Data Converter'], ...
'dacSamplesPerCycle')); % samples per FPGA cycle