Skip to the content
PCBKitNew board
2 layers33 × 33 mmFilter Board, the printed circuit board in 3D

This is a direct down conversion (DDC) HF transceiver & VNA using the Raspberry Pi Pico and the iCE40UP5K.

Size
33 × 33 mm
Copper layers
2
Thickness
1.6 mm
Parts
20
Nets
9
Pads
62
Tracks, vias
1, 0
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
15 Jul 2026
Updated
6 Nov 2026

Overview

Filter Board is an open-source printed circuit board by frohro, from the frohro/pico-dev-ice repository on GitHub. It is a 2-layer board of 33 × 33 mm with 20 parts on 9 nets, routed with 1 track and 0 vias.

Its parts include 4 capacitors, 3 connectors, 3 inductors and 1 resistor. It belongs with the radio and wireless boards of this library.

README

README.md

The Pico Dev-iCE 📡

DSP Educational Vehicle & iCE40 Mixed-Signal Laboratory

📌 Overview

The Pico Dev-iCE is a low-cost, high-performance "Lab-in-a-Box." It combines the high-speed programmable logic of a Lattice iCE40UP5K FPGA with the flexible C/MicroPython ecosystem of a Raspberry Pi Pico (YD-RP2040 with 16MB Flash).

Designed specifically as an educational platform, it abandons "black box" RF chips in favor of discrete, observable analog blocks. Students can physically probe the RF signal path, design their own LC filters on pluggable sandboxes, and write Verilog to perform Direct Digital Conversion (DDC), digital decimation, and hardware I2S audio routing.

Here is a video of the SDR receiving on 20 meters..

🚀 Key Capabilities

  • HF Software Defined Radio (RX/TX): Full-duplex DDC/DUC transceiver covering 0 - 15.36 MHz (1st Nyquist) with Super-Nyquist capabilities up to 30+ MHz.
  • Vector Network Analyzer (VNA): Built-in Return Loss Bridge (RLB) for S11 (reflection) antenna tuning, and Port-to-Port S21 (transmission) filter characterization.
  • Arbitrary Waveform Generator (AWG): Dedicated DC-coupled and AC-coupled SMA outputs for 30 MSPS generic signal generation.
  • Real-Time Spectrum Analyzer: Visualize the entire 15 MHz HF spectrum simultaneously via FPGA-accelerated FFTs.
  • Standalone Operation: Onboard Audio DAC/Headphone amp and rotary encoder support allows the board to operate as a standalone radio without a PC.

🧠 Hardware Architecture

Processing Core

  • Microcontroller: YD-RP2040 / Pico 2 socket. Handles AGC math, user interface, USB communications, and slow-state hardware toggles. The massive internal Flash (up to 16MB) stores the FPGA bitstream and programs the FPGA directly on every boot, eliminating the need for an external FPGA flash chip.
  • FPGA: Lattice iCE40UP5K (SG48). Handles high-speed 30.72 MHz DSP, NCO generation, CIC decimation/interpolation, and I2S master clocking.
  • Control Bus: The Pico uses its high-speed SPI0 bus to dual-role: it blasts the bitstream into the FPGA's internal CRAM on boot, and then seamlessly transitions to sending runtime DSP commands to the user's Verilog over the exact same 4 wires.

Clocking & DSP Math

  • Master Clock: A clean 30.720 MHz CMOS oscillator drives the FPGA.
  • The Magic of 30.72 MHz: The FPGA decimates the 30.72 MSPS ADC data by exactly $R=640$ to yield a mathematically perfect 48.000 kHz baseband I/Q audio stream over I2S to the Pico.
  • Process Gain: The 640x decimation provides ~ 28 dB of digital processing gain, turning the raw 8-bit ADC into a highly sensitive 12.6-bit effective receiver!

The Receive (RX) Path

  • Topology: SMA ➔ Ethernet Isolation/CMC ➔ Band Sandbox ➔ T/R Switch ➔ LNA 1 ➔ PGA (5/10dB) ➔ LNA 2 ➔ ADC.
  • Amplifiers: Uses discrete high-speed op-amps wired as AC-coupled inverting amplifiers.
  • Programmable Gain: A Digital Step Attenuator (DSA) built from CMOS switches and precision T-networks, providing 0 to 55 dB of gain control in 5 dB steps. LNA 1 and LNA 2 are both bypassable to prevent clipping on massive signals.
  • ADC (MS9280): 8-bit, 32 MSPS. Driven by an RF balun into True Differential Mode with a 4.5V analog supply, yielding a massive 4.0V peak-to-peak input span for maximum dynamic range.

