AXI TDD
The AXI TDD (Time Division Duplexing) is an FPGA IP core driver that provides a waveform generator capable of addressing RF applications which require Time Division Duplexing, as well as controlling other modules through its dedicated output channels. It solves the synchronization issue when transmitting and receiving multiple frames of data through multiple buffers.
The driver implements:
Up to 32 independent output channels with configurable on/off timing
Per-channel enable and polarity control
Configurable frame length and burst count
Initial startup delay before waveform generation
Three synchronization sources: external, internal, and software-generated
Timing values in both raw clock cycles and milliseconds
Dynamic clock rate tracking via clock notifiers
Supported IP Cores
AXI TDD IP v2.0.a
Status
Source |
Mainlined? |
|---|---|
No |
Files
Function |
File |
|---|---|
driver |
|
devicetree |
|
sysfs ABI |
Documentation/ABI/testing/sysfs-bus-platform-drivers-adi-axi-tdd |
HDL documentation |
|
HDL IP core source code |
Overview
The AXI TDD controller is a generic waveform generator developed for use in Analog Devices HDL reference designs. Unlike previous TDD engines, this core operates only in standalone mode and is not embedded into other devices.
Each output channel has independently configurable on and off times relative to the start of a frame. The controller generates repeating frames of a configurable length, with an optional startup delay before the first frame. Multiple frames can be grouped into a burst, or the controller can run continuously until disabled.
Synchronization can be triggered from three sources:
Software sync: A one-shot trigger via the
sync_softattributeInternal sync: A periodic trigger generated by an internal counter with a configurable period
External sync: A trigger from an external signal, optionally synchronized into the core clock domain via a CDC (Clock Domain Crossing) circuit
Adding Linux driver support
Enabling the driver
Configure kernel with make menuconfig:
Linux Kernel Configuration
Device Drivers --->
Misc devices --->
<*> Analog Devices TDD Engine support
Adding a device tree entry
Required properties
compatible: Must be"adi,axi-tdd"reg: Physical base address and size of the IP core registersclocks: References to the system clock and the TDD core clockclock-names: Must be"s_axi_aclk","intf_clk"
Device tree example
Basic TDD core instance:
tdd@84a00000 {
compatible = "adi,axi-tdd";
reg = <0x84a00000 0x10000>;
clocks = <&zynqmp_clk PL0_REF>, <&zynqmp_clk PL1_REF>;
clock-names = "s_axi_aclk", "intf_clk";
};
TDD core with external clock source (e.g. HMC7044):
axi_tdd_0: axi-tdd-0@9c460000 {
compatible = "adi,axi-tdd";
reg = <0x9c460000 0x10000>;
clocks = <&zynqmp_clk PL0_REF>, <&hmc7044 6>;
clock-names = "s_axi_aclk", "intf_clk";
};
Driver testing
The TDD driver exposes a sysfs interface for configuration and monitoring.
Sysfs interface
The driver creates sysfs attributes under
/sys/bus/platform/drivers/adi-axi-tdd/<device>/.
Core attributes
Attribute |
Access |
Description |
|---|---|---|
|
RO |
IP core version (semantic versioning) |
|
RO |
ID configuration parameter value |
|
RO |
Identification code (0x5444444E = ‘T’,’D’,’D’,’N’) |
|
RW |
Scratch register for testing register access |
|
RO |
Current state of the peripheral FSM |
Control attributes
Attribute |
Access |
Description |
|---|---|---|
|
RW |
Enable or disable the TDD module |
|
WO |
Trigger one software sync pulse |
|
RW |
Enable or disable the external sync trigger |
|
RW |
Enable or disable the internal sync trigger |
|
RW |
Reset the internal counter on sync event |
Timing attributes
Attribute |
Access |
Description |
|---|---|---|
|
RW |
Number of frames per burst (0 = continuous) |
|
RW |
Initial delay before first frame (clock cycles) |
|
RW |
Initial delay before first frame (milliseconds) |
|
RW |
Frame length (clock cycles) |
|
RW |
Frame length (milliseconds) |
|
RW |
Internal sync generator period (clock cycles) |
|
RW |
Internal sync generator period (milliseconds) |
Per-channel attributes (N = 0..31)
Attribute |
Access |
Description |
|---|---|---|
|
RW |
Enable or disable output channel N |
|
RW |
Set the polarity of output channel N |
|
RW |
Channel N assertion offset from frame start (clock cycles) |
|
RW |
Channel N de-assertion offset from frame start (clock cycles) |
|
RW |
Channel N assertion offset from frame start (milliseconds) |
|
RW |
Channel N de-assertion offset from frame start (milliseconds) |
Example sysfs usage
The following example configures a burst of 2 pulses on channel 0, triggered by an external sync signal (e.g. a GPSDO 1 PPS output). Each frame is 2 ms long, and within each frame channel 0 is high from 0.8 ms to 1.8 ms (a 1 ms pulse). After the 2 frames complete, the output stays low until the next external sync event re-arms the core.
~$
cd /sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0
# Configure timing (must be done before enabling)
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 0.000000 > startup_delay_ms
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 2.000000 > frame_length_ms
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 2 > burst_count
# Configure channel 0: 1 ms pulse starting at 0.8 ms into each frame
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 0.800000 > out_channel0_on_ms
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 1.800000 > out_channel0_off_ms
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 1 > out_channel0_enable
# Use external sync as trigger source and enable
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 1 > sync_external
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
echo 1 > enable
# Verify the core is armed and waiting for sync
/sys/bus/platform/drivers/adi-axi-tdd/9c460000.axi-tdd-0$
cat state
Explanation of the configuration:
startup_delay_ms = 0: No extra delay before the first frame. Note that any startup delay applies to all channels equally.frame_length_ms = 2: Each frame is 2 ms long; GPIO toggles are spaced 2 ms apart.burst_count = 2: A burst of 2 frames is generated, then the core stops. Set to 0 for infinite (continuous) operation.out_channel0_on_ms = 0.8: Channel 0 asserts 0.8 ms after the frame starts. This acts as a per-channel delay relative to the sync trigger.out_channel0_off_ms = 1.8: Channel 0 de-asserts 1.8 ms after the frame starts. The resulting pulse width is 1.0 ms (1.8 - 0.8).sync_external = 1: The core waits for an external sync pulse to begin the burst.enable = 1: Arms the TDD core; it enters the ARMED state and waits for the configured sync event.
Theory of operation
Frame generation
The central idea of the TDD controller is “frame”-based operation: all timing
defined for individual channels is relative to the beginning of a frame. The
frame_length value controls the length of a single frame, while
burst_count controls how many frames should be played after enabling the
device (a value of 0 means frames repeat indefinitely). Before the start of a
burst, an optional startup delay is inserted, defined by startup_delay in
clock cycles.
The TDD core generates timing waveforms organized into frames:
When enabled, the core enters the ARMED state and waits for a sync event
After sync, it transitions to the WAITING state and the startup delay counter runs (if configured)
The core enters the RUNNING state and the frame counter begins, cycling through the configured frame length
Each channel output is asserted at its
ontime and de-asserted at itsofftime within the frameAfter the frame completes, the next frame begins
If
burst_countis non-zero, the core stops after that many frames and returns to IDLE; otherwise it runs continuously until disabled
FSM states
The peripheral transitions between four states. The current state can be read
via the state sysfs attribute, which returns the numeric value:
Value |
State |
Description |
|---|---|---|
0 |
IDLE |
The core is disabled or has completed its burst |
1 |
ARMED |
The core is enabled and waiting for a synchronization event |
2 |
WAITING |
A sync has been received; the startup delay is counting down |
3 |
RUNNING |
Frames are actively being generated |
Synchronization
Three sync sources are available and can be enabled simultaneously:
Software (
sync_soft): Write-only, generates a single pulse. Useful for triggering operation at an arbitrary point in time.Internal (
sync_internal): Periodic trigger from an internal counter. The period is configured viainternal_sync_period_raw/_ms.External (
sync_external): An external signal input, optionally processed through a CDC circuit (synthesis-time configuration). This allows alignment of frames between multiple devices in different locations, for example using a GPSDO 1 PPS output.
If a synchronization signal is received while the TDD core is already running,
the sync_reset attribute controls whether the internal counter is reset to
zero. This can alter the counter value in both the WAITING and RUNNING states.
Channel output
The TDD controller can have up to 32 output channels. Each channel produces a
single-bit output signal with unique on and off values that are
continuously compared to the internal counter while the core is RUNNING.
Within a frame:
The output is asserted (set to active level) at the
ontimeThe output is de-asserted (set to inactive level) at the
offtimeThe
polarityattribute inverts the active level for a channel
Every bit in CHANNEL_ENABLE / CHANNEL_POLARITY corresponds to a
specific channel. The bit position is correlated to the channel index: the LSB
is associated with channel 0 and the MSB with channel 31.
Timing values can be specified in raw clock cycles or milliseconds. The
millisecond values are converted to clock cycles using the intf_clk rate,
which is tracked dynamically via clock notifiers.
Register update restrictions
Warning
Most configuration registers cannot be modified while the TDD core is enabled. Any writes to these registers while the peripheral is enabled will be ignored.
The following attributes must be configured before enabling the peripheral:
burst_countstartup_delay_raw/startup_delay_msframe_length_raw/frame_length_msinternal_sync_period_raw/internal_sync_period_msout_channelN_polarityout_channelN_on_raw/out_channelN_on_msout_channelN_off_raw/out_channelN_off_ms
Exceptions:
out_channelN_enablecan be modified on-the-fly. The new value takes effect when the core enters the ARMED state or at the end of the current frame.enable,sync_soft,sync_external,sync_internal, andsync_reset(theCONTROLregister) can be modified on-the-fly with immediate effect.