FPGA Capacitive Keyboard Synthesizer
An FPGA-Based Musical Instrument With Custom Capacitive Sensing and Digital Audio Synthesis
WHY — Motivation, Problem, and Constraints
Project Constraints
- Built on a Spartan-7 FPGA (limited BRAM + DSP slices)
- Real-time requirements: touch → audio latency must feel instantaneous
- Polyphony requires careful BRAM access arbitration and mixing
- Capacitive sensing is noisy and timing-sensitive
- No off-the-shelf IP cores; all RTL was hand-written
- 24–36 capacitive pads (depending on iteration)
- Clear division of labor required autonomy in subsystem design
WHAT — System Overview
A high-level architecture view:
Hardware System Components
Capacitive Interface
- 24 copper pads milled on a custom PCB
- 3× MPR121 ICs
- Address-configured to scale to 36+ pads
- Routed via PMOD cables to FPGA board
Custom I²C Controller (My Work)
A hand-written Finite State Machine implementing:
- Start / Stop conditions
- Clock stretching
- SDA bidirectional timing
- Addressing and register access
- ACK/NACK logic
- Read/write sequencing
- Bus arbitration
MPR121 Driver Module
Implements:
- Runtime configuration of thresholds
- Continuous electrode polling
- Combined 24-bit touch vector output
- Integration with interrupt-based updates
Digital Audio Path
Two sound-generation pipelines were implemented:
A. Procedural Synthesis (My lead)
- LUTs stored in BRAM
- DDS phase accumulator
- Sine / sawtooth / square waves
B. Oud Sample Playback (Adan's lead)
- Recorded and pitch-processed in Python (
librosa) - Resampled to 16 kHz
- Converted into BRAM
.memfiles - Up to ~8k samples per note
- 16-bit output resolution
ADSR (Adan's Module)
- FSMD structure
- Attack → Decay → Sustain → Release
- Smooth multiplier applied to waveform sample
- One ADSR per voice → enables polyphony
Polyphony Engine(Shared)
Supports 8 voices, each with:
- Independent phase accumulator
- Independent ADSR
- BRAM reading logic
- Normalized summation
PDM Output Encoder (My Work)
- Selected PDM over PWM for better audio quality
- Drives headphones or speakers with a simple RC filter
HOW — Engineering Decisions, Challenges, and Deep Technical Work
1. Custom I²C Implementation (My work)
Challenges
- Bidirectional SDA line requires careful enable/disable timing
- MPR121 requires specific reset timing and threshold registers
- Received values needed stable synchronizers to avoid metastability
- Correcting false positives due to noisy pads
- Handling multi-byte sequential reads
Key Engineering Work
- Designed a 9-state I²C FSM (“START”, “ADDR”, “ACK”, “WRITE”, “READ”, “STOP”, etc.)
- Implemented sampling of SDA on the rising edge of SCL and driving on the falling edge
- Added timeout behavior for bus lock-up
- Used Saleae logic analyzer to validate waveform timing
- Polled MPR121 electrode-status registers (0x00–0x01) and exposed a clean 24-bit vector
2. Note Decoder Logic (My Work)
Challenges
- Mapping 24 touch channels to musical notes
- Handling multi-pad activation gracefully
- Interfacing with voice allocator
Design Approach
Decision
I separated gesture detection (touch) from voice triggering (synthesis) so polyphony infrastructure remained modular.
3. DDS + Sample Playback Pipeline
Phase Accumulator
- 32-bit accumulator running at FPGA’s master clock
- Computed:
phase_increment = (frequency * 2^32) / Fs - High resolution → smooth pitch transitions
Waveform Address Generator
- Top bits of accumulator used as BRAM address
- Supported both LUT-based and sample-based paths
4. BRAM-Efficient Sample Storage
Challenge
- Spartan-7 BRAM is tight
- Realistic Oud notes require thousands of samples
Approach
- Preprocessing in Python:
- Trim silence
- Normalize
- Downsample to 16 kSps
- Convert to
.memfiles
- Designed BRAM layout: 4 BRAMs per note for ~8k samples
- Enabled instrument to sound authentic despite memory constraints
5. Polyphony Architecture & Mixing
Challenge
- Multiple voices → BRAM contention
- Summation → overflow risk
- Need per-voice ADSR channels
Design Choices
- Use parallel channels for primary voices
- Use TDM-like behavior for secondary voices
- Normalization via shift-based scaling avoids costly division
6. PDM Output
Why PDM
- Higher perceived audio fidelity than PWM on the same clock
- Easier analog filtering
- Produces clean signal for speakers/headphones
7. Physical Fabrication (My Work)
- Designed and milled the capacitive PCB
- Laser-cut enclosure inspired by Arabic geometries
- Integrated PCB pad shape into ergonomic layout
- Ensured low-noise grounding paths
Relevant Engineering Skills Demonstrated (Mapped to Formlabs Rubric)
✔ Autonomy
- Designed full capacitive subsystem alone
- Implemented I²C protocol from scratch
- Built ADSR, PDM, and major parts of DDS
- Performed full system integration & timing closure
✔ Challenge
- Real-time constraints
- BRAM budgeting
- Timing-sensitive I²C HDL implementation
- Polyphonic mixing without DSP overflow
- Debugging noisy capacitive signals
✔ Technical Depth
- FSM design for communication protocols
- Direct Digital Synthesis
- Audio sample processing and memory layout
- HDL for DACs (PWM/PDM)
- Multi-channel ADC-like sensing integration
- Polyphony architecture and scheduling
✔ Decision-Making
- Chose FPGA over MCU for deterministic timing & parallelism
- Chose PDM over PWM for fidelity
- Used sample playback where wavetable synthesis lacked richness
- Designed I²C FSM instead of vendor IP for transparency
- Mixed dedicated and TDM-based approaches for scalable polyphony