All docsStellar LinkRF bench · by Stellar Systems v0.1.0

Signal Processing

Transmitter Chain

The TX datapath block by block: framer, FEC encoder, scrambler, marker insertion, preamble and fill, modulators, DUC and egress, with what configures each.

text
DMA (bytes) -> framer -> fec_tx -> scrambler -> asm_insert -> tx_fill
            -> modulator (BPSK | QPSK | GMSK, selected by MOD_SEL)
            -> duc_core -> tx_egress -> AD9361 DAC
                                     \-> loopback mux -> channel emulator -> RX chain

All blocks live in the TX window at 0x4003_0000, one 256-byte sub-window each. Register names below are the catalogue names used by satlinkctl reg, scenario reg: steps and watched registers.

framer#

Cuts the incoming byte stream into frames of FRAME_LEN bytes.

RegisterMeaningSet by
tx.framer.ctrl[0] enableProfile (always enabled)
tx.framer.frame_lenFrame length in bytes (223 at reset)framing.mtu_bytes (223 with Reed-Solomon)
tx.framer.padByte used to pad a short frameReset value 0x00
tx.framer.frame_cntFrames fully emittedRead: the traffic proof

A frame is closed on the byte count, or padded to FRAME_LEN when the stream's tlast arrives. The TX DMA raises tlast once per 4096-byte block, not per packet, which is why packet boundaries only survive with slot framing (see Datapath and Transmission).

fec_tx#

CCSDS 131.0-B encoder: Reed-Solomon (255,223) outer code, convolutional K=7 r=1/2 inner code (G1 = 171₈, G2 = 133₈).

RegisterMeaning
tx.fec_tx.ctrl[0] enable, [1] bypass RS, [2] bypass convolutional
tx.fec_tx.rateRead-only: r = 1/2
tx.fec_tx.status[0] busy, [1] RS active, [2] convolutional active
framing.fec.typectrl
none (and unimplemented types)0x7 (both bypassed)
conv0x3
rs0x5
rs+conv0x1

The output is one symbol per byte: the convolutional path emits two coded bits per output byte (the modulators consume the low bits); the bypass path keeps the same packing. The RS encoder uses the conventional basis, not the CCSDS dual basis.

scrambler#

CCSDS pseudo-randomiser x^8+x^7+x^5+x^3+1 on the coded stream, before the marker.

RegisterMeaning
tx.scrambler.ctrl[0] enable, [15:8] seed (0 selects the CCSDS default 0xFF)
tx.scrambler.status[0] in frame, [15:8] live PN state, [19:16] PN bit index
tx.scrambler.frame_cntFrames scrambled

The PN sequence restarts on the first beat of every frame. The register layout is identical to the receiver's rx_demod.deframer.scramble, and a profile writes the same value to both, so the two ends cannot disagree.

asm_insert#

Attaches the 32-bit sync marker in front of every coded frame, in the same symbol packing as the data (16 bytes in QPSK, 32 in BPSK/GMSK, MSB first). The marker is not scrambled.

RegisterMeaning
tx.asm_insert.ctrl[0] enable. Disabled, the block is transparent
tx.asm_insert.sync_wordThe marker (0x1ACFFC1D)
tx.asm_insert.status, tx.asm_insert.asm_cntEmitting flag, markers emitted

A profile without framing.sync_word disables it: raw frames, no marker, and a receiver that cannot frame.

tx_fill#

Inserts a preamble before a frame that follows a silence (64 clock cycles with no symbol), and up to a bounded amount of fill between frames, only at frame boundaries.

RegisterMeaning
tx.fill.ctrl[0] preamble enable, [1] inter-frame fill enable
tx.fill.pre_lenPreamble length in symbols (16 bits)
tx.fill.post_lenMaximum fill between frames in symbols (16 bits)
tx.fill.pat_hi, tx.fill.pat_loThe 64-bit pattern, read MSB first, 1 or 2 bits per symbol
tx.fill.status, tx.fill.pre_cnt, tx.fill.fill_cntState and counters

The default pattern 0x727252D02A1FEDD8 was searched for: at least 10 bits from every image of the CCSDS marker the deframer tests, zero mean in QPSK and BPSK (no carrier line), and a flat spectrum. See Modulation & Coding for the profile fields and the checks applied to a custom pattern.

Modulators#

tx.chan_cfg.mod_sel selects which modulator feeds the DUC: 0 = BPSK, 1 = QPSK, 2 = GMSK. The selected modulator must also be enabled (ctrl bit 0); a disabled one accepts symbols and drops them silently, which the chain's modulator condition catches.

BlockRegistersNotes
mod_bpskctrl, sps, coeff, statusRRC α = 0.35 shaping
mod_qpskctrl, sps, coeff, statusGray mapping, constellation at 1/√2 of full scale (0x5A82), RRC α = 0.35. Reads bits [1:0] of each byte
mod_gmskctrl, bt, sps, coeff, statusMSK-style continuous phase, differentially coded, linear phase ramp; no Gaussian filter (bt and coeff unused)

The coeff registers allow the RRC taps to be rewritten at runtime (tap index in the low 16 bits, Q15 coefficient in the high 16 bits); profiles do not use them.

tx.chan_cfg.freq_hz, baudrate and sps are descriptive: written by a profile as a record, consumed by nothing (only mod_sel drives the modulator mux).

duc_core#

Interpolates by INTERP and shifts the signal with an NCO.

RegisterMeaningSet by
tx.duc.ctrl[0] enableProfile
tx.duc.interpInterpolation factor 1 to 32Profile, from the symbol rate
tx.duc.gainQ15 gain (0x7FFF = unity)Profile; radio gain --domain digital
tx.duc.nco_freqQ32 phase incrementTuning (the LO offset), radio nco --tx-hz
tx.duc.filter_selCompensation FIR bank (0 = identity)—

The interpolator is a first-order linear interpolator; the compensation FIR is an identity placeholder. A profile apply does not touch nco_freq: the offset belongs to the tuning (see RF Fundamentals).

tx_egress#

The exit of the TX chain.

RegisterMeaning
tx.egress.ctrl[0] enable (the "TX egress"), [1] loopback enable: must stay 0
tx.egress.status[0] busy, [1] overflow
tx.egress.cntSamples out (clear on write)

With the egress closed, blocks keep arriving from the DMA and are discarded: the framer counter climbs while tx.egress.cnt stays still. A profile opens it when radio.tx_enabled is true; the RF kill switch closes it.

Bit 1 is a second loopback switch inside the egress. The PL loopback is selected by the shell's GLOBAL_CTRL[0] only; setting both would divert the samples away from the loopback path and starve it.

After the egress#

Samples cross from the modem clock to the AD9361 clock through an asynchronous FIFO into the axi_ad9361 DAC core. The DAC core's source selector (dac_data_sel) must be 2 (DMA) for the modem's samples to be transmitted; other sources are the internal DDS (0, used by scenario tone: steps), test patterns and PN sequences (used by the interface tuning). Chain conditioning sets and checks it (see Chain Conditioning).

When GLOBAL_CTRL[0] is set, the loopback mux sends the stream through the channel emulator into the RX chain instead (see Channel Models).

Stellar Link · v0.1.0

↑↓ to moveEnter to open