The Transmit (TX) Path

  • Topology: DAC ➔ Passive I-V ➔ Ethernet Transformer ➔ TX Switch ➔ Recon Sandbox ➔ TX Op-Amp (+12dB) ➔ T/R Switch ➔ SMA.
  • DAC (MS9708): 8-bit, 32 MSPS Current-Steering DAC.
  • Passive 50Ω resistors and an Ethernet transformer gracefully map the DAC's strict output compliance limits into a clean 1.0V p-p RF signal, which is then amplified to drive a 50-ohm antenna.

Power Domains (Strict Isolation)

To achieve commercial-grade noise floors, the noisy Switch-Mode Power Supply (SMPS) of standard Picos is bypassed/isolated.

  • +4.5V AVDD: Clean LDO powering the RF op-amps, analog switches, and ADC/DAC analog cores.
  • +3.3V Digital: LDO powering the FPGA I/O, Pico, and IC logic.
  • +3.3V Clean: Ferrite bead + LC filtered rail strictly for the 30.72 MHz oscillator to eliminate phase-noise/jitter.

🎛️ Port & Jumper Reference

Coaxial Connectors

  1. SDR_ANT(BNC): Main Transceiver Port (Transformer isolated, AC-Coupled).
  2. SII (SMA): Device Under Test port for S11/VSWR Antenna measurements. Connects to the internal Return Loss Bridge.
  3. AWG_OUT (BNC): Direct DC-coupled output (0V to +4V) from the DAC. Perfect for baseband signal generation.
  4. S21 (SMA): AC-coupled output for S21 Filter sweeps and RF signal generation. Protects the op-amp from DC-shorted filters.

Filter Sandboxes (Plug-and-Play)

The board features IN-GND-GND-OUT 0.1" sockets for inserting custom filter daughterboards.

  • Band Sandbox: Shared by both RX and TX (pre-T/R switch). Students calculate and test bandpass filters here.
  • TX Pre-Sandbox: Placed before the TX amplifier. Used for mild Nyquist reconstruction filters or super-Nyquist image-selection filters.

🛠️ Software & HDL Notes

  • Level Shifters (Logic Inversion): The 4.5V analog switches are controlled by 3.3V GPIOs via 2N7002 N-Channel MOSFETs. Note: This results in a logic inversion. Writing 0 to the pin in MicroPython = Switch HIGH (Max Gain / Default Path). Writing 1 = Switch LOW (Attenuated / VNA / TX Path).
  • FPGA Boot & SPI0 Bus:
    • The external FPGA Flash chip was removed to simplify the architecture. The Pico boots the FPGA directly by blasting the bitstream into CRAM using its Hardware SPI0 block.
    • Because the Pico drives the bus, the net names match the Pico's hardware roles: SPI0_TX (MOSI) is data entering the FPGA, and SPI0_RX (MISO) is data leaving the FPGA.
    • Runtime: Once booted, the Pico reuses the exact same SPI0 bus and ICE_SSN Chip Select pin to send DSP commands to the user's Verilog.
  • ADC OTR: The MS9280 "Out of Range" (Clipping) pin pulses for only 32ns. The FPGA catches this, stretches the pulse, and triggers a hardware interrupt on the Pico to engage the AGC.

The ten-week, verification-first HDL course sequence is documented in DDC_SDR_Lab_Plan.md.


📍 Hardware Pinout Reference

1. Microcontroller (Raspberry Pi Pico) Pinout

This map defines the interface for the software team handling AGC, VNA sweeps, user interface, and I2S audio routing.

