A Wishbone-peripheral VHDL Direct Digital Synthesis (DDS) signal generator with programmable Gaussian pulse envelopes and DRAG correction, designed for quantum control applications.
wb_sig_gen (Wishbone peripheral, ADDR_WIDTH=3)
├── sig_gen_csrs — 7 CSR registers + valid/ready trigger handshake
└── sig_gen
├── trig_ctrl — Pending trigger + inter-pulse delay counter + envelope accumulator
├── pha_acc — Phase accumulator (32-bit), resets on trigger
├── sine_cos_lut — Quarter-wave LUT + full-wave reconstruction (sin + cos)
├── env_gen — Gaussian envelope + DRAG correction (amplitude scaling)
└── iq_mod — IQ modulator: envelope × sine, DRAG cross-terms, output pipeline
| Address | Register | Description |
|---|---|---|
0x0 |
FTW | Frequency tuning word (32-bit) |
0x1 |
POW | Phase offset word (32-bit) |
0x2 |
AMP | Amplitude scalar (16-bit, unsigned) |
0x3 |
ENV | Envelope step (32-bit) |
0x4 |
DRAG | DRAG coefficient Q1.15 (16-bit) |
0x5 |
DELAY | Inter-pulse delay in clock cycles (24-bit) |
0x6 |
TRIG | Write bit-0 to trigger; readback {24'b0, 5'b0, ready, valid} |
Requires GHDL with VHDL-2008 support and Python 3 (for analysis/verification).
make run # compile + simulate (default: 100 kHz, 200-cycle pulse)
make verify # analyze envelope quality (6 checks)
make plot # analyze + generate waveform/spectrum PNGs
make clean # remove work/, output/, .import, .make
make distclean # also remove py/.venvmake run FREQ_HZ=1000000 PHASE_DEG=45 AMP_VAL=65535 PULSE_LEN=500 DRAG_COEFF=0.3 CLK_PERIODS=4| Variable | Default | Description |
|---|---|---|
FREQ_HZ |
100000 | Output sine frequency |
PHASE_DEG |
0 | Initial phase (degrees) |
AMP_VAL |
65535 | Written to AMP CSR register; scales Gaussian envelope amplitude |
PULSE_LEN |
200 | Envelope pulse length in clock cycles |
DRAG_COEFF |
0.5 | DRAG coefficient (real; make auto-converts to Q1.15 integer) |
CLK_PERIODS |
4 | Number of output periods to simulate |
OUT_RES_BITS |
12 | Sine LUT output resolution (bits), affects SNR |
CLK_FREQ_HZ |
100e6 | Python analysis only (make verify/make plot); VHDL sim uses 100 MHz |
The testbench (tbs/sig_gen_tb.vhd) performs two-phase testing:
- Phase 1: standard pulse — checks width, glitch-free edges, pre/post extinction.
- Phase 2: pending trigger — writes TRIG mid-pulse, verifies second pulse fires correctly after delay.
Verification (make verify) checks: extinction pre/post-pulse, single active region, pulse width, envelope symmetry, peak magnitude.
Both sine_lut_pkg.vhd and envelope_lut_pkg.vhd are generated by Python scripts.
cd py && makeOverride in py/Makefile: LUT_ADDR_BITS, OUT_RES_BITS, ENV_LUT_ADDR_BITS, ENV_OUT_RES_BITS, INITIAL_PHASE, FINAL_PHASE.
make verify and make plot auto-create a Python virtualenv at py/.venv (numpy, scipy, matplotlib) to fit sine waves and compute spectral metrics from simulation output samples.
| Path | Description |
|---|---|
work/ |
GHDL compilation output (deleted by make clean) |
output/sig_gen_tb.ghw |
Simulation waveforms |
output/test_*/samples.txt |
Raw I/Q samples per test phase |