__ _ __ _ __ __ ______ _______ ___
/ / (_) /____ | |/_/___/ |/ /_ |/ __/ _ \/ _ \
/ /__/ / __/ -_)> </___/ /|_/ / __/_\ \/ // / , _/
/____/_/\__/\__/_/|_| /_/ /_/____/___/____/_/|_|
LiteX based M2 SDR FPGA board.
Copyright (c) 2024-2026 Enjoy-Digital.
- What? LiteXβbased M.2 2280 SDR board featuring a Xilinx Artixβ7 XC7A200T FPGA and an ADI AD9361 RFIC.
- Why? Openβsource gateware/software, up to 61.44 MSPS (122.88 MSPSβ ) over PCIe Gen2 Γ4, hackβfriendly clocking & debug.
- Who? SDR tinkerers, FPGA devs, timeβsync enthusiasts, or anyone hitting the limits of other SDRs.
- How fast?
apt install β¦β./build.pyβ stream/record IQ in β5 min with our C API/tools or any SoapySDR compatible software.
- Docs:
litex_m2sdr/doc/libm2sdr/README.md - Examples:
litex_m2sdr/doc/libm2sdr/example_sync_rx.c,litex_m2sdr/doc/libm2sdr/example_sync_tx.c - Install metadata:
litex_m2sdr/software/user/libm2sdr/m2sdr.pc - Current public library version:
1.0.0(ABI1) - Recent API additions: backend accessors
m2sdr_get_transport()/m2sdr_get_eb_handle()and finer-grainedparse/range/stateerror classes.
β Oversampling needs PCIe Gen2 Γ2/Γ4 bandwidth.
We know what you'll first ask when discovering this new SDR project: what's the RFIC? π€ Let's answer straight away: Another AD936X-based SDR! π
Why yet another SDR based on this RFIC? Because we've been designing FPGA-based projects for clients with this chip for almost 10 years now and still think this RFIC has incredible capabilities and possibilities that haven't been fully tapped by open-source projects. We believe it can provide a fantastic and simple solution when paired with the LiteX framework we're developing. π
Imagine a minimalist AD9361-based SDR with:
- A compact form factor (M2 2280). π
- Minimal on-board RF frontend that could be specialized externally.
- 2T2R / 12-bit @ 61.44MSPS (and 2T2R / 12-bit @ 122.88MSPS for those wanting to use/explore Cellwizard/BladeRF findings).
- PCIe Gen 2 X4 (~14Gbps of TX/RX bandwidth) with LitePCIe, providing MMAP and several possible DMAs (for direct I/Q samples transfer or processed I/Q samples). β‘
- A large XC7A200T FPGA where the base infrastructure only uses a fraction of the available resources, allowing you to integrate large RF processing blocks. πͺ
- The option to reuse some of the PCIe lanes of the M2 connector for 1Gbps or 2.5Gbps Ethernet through LiteEth. π
- Or ... for SATA through LiteSATA. πΎ
- Or ... for inter-board SerDes-based communication through LiteICLink. π
- Powerful debug capabilities through LiteX Host <-> FPGA bridges and LiteScope logic analyzer. π οΈ
- Multiboot support to allow secure remote update over PCIe (or Ethernet).
- ...and we hope a welcoming/friendly community as we strive to encourage in LiteX! π€
OK, you probably also realized this project is a showcase for LiteX capabilities, haha. π Rest assured, we'll do our best to gather and implement your requests to make this SDR as flexible and versatile as possible!
This board is proudly developed in France π«π· by Enjoy-Digital, managing the project and litex_m2sdr/gateware/software development, and our partner Lambdaconcept designing the hardware. π₯π·
Ideal for SDR enthusiasts, this versatile board fits directly into an M2 slot or can team up with others in a PCIe M2 carrier for more complex projects, including coherent MIMO SDRs. π§
For Ethernet support with 1000BaseX/2500BaseX and SATA connectivity to directly record/play samples to/from an SSD, mount it on the LiteX Acorn Mini Baseboard! π½
Unlock new possibilities in your SDR projects with this cutting-edge boardβwe'll try our best to meet your needs! π
- Hardware Availability
- Capabilities Overview
- M.2 / GPIO Voltage Levels
- PCIe SoC Design
- Ethernet SoC Design (WIP)
- Quick Start
- Contact
The LiteX-M2SDR board is now fully commercialized and available for purchase from our webshop: Enjoy-Digital Shop.
The hardware has been thoroughly tested with several SDR softwares compatible with SoapySDR as well as with our Bare metal C utilities.
We offer two variants:
- SI5351C Variant β Uses the SI5351C clock generator with flexible clocking (local XO or external 10MHz via FPGA/uFL). Recommended for general usage. More details
- SI5351B Variant β Uses the SI5351B clock generator, clocked from the local XO with FPGA-controlled VCXO for software-regulated loops. More details
Note: The differences between the variants are relevant only for specific use cases. The SI5351B variant is mostly intended for advanced users with specialized clock control requirements.
| Feature | Mounted in M.2 Slot | Mounted in Baseboard | Parameter(s) to Enable |
|---|---|---|---|
| SDR Functionality | |||
| SDR TX (AD9361) | β | β | (always included) |
| SDR RX (AD9361) | β | β | (always included) |
| Oversampling (122.88MSPS) | β (PCIe Gen2 x2/x4 only) | β | `--with-pcie --pcie-lanes=2 |
| C API + Utilities | β | β | (included in software build) |
| SoapySDR Support | β | β | (via optional SoapySDR driver) |
| Connectivity | |||
| PCIe (up to Gen2 x4) | β | β (x1 only) | `--with-pcie --pcie-lanes=1 |
| Ethernet (1G/2.5G) | β | β | --with-eth |
| ββ Ethernet RX (LiteEth) | β | β | (included with --with-eth) |
| ββ Ethernet TX (LiteEth) | β | (included with --with-eth) |
|
| Timing & Sync | |||
| PTM (Precision Time Measurement) | β (PCIe Gen2 x1 only) | β (PCIe Gen2 x1 only) | --with-pcie --pcie-lanes=1 --with-pcie-ptm |
| White Rabbit Support | β | β | --with-white-rabbit |
| External Clocking | β (SI5351C: ext. 10MHz) | β (SI5351C: ext. 10MHz) | (SI5351B VCXO mode in dev for PTM regulation) |
| Storage | |||
| SATA | β | --with-sata |
|
| System Features | |||
| Multiboot / Remote Update | β | β | (always included) |
| GPIO | β | β | (always included) |
The board exposes a single monochrome user_led, so the gateware uses it as a layered status indicator rather than a simple on/off flag:
- Not ready yet: double-heartbeat while time is still invalid or while an enabled PCIe/Ethernet transport is not ready. PCIe becomes ready when the link is up and DMA/PPS synchronization is established; Ethernet becomes ready when the link is up.
- Idle / ready state: gentle low-amplitude breathing.
- PPS event: short bright accent pulse over the base animation.
- RF or Ethernet RX/TX activity: bright accent pulse.
When PCIe is not enabled in the build, the PCIe-specific states are naturally skipped and the LED falls back to the generic timing/activity behavior.
LiteX-M2SDR does not use a single M.2 I/O voltage:
- FPGA banks 13/14/15/16 on the SDR are powered at 3.3V.
- FPGA banks 34/35 on the SDR are powered at 1.8V.
- The general-purpose sideband signals routed directly from the M.2 connector to the FPGA on LiteX-M2SDR (
PPS,Synchro_GPIO,PERST#, optionalPEWAKE#,SUSCLK,PEDET) sit on 3.3V FPGA banks on the SDR side. - The M.2
SMB_CLK/SMB_DATApins are a special case: on LiteX-M2SDR r02 they reach the FPGA bank-16 pins through optional resistorsR82/R83, which are not mounted by default. - PCIe lanes and the PCIe reference clock are transceiver signals, not single-ended 1.8V/3.3V GPIOs.
Additional notes:
- M.2 pin 44 (
ALERT#/SMB_ALERT#) is currently not routed to the FPGA on LiteX-M2SDR r02. - M.2 pin 52 (
CLKREQ#) is pulled up to3V3_PCIeand is not routed to the FPGA. - M.2 pin 10 (
LED#) is not connected on the FPGA side. - The dedicated FPGA JTAG/config pins and the Acorn JTAG header are separate 3.3V JTAG paths.
- When discussing M.2 sideband voltages, distinguish the FPGA bank voltage on the SDR from the connector-side voltage expected by a host/baseboard. For example, the Acorn baseboard implements the M.2 SMBus pins as a 1.8V SMBus domain with translation to 3.3V for the SFP modules.
| Signal | Connector Location | FPGA Pin | Bank | Voltage On SDR Side | Notes |
|---|---|---|---|---|---|
GPIO0 |
TP1 |
E22 |
16 | 3.3V | General-purpose test point (FPGA_GPIO0). |
GPIO1 |
TP2 |
D22 |
16 | 3.3V | General-purpose test point (FPGA_GPIO1). |
PPS_IN |
M.2 pin 22 (NC22) |
K18 |
15 | 3.3V | Routed to the FPGA. |
PPS_OUT |
M.2 pin 24 (NC24) |
Y18 |
14 | 3.3V | Routed to the FPGA. |
Synchro_GPIO1 |
M.2 pin 28 (NC28) |
A19 |
16 | 3.3V | Routed to the FPGA. |
Synchro_GPIO2 |
M.2 pin 30 (NC30) |
A18 |
16 | 3.3V | Routed to the FPGA. |
Synchro_GPIO3 |
M.2 pin 32 (NC32) |
A21 |
16 | 3.3V | Routed to the FPGA. |
Synchro_GPIO4 |
M.2 pin 34 (NC34) |
A20 |
16 | 3.3V | Routed to the FPGA. |
Synchro_GPIO5 |
M.2 pin 36 (NC36) |
B20 |
16 | 3.3V | Routed to the FPGA. |
SMB_CLK |
M.2 pin 40 | A13 |
16 | 3.3V FPGA bank on SDR | Optional path through R82, not mounted by default; connector-level SMBus compatibility depends on the host/baseboard. |
SMB_DATA |
M.2 pin 42 | A14 |
16 | 3.3V FPGA bank on SDR | Optional path through R83, not mounted by default; connector-level SMBus compatibility depends on the host/baseboard. |
ALERT# / SMB_ALERT# |
M.2 pin 44 | - | - | Host-defined sideband | Not routed to the FPGA on LiteX-M2SDR r02. |
PERST# |
M.2 pin 50 | A15 |
16 | 3.3V | Routed to the FPGA. |
CLKREQ# |
M.2 pin 52 | - | - | 3.3V | Pulled up to 3V3_PCIe with R59; not routed to the FPGA. |
PEWAKE# |
M.2 pin 54 | B16 |
16 | 3.3V | Optional path through R88, not mounted by default. |
SUSCLK |
M.2 pin 68 | B17 |
16 | 3.3V | Routed through R84 (0R). |
PEDET / PRESENT |
M.2 pin 69 | A16 |
16 | 3.3V | Routed through R85 (0R). |
LED# |
M.2 pin 10 | - | - | Host-defined sideband | Not connected on LiteX-M2SDR. |
The PCIe design is the first variant developed for the board and does not require an additional baseboard. Just pop the M2SDR into a PCIe M2 slot, connect your antennas, and you're ready to go! π
The SoC has the following architecture:
- The SoC is built with the LiteX framework, allowing highly efficient HDL coding and integration. π‘
- You'll also find that most of the complexity is managed by LiteX and LitePCIe. The SoC itself only has an MMAP interface, DMA interface, and integrates the specific SDR/RFIC cores and features. βοΈ
- It provides debugging over PCIe or JTAG for MMAP peek & poke or LiteScope. π οΈ
- LitePCIe and its Linux driver (sorry, we only provide Linux support for now π ) have been battle-tested on several commercial projects. π
The PCIe design has already been validated at the maximum AD9361 specified sample rate: 2T2R @ 61.44MSPS (and also seems to correctly handle the oversampling at 2T2R @ 122.88MSPS with 7.9 Gbps of bandwidth on the PCIe bus; this oversampling feature is already in place and more tests/experiments will be done with it in the future).
Warning
WiP π§ͺ Still in the lab, RX only for now!
The Ethernet design variant gives flexibility when deploying the SDR. The PCIe connector has 4 SerDes transceivers that are in most cases used for... PCIe :) But these are 4 classical GTP transceivers of the Artix7 FPGA that are connected to the PCIe hardened PHY in the case of a PCIe application but can be used for any other SerDes-based protocol: Ethernet 1000BaseX/2500BaseX, SATA, etc...
In this design, the PCIe core will then be replaced with LiteEth, providing the 1000BaseX or 2500BaseX PHY but also the UDP/IP hardware stack + Streaming/Etherbone front-end cores.
The Ethernet SoC design is RX capable only for now. TX support will come soon.
If you are an SDR enthusiast looking to get started with the LiteX-M2SDR board, follow these simple steps to get up and running quickly:
-
Install Prerequisite Packages:
- On a fresh Ubuntu system, install the required development and SDR packages to ensure compatibility with the LiteX-M2SDR software:
sudo apt install build-essential cmake git \ pkg-config libsdl2-dev libgl1-mesa-dev \ libsoapysdr-dev soapysdr-tools libsoapysdr0.8 \ gnuradio gnuradio-dev libgnuradio-soapy3.10.9t64 gqrx-sdr \ libsndfile1-dev libsamplerate0-dev
- Note: For non-Ubuntu Linux distributions (e.g., Fedora, Arch), install the equivalent packages using your distribution's package manager (e.g.,
dnffor Fedora orpacmanfor Arch).
-
Connect the Board:
- Insert the LiteX-M2SDR board into an available M2 slot on your Linux computer and connect your antennas.
Warning
If an error related to DKMS appears during installation, run sudo apt remove --purge xtrx-dkms dkms and then re-execute the installation command.
-
Clone the Repository:
- Clone the LiteX-M2SDR repository using the following command:
git clone https://github.com/enjoy-digital/litex_m2sdr -
Build Software: Software build uses
makeand CMake for the C kernel driver and utilities, but since we also like Python π , we created a small script on top of it to simplify development and installation:cd litex_m2sdr/software ./build.py- This builds the kernel driver, the user-space utilities,
libm2sdr, and the SoapySDR driver. - If you also want the optional SDL/OpenGL GUI tools (
m2sdr_check/m2sdr_scan), first populate the pinnedcimguicheckout with:
cd litex_m2sdr/software ./fetch_cimgui.py- Or in a single step:
cd litex_m2sdr/software ./build.py --fetch-cimgui- By default,
./build.pybuilds incrementally and does not install when run as a normal user. - Use
./build.py --cleanwhen you want a full rebuild. - Use
sudo ./build.pywhen you also want to install the kernel driver, the user-space utilities /libm2sdr, and the SoapySDR module under the default prefix. - Example install command with the optional GUI fetch step:
cd litex_m2sdr/software sudo ./build.py --fetch-cimguim2sdr_checkandm2sdr_scanare optional SDL/OpenGL GUI tools. They are built only when SDL2/OpenGL development packages are installed andlitex_m2sdr/software/user/cimgui/has been populated. Ifcimguiis absent, only those two GUI tools are skipped; the CLI tools,libm2sdr, and the SoapySDR module still build normally.
- This builds the kernel driver, the user-space utilities,
-
Install the Built Software:
- Install the kernel driver:
cd litex_m2sdr/software/kernel sudo make install sudo insmod m2sdr.ko # Optional if you do not want to reboot yet.- Install the public C API headers/library for external applications:
cd litex_m2sdr/software/user make sudo make install_dev PREFIX=/usr/local sudo ldconfig- Install the SoapySDR module:
cd litex_m2sdr/software/soapysdr/build sudo make install- If you already used
sudo ./build.py, the kernel and SoapySDR install steps above are already done.libm2sdrstill needssudo make install_dev ...if you want to develop external applications against the public C API. - π Ready for launch!
-
Run Your SDR Software:
- Now, you can launch your preferred SDR software (like GQRX or GNU Radio) and select the LiteX-M2SDR board through SoapySDR. π‘
- IOMMU / DMA: For PCIe streaming, set IOMMU to passthrough mode. If you don't see I/Q data streams in your SDR app, this is the first thing to check.
- PCIe Gen & Lanes: Oversampling (122.88 MSPS) requires PCIe Gen2 x2/x4 bandwidth. Gen2 x1 is enough for standard 61.44 MSPS.
- Ethernet VRT (optional RX path): Build with
--with-eth --with-eth-vrtto enable an Ethernet RX VRT UDP streamer in hardware. A simple host receiver utility is available atlitex_m2sdr/software/user/m2sdr_vrt_rx.py. - Ethernet / SATA (WIP): Ethernet SoC is RX-only for now; TX support is in development. SATA support is in development. Both require the LiteX Acorn Baseboard Mini.
Tip
If you don't see I/Q data streams in your SDR app, make sure IOMMU is set to passthrough mode. Add the following to your GRUB configuration:
x86/PC:
# Add to GRUB config (/etc/default/grub):
GRUB_CMDLINE_LINUX="iommu=pt"
sudo update-grub && sudo rebootARM (ex NVIDIA Jetson/Orin):
# Add to extlinux.conf (/boot/extlinux/extlinux.conf):
APPEND ... iommu.passthrough=1 arm-smmu.disable=1
sudo rebootWarning
For intel CPU: if a kernel panic occurs with the message Corrupted page table at address,
add intel_iommu=off to GRUB_CMDLINE_LINUX. (This has been observed on
an 11th Gen Intel(R) Core(TM) i7-11700B @ 3.20GHz)
Warning
WiP π§ͺ Content below is more our memo as developers than anything useful to read π . This will be reworked/integrated differently soon.
For some platforms we created detailed tutorials. For everything else, please follow the earlier Getting Started tutorial.
For those who want to dive deeper into development with the LiteX-M2SDR board, follow these additional steps after completing the SDR enthusiast steps:
-
Test Structure (CI-safe vs hardware scripts):
- Gateware simulation/unit tests live in
test/and are CI-safe (no hardware needed):
pytest -v test- Board control/debug scripts live in
scripts/and require a running board/server:
python3 scripts/test_xadc.py python3 scripts/test_dashboard.py- CI runs both software build checks and simulation tests with:
# Software build checks (kernel/user/SoapySDR) are run in CI. python3 -m pytest -v test - Gateware simulation/unit tests live in
-
Run Software Tests:
- Test the kernel:
cd litex_m2sdr/software/kernel make clean all sudo make install sudo insmod m2sdr.ko (To avoid having to reboot the machine)- Test the user-space utilities:
cd litex_m2sdr/software/user make clean all ./m2sdr_util info ./m2sdr_rf --sample-rate=30720000 --tx-freq=2400000000 --rx-freq=2400000000 ./m2sdr_gen --sample-rate 30720000 --signal tone --tone-freq 1000000 --amplitude 0.5- C API (libm2sdr) quick start and examples:
See litex_m2sdr/doc/libm2sdr/README.md cd litex_m2sdr/software/user make examples ../../doc/libm2sdr/example_sync_rx > /tmp/rx.iq ../../doc/libm2sdr/example_tone_txlibm2sdris the common host interface used by the user utilities and the SoapySDR module, so example code there is the reference starting point for new host applications.
-
SoapySDR Detection/Probe:
- Detect the LiteX-M2SDR board:
SoapySDRUtil --probe="driver=LiteXM2SDR" -
Run GNU Radio FM Test:
- Open and run the GNU Radio FM test:
gnuradio-companion litex_m2sdr/software/gnuradio/test_fm_rx.grc -
Enable Debugging in Kernel:
- Enable debugging:
sudo sh -c "echo 'module m2sdr +p' > /sys/kernel/debug/dynamic_debug/control"
For those who want to explore the full potential of the LiteX-M2SDR board, including FPGA development, follow these additional steps after completing the software developer steps:
-
Install LiteX:
- Follow the installation instructions from the LiteX Wiki: LiteX Installation. π
-
Ethernet and PCIe Tests:
- For Ethernet tests, if the board is mounted in an Acorn Mini Baseboard:
./litex_m2sdr.py --with-eth --eth-sfp=0 --build --load ping 192.168.1.50- For PCIe tests, if the board is mounted directly in an M2 slot:
./litex_m2sdr.py --with-pcie --variant=m2 --build --load lspci- For PCIe tests, if the board is mounted directly in a LiteX Acorn Baseboard:
./litex_m2sdr.py --with-pcie --variant=baseboard --build --load lspci -
White Rabbit (Baseboard):
- White Rabbit is supported on the baseboard variant only:
./litex_m2sdr.py --with-pcie --with-white-rabbit --variant=baseboard --build--wr-sfpis optional; when omitted, the first availablesfpindex is auto-selected.- Firmware path lookup order:
--wr-firmware--wr-nic-dirLITEX_WR_NIC_DIR- auto-discovery of
../litex_wr_nicand../../litex_wr_nic
- If a stale local
wr-cores/checkout is detected, refresh it:
mv wr-cores wr-cores.old ./litex_m2sdr.py --with-pcie --with-white-rabbit --variant=baseboard --build -
Use JTAGBone/PCIeBone:
- Start the LiteX server for JTAG or PCIe:
litex_server --jtag --jtag-config=openocd_xc7_ft2232.cfg # JTAGBone sudo litex_server --pcie --pcie-bar=04:00.0 # PCIeBone (Adapt bar) -
Flash the Board Over PCIe:
- Flash the board:
cd litex_m2sdr/software ./flash.py ../build/litex_m2sdr_platform/litex_m2sdr/gateware/litex_m2sdr_platform.bin -
Reboot or Rescan PCIe Bus:
- Rescan the PCIe bus:
echo 1 | sudo tee /sys/bus/pci/devices/0000\:0X\:00.0/remove # Replace X with actual value echo 1 | sudo tee /sys/bus/pci/rescan
Got a unique idea or need a tweak? Whether it's custom FPGA/software development or hardware adjustments (like adapter boards) for your LiteX M2 SDR, we're here to help! Feel free to drop us a line or visit our website. We'd love to hear from you!
E-mail: florent@enjoy-digital.fr Website: http://enjoy-digital.fr/