Pico GPIONet NameFunctionDirectionNotes
GPIO 0FPGA_INTFPGA Hardware InterruptInputCatches stretched ADC Out-Of-Range (OTR) pulses
GPIO 1PMOD_3PMOD / GPIO JumpI/OConnected via series resistor R32 to PMOD_3
GPIO 2SDAI2C DataIn/OutI2C bus for the OLED Display
GPIO 3SCLI2C ClockOutputI2C bus for the OLED Display
GPIO 4SPI0_RXSPI0 MISOInputData entering Pico from FPGA (via series resistor R33)
GPIO 5ICE_SSNSPI0 CSn (FPGA CS)OutputHardware SPI0 Chip Select (Boot & Runtime)
GPIO 6SPI0_CLKSPI0 SCKOutputSPI Clock for Boot and Runtime (via series resistor R34)
GPIO 7SPI0_TXSPI0 MOSIOutputData leaving Pico to FPGA (via series resistor R35)
GPIO 8PGA05 dB AttenuatorOutputLogic 1 = Attenuator Active (LOW at switch)
GPIO 9PGA110 dB AttenuatorOutputLogic 1 = Attenuator Active (LOW at switch)
GPIO 10PGA2LNA 2 BypassOutputLogic 1 = LNA Bypassed (LOW at switch)
GPIO 11PGA3LNA 1 BypassOutputLogic 1 = LNA Bypassed (LOW at switch)
GPIO 12BAND_SWBand Filter SandboxOutputToggles sandbox selection switch
GPIO 13TX_DATAI2S TX DataOutputFull-Duplex Baseband Audio TO the FPGA
GPIO 14RX_DATAI2S RX DataInputFull-Duplex Baseband Audio FROM the FPGA
GPIO 15BCKI2S Bit ClockInputClocks generated by FPGA (I2S Master)
GPIO 16WSI2S Word Select (L/R)InputClocks generated by FPGA (I2S Master)
GPIO 17AF_DAC_DATAAudio DAC DataOutputI2S out to standalone headphone amp
GPIO 18AF_DAC_MCLKAudio DAC MasterOutputI2S out to standalone headphone amp
GPIO 19AF_DAC_SCLKAudio DAC ClockOutputI2S out to standalone headphone amp
GPIO 20AF_DAC_LRCKAudio DAC L/ROutputI2S out to standalone headphone amp
GPIO 21ICE_DONEFPGA Boot StatusInputGoes HIGH when FPGA is running and lights White LED
GPIO 22~ICE_RSTFPGA ResetOutputPull LOW to hold FPGA in reset
GPIO 26REFFront-End RF MuxOutput0 = SDR RF Antenna RX, 1 = VNA Input
GPIO 27(Optional)PMOD / GPIO JumpI/OJumper JP3 maps to PMOD_2
GPIO 28~T/RTransmit/Receive SwOutput1 = RX Mode (Antenna -> LNA), 0 = TX Mode

2. FPGA (Lattice iCE40UP5K-SG48) Pinout

This map defines the interface for the digital design team writing Verilog and the .pcf constraints file.

Pin #Lattice NameNet NameFunction / Connection
37IOT_45a_G1CLK30.72 MHz Master Clock IN (From Oscillator)
23IOT_37aADC_CLKADC Clock OUT (To MS9280 via 22Ω resistor)
6IOB_13bDAC_CLKDAC Clock OUT (To MS9708)
25IOT_36bD0ADC Data Bit 0 (LSB)
26IOT_39aD1ADC Data Bit 1
27IOT_38bD2ADC Data Bit 2
28IOT_41aD3ADC Data Bit 3
31IOT_42bD4ADC Data Bit 4
32IOT_43aD5ADC Data Bit 5
34IOT_44bD6ADC Data Bit 6
35IOT_46b_G0D7ADC Data Bit 7 (MSB)
36IOT_48bOTRADC Out of Range (Clipping Flag)
4IOB_8aDB0DAC Data Bit 0 (LSB)
3IOB_9bDB1DAC Data Bit 1
2IOB_6aDB2DAC Data Bit 2
48IOB_4aDB3DAC Data Bit 3
47IOB_2aDB4DAC Data Bit 4
46IOB_0aDB5DAC Data Bit 5
45IOB_5bDB6DAC Data Bit 6
44IOB_3b_G6DB7DAC Data Bit 7 (MSB)
14IOB_32a_SPI_SOSPI0_RXSPI MISO (Data to Pico during runtime)
17IOB_33b_SPI_SISPI0_TXSPI MOSI (Data from Pico during runtime)
15IOB_34a_SPI_SCKSPI0_CLKSPI Clock IN (From Pico GPIO 6)
16IOB_35b_SPI_SSICE_SSNSPI Chip Select IN (From Pico GPIO 5)
12IOB_22aBCKI2S Bit Clock OUT (To Pico GPIO 15)
9IOB_16aWSI2S Word Select OUT (To Pico GPIO 16)
11IOB_20aRX_DATAI2S Data OUT (SDR audio to Pico GPIO 14)
10IOB_18aTX_DATAI2S Data IN (Transmit audio from Pico GPIO 13)
13IOB_24aFPGA_INTHardware Interrupt OUT (To Pico GPIO 0)
38IOT_50bANG_0Rotary Encoder / Tuning Knob A
42IOT_51aANG_1Rotary Encoder / Tuning Knob B
43IOT_49aANG_2Rotary Encoder / Tuning Knob Switch
21IOB_23bPMOD_0PMOD Header Pin 1
19IOB_29bPMOD_1PMOD Header Pin 2
18IOB_31bPMOD_2PMOD Header Pin 3
20IOB_25b_G3PMOD_3PMOD Header Pin 4
39RGB0REDOpen-Drain LED Driver (Active-Low: 0=ON, pulses on ADC OTR clipping)
40RGB1YELLOWOpen-Drain LED Driver (Active-Low: 0=ON, pulses on SPI tuning activity)
41RGB2GREENOpen-Drain LED Driver (Active-Low: 0=ON, steady ON when un-reset)
7CDONEICE_DONEHardware Boot / Status Out
8~CRESET~ICE_RSTHardware Boot / Reset In

