This is an old revision of the document!
TDD (Time-Division Duplex) mode allows the user to control the time period of the receive and transmit bursts.
The AXI TDD engine is a relatively simple peripheral originally intended to be used for TDD (wireless) communication systems. It solves the synchronization issue when transmitting and receiving multiple frames of data through multiple buffers.
Device Family | LUTs | FFs |
---|---|---|
Xilinx Zynq UltraScale+ | 990 | 2738 |
Name | Description |
---|---|
axi_tdd.v | Verilog source for the peripheral. |
ad_tdd_control.v | Main TDD controller - manages the signals |
up_tdd_cntrl.v | up interface (Later bridged to AXIL) |
cf_axi_tdd.c | TDD Linux Driver |
zynqmp-zcu102-rev10-ad9081-m8-l4-tdd.dts | Device tree using TDD |
The central idea of the TDD engine is “frame”-based operation, i.e. all the timing defined for the individual channels is relative to the beginning of a frame. The frame_length
parameter controls the length of a single frame, while the burst_count
parameter controls how many frames should be played after enabling the device (a value of 0 means frames will be repeated indefinitely). Another important aspect of the peripheral is the external synchronization capability, which allows the alignment of frames between multiple devices in different locations, for example using a GPSDO 1 PPS output.
This diagram tries to illustrate how the different channels can be enabled at different times relative to the beginning of a frame.
When there is asymmetry (caused by dynamically allocating the amount of time for uplink and downlink) between the data rates of the uplink and downlink, the IP is able to control when the RX buffer is read from and the TX buffer is played. There will be a fixed time offset between every i-th RX and TX sample, synchronizing the communication between the transmit and receive paths, as simple as possible, without using network synchronization.
AXI TDD divides data streams into frames and assigns different time slots to forward and reverse transmissions, sending and receiving the buffers in the initial order, and at specific and known times.
The TDD control contains 2 counters: a 24 bit free running counter for frames, and a 6 bit counter for bursts, the first one being compared with several configurable registers. Both counters can be configured to start from a certain value, through the corresponding registers (check the register map for TDD_COUNTER_INIT and TDD_BURST_COUNT).
The frame counter counts to the length of the current frame that is processed, and marks further if the end of the frame has been reached (also resetting the counter). Depending on the registers it is compared with, some control signals are turned on or off (for VCO and RF paths). The end of a burst is marked by the last burst and the end of the frame.
The frame counter is implemented using a state machine. When counter is working (ON state), and either the TDD is not enabled or it reached the end of burst, the counter in the next state will stop counting. When the counter is stopped (OFF state), it can be turned on again by enabling the TDD.
Interface | Pin | Type | Description |
---|---|---|---|
Core clock and reset | |||
clk | input | Core clock signal | |
rst | output | Core reset signal | |
TDD control interface | |||
tdd_enabled | output | Status signal | |
tdd_rx_vco_en | output | Output TDD control signal | |
tdd_tx_vco_en | output | Output TDD control signal | |
tdd_rx_rf_en | output | Output TDD control signal | |
tdd_tx_rf_en | output | Output TDD control signal | |
tdd_tx_valid | output | TX data flow control | |
tdd_rx_valid | output | RX data flow control | |
TDD sync interface | |||
tdd_sync | input | SYNC input for frame synchronization (1 PPS) | |
tdd_sync_cntr | output | SYNC output for frame synchronization (1 PPS) | |
AXI4 Lite interface | |||
s_axi_* | Standard AXI Slave Memory Map interface |
The linux driver defines an iio interface. The driver can be instantiated in the device tree as follows:
axi_tdd_0: axi-tdd-0@9c460000 { compatible = "adi,axi-tdd-1.00"; reg = <0x9c460000 0x10000>; clocks = <&zynqmp_clk PL0_REF>, <&hmc7044 6>; clock-names = "s_axi_aclk", "intf_clk"; };
clk
to calculate the required register values from the times provided to the iio attributes (T / clk_rate
).
The resulting IIO device looks like this, where there is one channel per combination of rx
, tx
and primary
, secondary
. Keep in mind that these channels are only used to structure their attributes, and don't carry any information themselves.
iio:device2: axi-core-tdd 4 channels found: data1: (output, WARN:iio_channel_get_type()=UNKNOWN) 6 channel-specific attributes found: attr 0: dp_off_ms value: 0 attr 1: dp_on_ms value: 0 attr 2: off_ms value: 0 attr 3: on_ms value: 0 attr 4: vco_off_ms value: 0 attr 5: vco_on_ms value: 0 data1: (input, WARN:iio_channel_get_type()=UNKNOWN) 6 channel-specific attributes found: attr 0: dp_off_ms value: 0 attr 1: dp_on_ms value: 0 attr 2: off_ms value: 0 attr 3: on_ms value: 0 attr 4: vco_off_ms value: 0 attr 5: vco_on_ms value: 0 data0: (output, WARN:iio_channel_get_type()=UNKNOWN) 6 channel-specific attributes found: attr 0: dp_off_ms value: 0 attr 1: dp_on_ms value: 0 attr 2: off_ms value: 0 attr 3: on_ms value: 0 attr 4: vco_off_ms value: 0 attr 5: vco_on_ms value: 0 data0: (input, WARN:iio_channel_get_type()=UNKNOWN) 6 channel-specific attributes found: attr 0: dp_off_ms value: 0 attr 1: dp_on_ms value: 0 attr 2: off_ms value: 0 attr 3: on_ms value: 0 attr 4: vco_off_ms value: 0 attr 5: vco_on_ms value: 0 10 device-specific attributes found: attr 0: burst_count value: 0 attr 1: counter_int value: 0 attr 2: dma_gateing_mode value: rx_tx attr 3: dma_gateing_mode_available value: rx_tx rx_only tx_only none attr 4: en value: 0 attr 5: en_mode value: rx_tx attr 6: en_mode_available value: rx_tx rx_only tx_only attr 7: frame_length_ms value: 0 attr 8: secondary value: 0 attr 9: sync_terminal_type value: 0 1 debug attributes found: debug attr 0: direct_reg_access value: 0x10061 No trigger on this device
zynqmp-zcu102-rev10-ad9081-m8-l4-tdd.dts | Device tree using TDD |