tx_path_top (LiteX)
Description
Top module for the Transmit (TX) path that accepts packetized IQ data, performs optional timestamp synchronization, adapts sample width, and unpacks payloads into a stream format suitable for the LMS7002/AFE TX datapath.
- Functionality:
Receive packetized IQ data on an AXI-Stream sink.
Cross from the sink clock domain to the TX domain using an asynchronous FIFO.
Buffer incoming packets into multiple per-packet FIFOs to allow timestamp-based alignment and loss handling.
Optionally synchronize to an external 64-bit sample counter; drop outdated packets and raise a sticky flag on loss.
Pad 12-bit IQ samples to 16-bit (bypass when 16-bit is selected).
Unpack 128-bit payload words into a 64-bit or 128-bit TX stream depending on channel mode.
Main block diagram
The top-level TX file integrates the following blocks:
Input CDC (input_buff) – Asynchronous FIFO crossing from the sink clock domain to the TX domain.
Slave Width Converter (conv_64_to_128) – Adapts the sink bus to a fixed 128-bit internal width.
Packet Buffer Writer (PCT2DATA_BUF_WR) – Writes incoming packets into one of BUFF_COUNT per-packet FIFOs.
Packet FIFOs (axis_fifo) – FIFOs designed to store one packet at a time.
Packet Buffer Reader (PCT2DATA_BUF_RD) – Selects the next packet to transmit, aligns by sample number and emits a continuous payload stream; reports packet loss.
Sample Padder (sample_padder) – Pads 12-bit samples to 16-bit; bypass in 16-bit mode.
Sample Unpacker (SAMPLE_UNPACK / sample_unpack128) – Converts 128-bit payload words into the downstream TX stream width and channel ordering.
Sample Nr CDC (smpl_nr_fifo) – Asynchronous FIFO to cross external timestampt to internal clock domain.
Clock domains
This module typically operates with three clock/reset domains:
s_clk_domain(sink clock domain) — Clock domain of the AXI-Stream sink that feeds packetized IQ data.m_clk_domain(source clock domain) — Main TX processing domain. All packet buffering, padding, and unpacking occur here; the AXI-Stream source also uses this domain.rx_clk_domain(sample nr clock domain) — Domain of the external sample counter input. The sample number is safely transferred intom_clk_domainvia a small CDC FIFO.
Packet format (expected at sink)
TX expects a similar packet structure to RX. A packet consists of a 64-bit header, a 64-bit timestamp, and a payload of up to PCT_MAX_SIZE - 16 bytes. PCT_MAX_SIZE is usually 4096 Bytes.
Field |
Byte Offset |
Size |
Description |
|---|---|---|---|
Header |
0 - 7 |
8 Bytes |
General packet header. |
Timestamp |
8 - 15 |
8 Bytes |
64-bit sample number used for alignment/synchronization. |
Payload |
16 - … |
up to PCT_MAX-16 |
IQ sample payload, interleaved by channels. |
When multiple channels are enabled, payload samples are ordered per enabled-channel set (e.g. A-only, A+B, B+D, or A+B+C+D in 4-channel mode). The unpack block converts these payload words to the downstream TX stream format.
Input CDC (input_buff)
The input_buff is a clock-domain crossing buffer:
Layout: one field,
dataof widthFIFO_DATA_W(default 128).From
s_clk_domaintom_clk_domain.Depth is derived from
input_buff_size / FIFO_DATA_W. The default sizing ensures at least 4 words of buffering for safe CDC.
Slave Width Converter (conv_64_to_128)
Adapts the sink bus to a fixed internal width of 128 bits using stream.Converter. If FIFO_DATA_W is already 128, the converter behaves as a pass-through.
Packet Buffer Write (PCT2DATA_BUF_WR)
Writes packets into one of BUFF_COUNT per-packet AXIS FIFOs. Exposes a vector of write-side handshake signals:
p2d_wr_tvalid/tdata/tlast(per buffer index)p2d_wr_treadyback-pressure from the selected FIFO
The module also consumes the global p2d_wr_buf_empty (one bit per buffer) to avoid selecting a full or busy buffer.
A Complete packet is written into a single FIFO and left untouched until consumed. Since the upstream width converter’s last is forced to 0, PCT2DATA_BUF_WR is the sole source of TLAST: it parses the header, derives the packet length, counts 128‑bit words, and asserts TLAST on the final word. Downstream blocks use this TLAST exclusively to mark end‑of‑packet (EOP), and buffer selection ensures a packet never spans multiple FIFOs.
Per-Packet AXIS FIFOs (axis_fifo)
The design instantiates BUFF_COUNT copies of an AXIS FIFO (generic VHDL, vendor-agnostic implementation). Each FIFO:
Data width equals
FIFO_DATA_W(default 128).Depth is
PCT_MAX_SIZE / FIFO_DATA_Wwords so a full packet fits in one FIFO.Per‑buffer reset (
p2d_rd_resetn[i]) is used only when the reader drops an outdated packet; normal end‑of‑packet does not reset the FIFO.
Configured with G_PACKET_MODE=true, these FIFOs do not parse packet size; they store and propagate the writer‑generated TLAST to preserve boundaries. Exactly one packet occupies a FIFO. tkeep is unused (all ones). Because a whole packet fits in one FIFO, mid‑packet buffer switches cannot occur.
Packet Buffer Read (PCT2DATA_BUF_RD)
Selects which buffer to read next and emits a continuous 128-bit stream:
Performs optional timestamp synchronization against the external sample number stream.
Drives
data_pad_tvalid/data_pad_tdata/data_pad_tlast.Exposes the current buffer index (
curr_buf_index) and a per‑buffer reset vector (p2d_rd_resetn) used only when a packet is dropped.Reports packet drops with
pct_loss_flg; a write topct_loss_flg_clrclears the sticky flag.
Synchronization inputs:
rx_sample_nr(64-bit) is written into a small CDC FIFO fromrx_clk_domainand read inm_clk_domainasrx_sample_nr_sync.synch_disdisables the synchronization logic when asserted.
The reader relies solely on the incoming TLAST from the selected FIFO to detect EOP; it does not infer size itself. It streams all words from the selected buffer until TLAST, then switches to the next buffer; it does not reset the FIFO on normal completion. Per‑buffer reset is asserted only when an outdated packet is dropped. data_pad_tlast mirrors the selected FIFO’s TLAST for downstream padder/unpacker logic. Sync can be disabled globally (synch_dis) or per‑packet via a header flag; the 128‑bit header+counter word is discarded with a one‑cycle ready override before payload streaming.
Sample Padder (sample_padder)
Pads 12-bit IQ samples up to 16 bits to match the downstream bus width. Controlled by smpl_width via an internal unpack_bypass signal:
smpl_width == 0b00→ 16-bit mode, padder is bypassed.Other values → 12-bit mode, padder inserts zero/sign extension up to 16 bits.
The padder feeds a small 128-bit SyncFIFO that provides additional decoupling before unpacking.
Sample Unpack (SAMPLE_UNPACK / sample_unpack128)
Unpacks 128-bit payload words into the final TX stream format:
2-channel mode (default):
SAMPLE_UNPACKemits a 64-bit TX stream containing interleaved 16-bit I/Q sample pairs for the enabled channels.4-channel mode (
output4channels=True):sample_unpack128emits a 128-bit TX stream with interleaved I/Q samples for channels A/B/C/D.
Channel selection is controlled by ch_en (propagated from the configuration manager). Only enabled channels are emitted.
Sample Nr CDC (smpl_nr_fifo)
Transfers the 64‑bit external sample counter from rx_clk_domain to m_clk_domain using a small async FIFO (LiteX ClockDomainCrossing) so the reader can align packets by timestamp.
The write side samples whenever ready, while the read side stays ready to expose the latest value with minimal latency.
The synchronized value (rx_sample_nr_sync) is compared in PCT2DATA_BUF_RD during WAIT_HEADER; sync can be disabled globally (synch_dis) or per‑packet via a header bit.
Interfaces and control
Sink:
self.sink— AXI-Stream, widthFIFO_DATA_W(default 128), clock domains_clk_domain.Source:
self.source— AXI-Stream, width 64 (2-ch) or 128 (4-ch), clock domainm_clk_domain.External sample counter input:
self.rx_sample_nr(64-bit), clocked inrx_clk_domain.Sticky status:
self.pct_loss_flg; clear withself.pct_loss_flg_clr.External reset:
self.ext_reset_n(active-low); additionally,rx_enfrom the configuration manager is synchronized into both sink and TX domains and used as part of the local resets.
Configuration registers (via fpgacfg_manager):
ch_en— Channel enable bitmap (2 or 4 bits depending on mode).smpl_width— 16-bit vs 12-bit selection (controls padder bypass).synch_dis— Disable timestamp synchronization when asserted.rx_en— Enables the path and participates in local reset generation.
Key parameters
Constructor parameters (with typical defaults):
IQ_WIDTH=12— Expected incoming IQ sample width before padding.PCT_MAX_SIZE=4096— Maximum packet size in bytes; per-packet FIFOs are sized accordingly.PCT_HDR_SIZE=16— Header (8B) + counter (8B) size in bytes.BUFF_COUNT=4— Number of per-packet FIFOs to pipeline/queue packets.FIFO_DATA_W=128— Internal packet data width; sink width. Converter adapts this to 128 if needed.rx_clk_domain='lms_rx'— Clock domain of external sample number input.m_clk_domain='lms_tx'— Main TX processing clock domain.s_clk_domain='lms_tx'— Sink clock domain; may equalm_clk_domainor be distinct.output4channels=False— Enable 4-channel output mode (128-bit source width); otherwise 2-channel (64-bit).input_buff_size=512— Depth in bits for the input CDC buffer sizing; must be >=FIFO_DATA_W * 4.
Notes
The packet write/read engines (
PCT2DATA_BUF_WR/RD) and the AXIS FIFOs are implemented in VHDL and are automatically converted for use within the LiteX build.pct_loss_flgasserts when a packet is dropped (e.g., outdated timestamp) and remains high until cleared bypct_loss_flg_clr.The top-level uses standard LiteX/Migen stream components for CDC and width conversion; all outputs are provided as AXI-Stream endpoints.