SatLink SDR is a software-defined radio test bench for satellite communication links. It runs on
a Xilinx Zynq-7020 system-on-chip wired to an Analog Devices AD9361 RF transceiver. The FPGA
fabric (the PL) carries a complete modem: framing, coding, scrambling, modulation, a channel
emulator and a demodulator. The ARM cores (the PS) run a Linux daemon, satlinkd, which drives
the modem, runs test scenarios and exposes the whole bench over HTTP, WebSocket and ZeroMQ.
The bench is meant for testing satellite radios and ground-segment software before a spacecraft exists: send telecommands and telemetry through a real modem, degrade the link in a controlled way, and measure what comes out the other side.
What it does#
| Capability | In short | Read more |
|---|---|---|
| Modem | BPSK, QPSK and GMSK at 4 samples per symbol, CCSDS attached sync marker, CCSDS randomiser, convolutional K=7 r=1/2 and Reed-Solomon (255,223) coding, preamble and inter-frame fill | Modulation & Coding |
| Radio profiles | One YAML file describes a complete radio configuration; applying it writes about 55 PL registers and tunes the AD9361 | RF Profiles |
| Loopback paths | PL loopback (the modem feeds its own receiver through the channel emulator), AD9361 digital loopback, and on-air through the RF connectors | Chain Conditioning |
| Channel emulation | Frequency offset and Doppler, attenuation, additive noise, burst errors and link mute, applied in the fabric on the PL loopback path | Channel Models |
| Scenarios | A YAML timeline of channel changes, traffic, packets, radio settings, register writes and tones, judged by assertions on measured telemetry | Scenarios |
| Campaigns | Ordered runs of scenarios, board actions and gates, with a cursor that survives a reboot | Campaigns |
| External link | A ZeroMQ bridge: push frames into the modem, subscribe to received frames and telemetry | ZeroMQ Link Service |
| Telemetry | EVM, SNR/MER, lock flags, AGC gain, RSSI, frame and symbol counters, sampled at 5 Hz | Telemetry and Metrics |
| Traceable releases | One identifier ties the bitstream, the daemon and the firmware together, readable from the running board | Releases and Deployment |
Main parts#
flowchart LR
subgraph Host["Operator host"]
cli[satlinkctl CLI]
web[Web console]
cc[Control centre / harness]
end
subgraph PS["Zynq PS (Linux)"]
d[satlinkd]
api[REST + WebSocket :8080]
zmq[ZeroMQ :5555-5557]
d --- api
d --- zmq
end
subgraph PL["Zynq PL (FPGA)"]
tx[TX chain] --> mux{loopback mux}
mux -->|PL loopback| ch[channel emulator] --> rx[RX chain]
mux -->|RF| ad[axi_ad9361]
ad --> rx
end
cli --> api
web --> api
cc <--> zmq
d -- "AXI-Lite registers (/dev/uio0)" --> PL
d -- "DMA (IIO buffers)" --> PL
ad <--> rf((AD9361 / antenna port))| Part | What it is |
|---|---|
| PL bitstream | SystemVerilog modem datapath (pl/), the channel emulator, monitors, and ADI's axi_ad9361 interface core, built with Vivado for part xc7z020clg400-1 |
satlinkd | The control daemon (Rust, ps/satlinkd). Loads profiles, scenarios and campaigns, drives the PL through a UIO register window and two IIO DMA devices, runs the scenario and campaign engines, serves the API and the link bridge |
satlinkctl | The operator CLI (Rust, ps/satlinkctl). Talks to the daemon's REST API; a few commands (compare) run entirely on the host |
| Web console | A React application (frontend/) that runs on your host and talks to the board's API |
| DSL files | Profiles, scenarios and campaigns in YAML (dsl/), shipped on the board under /opt/satlink/dsl |
| Firmware | Built by the separate stellar-fw repository on top of the official ADI plutosdr-fw v0.39: kernel, device tree, root filesystem with satlinkd, and the SatLink bitstream |
See Bench Architecture for how the parts talk to each other.
What SatLink is not (yet)#
SatLink is a working bench, not a finished product. A few things matter before you plan work on it:
- Some profile fields are descriptive only. A profile can declare an interleaver, a line encoding, duty-cycle limits or a bus interface; nothing in the modem acts on them. The RF Profiles page lists which fields reach the hardware.
- Several modulations are refused. OQPSK, MSK, π/4-DQPSK, FSK and GFSK exist in the schema but the fabric has no path for them, so a profile asking for them is rejected at apply.
- The symbol rate is a fixed ladder, from 19 531.25 to 2 500 000 baud. A 9600-baud spacecraft link cannot be matched without an FPGA change.
- Timestamps count from boot. The board has no real-time clock.
- Some boots are bad. A fraction of boots fail in the first DMA transfer after a PL reset. Verify the PL loopback byte for byte before trusting a measurement.
The full list is in Known Limitations.
Where to start#
- Hardware Setup: the boards, the SD card, how to reach the board and how to cable the RF path.
- Quick Start: install the CLI, check the board, run a PL loopback and a scenario.
- Glossary: the vocabulary used throughout this documentation.
- RF Fundamentals: sample rates, symbol rates, the LO and NCO, gains and levels.