
Module: tt_um_FG_TOP_Dominik_Brandstetter
A compact, programmable 8-bit function generator for TinyTapeout. It outputs either a constant DC level, a CORDIC-based sine, or a programmable trapezoid/pulse (riseβholdβfall). A tiny on-chip timer with prescaler drives sample timing. Configuration uses TinyTapeout GPIOs via a simple write-only register interface. The 8-bit output feeds an external DAC or resistor ladder.
Target DAC: Analog Devices AD5330 (parallel, 8-bit).
ENABLE=0.CR0..CR6 while halted.ENABLE=1 β it runs.
| Signal | Dir | W | Purpose |
|---|---|---|---|
ui_in[7:0] |
in | 8 | Register data bus (write-only) |
uo_out[7:0] |
out | 8 | DAC data (parallel 8-bit) |
uio_in[7] |
in | 1 | ENABLE: Low = halt, High = run |
uio_in[6] |
in | 1 | WR_n (active-low) β write selected register |
uio_in[5:3] |
in | 3 | ADDR[2:0] β select CR0..CR6 (0..6) |
uio_out[0] |
out | 1 | dac_clr_n β AD5330 /CLR |
uio_out[1] |
out | 1 | dac_pd_n β AD5330 power-down (high = enabled) |
uio_out[2] |
out | 1 | dac_wr_n β AD5330 /WR pulse on new sample |
clk |
in | 1 | System clock |
rst_n |
in | 1 | Async reset (active-low) |
ena |
in | 1 | Always 1 on TinyTapeout |
Write protocol: Assert WR_n=0 β₯ 3 clocks with ADDR & DATA stable to update the target register.
{CR0..CR6})| Bits | From | What it does |
|---|---|---|
| 55 | CR0 | Constant mode (1 = force DC = AMPLITUDE) |
| 54 | CR0 | Mod select (0 = Waveform, 1 = Sine) |
| 53..48 | CR0 | Prescaler (timer divider) |
| 47..40 | CR1 | Counter (sine: phase increment β’ waveform: period) |
| 39..32 | CR2 | Initial phase (sine) β’ ON duration (waveform) |
| 31..24 | CR3 | Rise step per tick (waveform) |
| 23..16 | CR4 | Fall step per tick (waveform) |
| 15..8 | CR5 | Amplitude (sine & waveform; DC level in Constant mode) |
| 7..0 | CR6 | Offset (added after selection) |
Reset defaults:
CR0=0x49, CR1=0x05, CR2=0x00, CR3=0x00, CR4=0x00, CR5=0x32, CR6=0x00.
0x49)[55] Constant mode 1 β output = AMPLITUDE (modulated path ignored)
[54] Mod select 0 β Waveform, 1 β CORDIC sine
[53:48] Prescaler 6-bit timer divider (timebase=100kHz @1MHz clock_i)
0x05)[47:40] Counter
β’ Sine: phase increment per sample (sets frequency)
β’ Waveform: period value for RISE/ON/FALL FSM
0x00)[39:32] Initial phase / ON time
β’ Sine: initial accumulator load
β’ Waveform: ON ticks (RISE+ON before FALL)
0x00)[31:24] k_rise step/tick during RISE (0 β AMPLITUDE slope)
0x00)[23:16] k_fall step/tick during FALL (AMPLITUDE β 0 slope)
0x32)[15:8] AMPLITUDE peak for sine & waveform; constant level in DC mode
0x00)[7:0] OFFSET signed (twoβs complement) post-add
β’ Overflow wraps (no saturation)
Sine (default)
CR0[55]=0, CR0[54]=1.Prescaler (CR0[53:48]), and with Counter (CR1).AMPLITUDE (CR5) + OFFSET (CR6).Constant (DC)
CR0[55]=1.AMPLITUDE (CR5) + OFFSET (CR6).Trapezoid / Pulse
CR0[55]=0, CR0[54]=0.k_rise (CR3), ON duration (CR2), k_fall (CR4).Prescaler (CR0) + Counter (CR1).AMPLITUDE (CR5) + OFFSET (CR6).uo_out[7:0] β AD5330 DB[7:0]uio_out[2] β /WRuio_out[1] β PD_n (high = enabled)uio_out[0] β /CLR (high in normal operation)AMPLITUDE + OFFSET must fit 8-bit (wraps otherwise).| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | DATA_IN_0 | DAC_OUT_0 | dac_clr_OUT (active low) |
| 1 | DATA_IN_1 | DAC_OUT_1 | dac_pd_OUT (active low) |
| 2 | DATA_IN_2 | DAC_OUT_2 | dac_wr_OUT (active low) |
| 3 | DATA_IN_3 | DAC_OUT_3 | CONFIG ADDR_0_IN |
| 4 | DATA_IN_4 | DAC_OUT_4 | CONFIG ADDR_1_IN |
| 5 | DATA_IN_5 | DAC_OUT_5 | CONFIG ADDR_2_IN |
| 6 | DATA_IN_6 | DAC_OUT_6 | WR_enable_IN (active low) |
| 7 | DATA_IN_7 | DAC_OUT_7 | Enable_IN (active low) |