Pico SDK Bring-Up

The SDK port is under Software/pico-ice-sdk. It uses the checked-in Pico SDK (currently 2.2.0). The general SDK examples use the TinyUSB revision bundled by that SDK. The DDC firmware below uses a newer TinyUSB checkout because it needs the UAC1 descriptor definitions that are not present in the bundled revision.

The smallest board-specific firmware example programs the FPGA's volatile CRAM directly from the RP2040:

sh
cmake -S Software/pico-ice-sdk/examples/rp2_dev_ice_blinky \
    -B Software/pico-ice-sdk/examples/rp2_dev_ice_blinky/build \
    -DPICO_BOARD=pico_dev_ice -DPICO_NO_PICOTOOL=1
cmake --build Software/pico-ice-sdk/examples/rp2_dev_ice_blinky/build

The generated UF2 is RP2040 firmware that contains the FPGA bitstream. The Dev-iCE has no external FPGA configuration flash, so the board port excludes the external-flash and TinyUF2 FPGA-storage paths. SPI0 GPIO 6 is the CRAM transfer clock and GPIO 7 carries configuration data; normal FPGA operation uses the separate external 30.720 MHz oscillator, not a Pico-generated clock on GPIO 27.

DDC SDR Firmware

The first Dev-iCE SDR application is in Software/ddc_sdr_firmware. It replaces the earlier Si5351a, Tayloe detector, and PCM1808 path with FPGA-generated DDC I/Q data received as PCM1808-compatible I2S. The Pico firmware:

  • programs the FPGA's volatile CRAM over SPI0;
  • reuses SPI0 for runtime frequency and sample-rate commands;
  • captures FPGA I2S with DMA; and
  • exposes stereo 24-bit UAC1 audio at 48 kHz and 96 kHz, CDC control, and a DFU interface.

The DDC application requires a TinyUSB checkout with both src/tusb.h and hw/bsp/rp2040. A current checkout at $HOME/tinyusb is detected automatically, or it can be selected explicitly:

sh
cmake -S Software/ddc_sdr_firmware -B Software/ddc_sdr_firmware/build \
        -DPICO_TINYUSB_PATH="$HOME/tinyusb" \
        -DPICO_BOARD=pico_dev_ice \
        -DPICO_NO_PICOTOOL=1
cmake --build Software/ddc_sdr_firmware/build -j2

The Pico firmware keeps FPGA deployment easy to choose: FPGA_BOOT_MODE=DFU waits for a development bitstream from dfu-util, while FPGA_BOOT_MODE=STORED loads an image embedded in the Pico firmware at boot. Two stored transceiver profiles can be included with FPGA_RX_BITSTREAM_BIN and FPGA_TX_BITSTREAM_BIN, with FPGA_DEFAULT_IMAGE selecting the boot profile and FPGA,LOAD,RX or FPGA,LOAD,TX selecting one between sessions. The full commands and build examples are in Software/ddc_sdr_firmware/README.md.

These profile loads are not a VNA sweep mechanism. A VNA needs a single coherent FPGA design containing the stimulus, reference, receive, and measurement paths for the complete sweep. Select a persistent VNA-capable image before a measurement, or implement those paths in one integrated image; do not reconfigure between sweep points.

