A polyphase channelizer implementation in VHDL, designed for spectrum monitoring and digital communications applications.
This project implements a polyphase channelizer that splits a wideband input signal into multiple narrowband frequency channels. The design supports two configurations:
| Configuration | Channels | Sample Rate | Target | Application |
|---|---|---|---|---|
| MDT | 4 | 40 ksps | iCE40 UltraPlus | FunCube+ transponder monitoring |
| Haifuraiya | 64 | 10 Msps | ZCU102 | Opulent Voice FDMA |
A polyphase channelizer efficiently splits a wideband signal into N frequency channels using:
- Polyphase Filterbank - N parallel FIR filters, each processing every Nth sample
- FFT - Converts filtered outputs to frequency domain
This is computationally efficient compared to running N separate bandpass filters, and is widely used in software-defined radio, satellite communications, and spectrum analyzers.
┌─────────────────────────────────────────────┐
│ Polyphase Channelizer │
│ │
Wideband ───────►│ ┌────────-────┐ ┌─────┐ │
Input │ │ Polyphase │ │ │ Channel 0 ──►│
│ │ Filterbank │─────►│ FFT │ Channel 1 ──►│
│ │ (N branches)│ │ │ Channel 2 ──►│
│ └───────────-─┘ └─────┘ ... ──►│
│ │
└─────────────────────────────────────────────┘
Mode-Dynamic-Transponder/
├── README.md # This file
├── docs/ # Documentation and reference models
│ ├── polyphase_channelizer.ipynb # Python reference implementation
│ └── mdt_channelizer_summary.md # Design summary
├── rtl/ # Synthesizable VHDL
│ ├── README.md # RTL documentation
│ ├── pkg/ # Packages
│ │ └── channelizer_pkg.vhd
│ ├── channelizer/ # Core modules
│ │ ├── coeff_rom.vhd
│ │ ├── delay_line.vhd
│ │ ├── mac.vhd
│ │ ├── fir_branch.vhd
│ │ ├── polyphase_filterbank.vhd
│ │ ├── fft_4pt.vhd
│ │ ├── fft_64pt.vhd
│ │ └── polyphase_channelizer_top.vhd
│ └── coeffs/ # Filter coefficients
│ ├── mdt_coeffs.hex
│ └── haifuraiya_coeffs.hex
└── sim/ # Simulation
├── README.md # Testbench documentation
├── run_tests.tcl # Vivado TCL script
└── tb_*.vhd # Testbenches
- Vivado 2022.2 (for simulation and synthesis)
- Python 3.8+ with NumPy, SciPy, Matplotlib (for reference model)
# In Vivado TCL console:
cd /path/to/Mode-Dynamic-Transponder
source sim/run_tests.tcl
create_sim_project channelizer_sim
run_all_testsOr run a single testbench:
run_test tb_mac
run_test_gui tb_fir_branch # With waveform viewerThe filter coefficients are generated by the Python reference model:
cd docs
jupyter notebook polyphase_channelizer.ipynb
# Run all cells - generates rtl/coeffs/*.hex filespolyphase_channelizer_top
├── coeff_rom # Filter coefficients (Block RAM)
├── polyphase_filterbank # N parallel FIR branches
│ └── fir_branch (×N)
│ ├── delay_line # Sample history (shift register)
│ └── mac # Multiply-accumulate
└── fft_4pt / fft_64pt # Frequency separation
- Input samples arrive one at a time
- Samples are distributed round-robin to N filter branches
- Each branch filters with its portion of the prototype lowpass filter
- After N samples, all branch outputs feed the FFT
- FFT produces all N frequency channels simultaneously
The channelizer outputs all N channels at once - there's no channel selection at this stage. For Haifuraiya, all 64 channels are packetized into DVB-S2/X frames and transmitted. Receivers get everything and filter locally for the channels they want to monitor.
This "broadcast everything" model supports:
- Single operator listening to one channel
- Conference room with multiple operators on different channels
- Locus (satellite repeater/conference room server) managing multiple simultaneous conversations
| Resource | MDT (iCE40 UP) | Haifuraiya (ZCU102) |
|---|---|---|
| Flip-flops | ~1,500 | ~30,000 |
| LUTs | ~2,000 | ~15,000 |
| Multipliers | 4 | 64 |
| Block RAM | 1 | 8 |
The design is parameterized via channelizer_pkg.vhd:
-- Use pre-defined configuration
constant CFG : channelizer_config_t := MDT_CONFIG;
-- Or customize
constant CFG : channelizer_config_t := (
n_channels => 8,
taps_per_branch => 20,
data_width => 16,
coeff_width => 16,
accum_width => 38
);- rtl/README.md - Detailed RTL documentation, module descriptions, timing diagrams
- sim/README.md - Testbench descriptions, simulation setup, Vivado usage
- docs/polyphase_channelizer.ipynb - Python reference model with filter design, visualization, and coefficient export
- Python reference model with filter design
- Coefficient generation and export
- All RTL modules (coeff_rom, delay_line, mac, fir_branch, polyphase_filterbank, fft_4pt, fft_64pt, top)
- Testbenches for all modules
- Vivado simulation scripts
- Documentation
- Synthesize for iCE40 UltraPlus (MDT)
- Synthesize for ZCU102 (Haifuraiya)
- Hardware verification
- Integration with FunCube+ receiver
- Integration with Opulent Voice modem
- Opulent Voice Protocol - Digital voice protocol that will use this channelizer
- AMSAT-UK FunCube+
- ORI Haifuraiya
This is an Open Research Institute project. Contributions are welcome!
- Fork the repository!
- Create a feature branch!
- Submit a pull request!
- Have fun!
For questions or discussion, join the ORI community channels
This project is open source, using CERN OHL 2.0 and other OSI approved licenses
- Open Research Institute engineering team
- AMSAT-UK community for FunCube documentation, participation, and leadership
- Contributors to the Opulent Voice and Haifuraiya projects
Open Research Institute - Advancing open source digital radio for space and terrestrial use