For development, compile an FPGA bitstream with Yosys, nextpnr-ice40, and icepack, then load it without reflashing the Pico:

sh
python3 Software/ddc_sdr_firmware/tools/dfu_fpga.py /path/to/ddc_sdr.bin

Stop the SDR++ or Quisk audio stream before starting DFU. The helper prepares the shared SPI0 bus, sends the packed bitstream through dfu-util, and lets the Pico restore the runtime FPGA state afterward. Do not reset the Pico after a DFU-only update: FPGA CRAM is volatile and a reset clears the loaded design.

For the complete pinout, SPI protocol, CDC commands, build options, and DFU sequence, see Software/ddc_sdr_firmware/README.md.

Parts

20
QtyValueFootprintReferences
5Jumper_2_BridgedJumper:SolderJumper-2_P1.3mm_Bridged_RoundedPad1.0x1.5mmJP1, JP2, JP6, JP7, JP8
4C_Small_USJLC:Capacitor_multi_no_trimmerC6, C7, C8, C9
4Jumper_2_OpenJumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mmJP3, JP4, JP5, JP10
3L_Iron_SmallJLC:Inductor_MultiL1, L2, L3
150Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolderR1
1INConnector_Coaxial:SMA_Amphenol_132289_EdgeMountJ14
1OUTConnector_Coaxial:SMA_Amphenol_132289_EdgeMountJ15
1PCB ConnectorConnector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_HorizontalJ1

Questions

How big is the Filter Board PCB?

It measures 33 × 33 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Filter Board use?

20 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Filter Board KiCad files?

From the frohro/pico-dev-ice repository on GitHub, at the commit this page was made from: the board is Hardware/Filter_Board/_restore_backup_2026-07-28T20-06-10-139/Filter_Board.kicad_pcb and its schematic Hardware/AF_DAC.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Filter Board design in my own project?

Its repository states no licence, so its author keeps all rights: ask frohro before reusing the design.

More from frohro/pico-dev-ice

1
  • 4 layers100 × 100 mmPico Dev iCE, the printed circuit board in 3D

    Pico Dev iCE

    frohro/pico-dev-ice

    This is a direct down conversion (DDC) HF transceiver & VNA using the Raspberry Pi Pico and the iCE40UP5K.

    294 parts3

Similar boards

  • 2 layers66.9 × 74.5 mmDeskHop Rev1, the printed circuit board in 3D

    DeskHop Rev1

    hrvach/deskhop

    Fast Desktop Switching Device

    20 parts7.9kGPL-3.0
  • 2 layers86.4 × 64.8 mmSlot machine, the printed circuit board in 3D

    Slot machine

    google/google-ctf

    Google CTF

    20 parts5.1kApache-2.0
  • 2 layers36.2 × 26.8 mmEsp32 minimal, the printed circuit board in 3D

    Esp32 minimal

    atopile/atopile

    Design circuit boards with code! ✨ Get software-like design reuse 🚀, validation, version control and collaboration in hardware; starting with electronics ⚡️

    20 parts4kMIT
  • 2 layers108.1 × 393.8 mmSweep compact ble, the printed circuit board in 3D

    Sweep compact ble

    davidphilipbarr/Sweep

    Sweep - a small promicro based keyboard inspired by the Ferris.

    20 parts2.1k
  • 2 layers26 × 15.9 mmTPS54340 Buck Regulator, the printed circuit board in 3D

    TPS54340 Buck Regulator

    rusefi/rusefi

    rusefi - GPL internal combustion engine control unit

    20 parts1.2k
  • 2 layers67.6 × 30.5 mmRgb to hdmi, the printed circuit board in 3D

    Rgb to hdmi

    hoglet67/RGBtoHDMI

    Bare-metal Raspberry Pi project that provides pixel-perfect sampling of Retro Computer RGB/YUV video and conversion to HDMI

    20 parts1kGPL-3.0
  • 2 layers44.3 × 28.7 mmLin bus adapter esp32, the printed circuit board in 3D

    Lin bus adapter esp32

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    20 parts915
  • 2 layers89.5 × 61.6 mmFreeDeck TH 2020-02, the printed circuit board in 3D

    FreeDeck TH 2020-02

    FreeYourStream/freedeck-hardware

    all the stuff you need to build your own FreeDeck

    20 parts772