Whole-engine fabric budget: about 2.5x the DE25-Standard in logic; architecture and board to decide #170

Open
opened 2026-10-06 20:27:50 +00:00 by bcox · 3 comments
Owner

An estimate of what the whole instrument costs on the fabric, made on 2026-10-06 while stage F9.1b slice 1 (branch f9-1b-slice1, commit 7523bbcd) was closing. It answers one question: does every layer engine fit the DE25-Standard, and if not, by how much.

Nothing was run for the estimate. Figures are read from fit reports, the price ledger and the C++ sources, and each is labeled measured, derived or guess. The estimate is joan's (the FPGA specialist agent); the license and form-factor checks at the end were made separately.

Verdict

  • Built the way the VA layer is built today (a hardwired pipeline per engine), the whole instrument is about 2.2x to 2.7x the device in logic (range 1.5x to 4x). This is the "small multiple" case: not short one or two engines, and not 4x.
  • Logic (ALMs) binds first, block RAM second (about 1.3x to 1.6x), DSP blocks last.
  • DSP does not bind if every multiplier is a pool member: about 50 to 70 blocks for a mixed 128-voice bank, of 188.
  • The DE25-Standard holds the full VA layer, the mixer and the small effects. It does not hold all twelve engines at once.
  • Fewer voices does not rescue it. Logic buys datapaths, not voices.

Device: Agilex 5 A5ED013BB32AE4SCS, 46,800 ALMs, 358 M20K, 188 DSP blocks. Engine clock 250 MHz; a 48 kHz sample is 5,106 cycles.

resource whole image now (measured) full VA layer, 128 voices, ratio 4 whole engine, likely (low to high) device
ALMs 25,375 (engine 14,509; other 10,866) 24k to 29k (guess on a measured base) 105k to 125k (70k to 190k) 46,800
M20K 133 (engine 87; other 46) 340 to 380 with tables (derived; ledger floor 273) 400 to 500 (310 to 800) 358
DSP blocks 65 (63 private, 2 pooled) 66 to 99 pooled (derived); 177 as built (ledger) 50 to 70 pooled (25 to 480 by workload) 188
cycles a sample 973 to 4,300 a pass 4,526 for the ratio-4 skeleton per engine 5,106

"Whole image now" is the hps_lw compile at 7523bbcd, which plays 3 of the 19 factory VA patches at ratio 1, one layer, 128 voice indices.

The measured anchor

The part of the verdict that is not a guess:

  • u_layer is 12,388 ALMs in place (measured, golden_top.fit.rpt by entity).
  • The ratio-4 ladders and wide decimator already fitted are 7,614 ALMs (measured, ledger row 16).
  • That is about 20,000 ALMs with sixteen VA patches' paths still missing, against about 35,900 free after the non-engine image.
  • Under 16,000 ALMs are then left for eleven more engines, the layer strip and a 65-strip mixer, when single primitives cost 1,300 to 2,000 each.

The remaining VA paths are a guess of 4k to 9k ALMs, from slice 1's 4,599 ALMs for about five features. The other engines' 45k to 70k is a sum of guesses by analogy: only one composed layer has ever been fitted. That is the weakest number here.

What binds, and why

ALMs.

  • The layer is register-dominated: 40,001 registers behind a 331-stage pipeline (ledger row 17), and 6,075 of its 16,244 placed ALMs hold registers only.
  • Its largest pieces by entity: its own glue 3,392, mod_op 1,974, the bit-serial reciprocal 1,310, the envelope 1,224, svf_coefficients 804, sync_slave 792.
  • Pooling as built costs logic. The pooled multiplier took the layer from 93 DSP blocks to 65 and added 1,177 ALMs and 100 pipeline stages (ledger, "The fit across the slice"). It saved the resource that is not scarce and spent the one that is.
  • Today's 65 DSP blocks carry about 13k products a sample: roughly 4% utilization.

M20K.

  • Decimator histories and tables dominate. Shared ROMs alone are about 115 blocks (derived from table sizes).
  • 128 modal voices at 128 modes need about 344 blocks; 128 two-layer FM voices at 16x about 490 (derived, ideal packing). Measured state packs at about twice ideal.
  • One FM patch's spectral tables are up to 4.2 Mbit, 205 M20K, if kept on chip (derived).

Bulk storage is off-chip on any board.

  • The software region is 185 MB (fabric::kRegionPages) against 64 MB of fabric SDRAM and under 1 MB of M20K in total.
  • Whether the SDRAM's random-access rate carries 128 waveguide voices (about 1,300 word accesses a sample) is not determined.

DSP, pooled. One 32x32 pool member gives about 3,600 products a sample at 70% use.

  • F4 target, 128 VA voices at ratio 1: about 17k products, 10 to 15 blocks.
  • 128 voices at the factory bank's mix: about 82k products, 50 to 70 blocks.
  • Every voice an FM pair at 16x: 190k to 576k products, 0.6x to 2.6x of the device.

Cycles. Each engine's pass must fit 5,106 on its own. These need replicated lanes, paid in ALMs, whatever the board:

  • a hard-synced VA voice at ratio 4 at 128 voices (128 x 4 x 15 = 7,680);
  • the FM pair at 16x (2,048 ticks a sample, each with a harmonic loop);
  • modal at full polyphony.

Per engine

Twelve kinds are registered (LayerKind, plugin/program.h). Multiplies are per voice-layer per 48 kHz sample, counted from source by hand, not instrumented. Almost none fits one 27x27: operands are 32x32 or 21x39, so a multiplier is 2 DSP blocks.

engine (factory patches) multiplies hot state notes
VA (19) about 100 at ratio 1; about 920 with the ladder at 4x 2.6 kbit measured for 3 patches 514 of the 920 are the decimator; 8 patches derive 4x
FM pair (6) 190 to 750 typical (guess on ratio); 1,485 for a sine pair at 16x 6 kbit plus 32.8 kbit of history at 16x operators are additive sums of up to 512 harmonics
Unvoiced (12) 72 to 86 1.3 kbit ratio 1
Partial (3) 150 to 350 18 kbit 598 kbit of frames a patch
Modal (10) 730 to 1,400 55 kbit 10 a mode, 64 to 128 modes
Waveguide (8) 20 to 150 7 kbit 590 kbit of line a voice in the region
Particle (5) 80 to 240 average; 3,000+ on a worst sample about 60 kbit Poisson scheduler
Delay, long delay 13 to 35 small 590 kbit a chorus slot; region for the long one
Reverb 31 (plate) to 218 (hall) 2 kbit 35 to 75 region accesses a sample
Phaser, shifter 27 to 53 1 to 2.5 kbit no bulk storage
Layer strip, a slot 16; about 60 with the damper 0.3 kbit
Mixer, all 65 strips up to about 3,470 about 3 kbit a strip

The factory bank averages 1.4 layers a patch.

What the answer hinges on

  • A hardwired pipeline per engine, as today: 2.2x to 2.7x in ALMs.
  • One shared, programmed datapath (pool members, voice state in RAM, a per-engine schedule): ALMs stop scaling with engine count, perhaps 0.8x to 1.5x (guess). M20K still runs about 1.5x and worst-case FM still overruns. Unbuilt and unpriced. This is where "all engines share the multipliers" leads if followed through: the whole datapath is shared, not only the multipliers.
  • Frame primitives shared across engines (envelope, matrix, exp2, coefficients, reciprocal): about 5.5k ALMs paid once instead of per engine.
  • Voices per engine. Capping FM at 16x and modal at about 32 voices each brings M20K to about 1x.
  • Where bulk state goes. Fabric-attached DDR on a larger board removes the SDRAM question.

The step up, if it is taken

The device is the Agilex 5 E-Series 065B: 222,400 ALMs, 1,611 M20K, 846 DSP blocks (Altera's product tables, 2026.08.07). That is 4.75x the logic and 4.5x the memory of the 013B.

board device fabric memory price
Altera 065B Modular Development Kit, sold by Terasic A5ED065BB32AE4S two 8 GB DDR4 banks $1,995 (Terasic)
Terasic Atum A5 same 4 GB DDR4 fabric-only, 4 GB shared $2,343 (Terasic)
Arrow/Trenz AXE5-Eagle-ES 065B engineering sample 1 GB LPDDR4 $995 (LinuxGizmos; Arrow's page timed out)
  • Quartus stays free. The Agilex 5 E-Series is on Altera's no-cost Quartus Prime Pro license (SW-AGILEX-5E, renewed yearly); the pages read state no density limit. Requesting the license for the 065B part before a purchase confirms it at no cost. The D-Series is not on the free list (a paid license is about $3,645, unverified), and no board carrying one was found.
  • No PCIe host is needed. All three are PCIe-capable and run on a bench from 12 V. The Altera kit is a module on a carrier with a 12 V adapter in the box (confirmed from its contents list). The Atum A5 is described as "tabletop and PCIe form factor"; the AXE5-Eagle is card-shaped and ships with a 12 V supply. The last two are as reported by distributor and news pages; Terasic's own pages did not load.
  • None has an audio codec or HSMC; all use FMC or FMC+. The missing codec is not a cost of moving: the DE25-Standard's SSM2603 is a temporary measure and an audio daughtercard is being built regardless (bcox, 2026-10-06). What the board choice does decide is that card's connector, HSMC on the DE25-Standard against FMC on these, so the card's design should wait for this decision or carry both. The HPS reference design is redone for a new board.
  • A larger board does not fix the cycle budget. These are the same -4 speed grade, so a sample is still 5,106 cycles; the extra ALMs are what pay for replicated datapaths.
  • DE25-Standard for reference: $586 list.

Cheapest measurements, in order

  1. Count products in software (hours, no Quartus): a counting build of dsp/fixed.h's multiply over the factory bank, giving measured products a voice-sample per patch and the FM ratios patches actually derive. Replaces every hand count above.
  2. Re-run //plugin:state_census with patch and ratio named (minutes). Settles M20K per slot, which the ledger still marks unverified.
  3. Fit a second engine's skeleton beside the VA frame: the modal bank (CoupledMode) or the FM tick with a 16x1025 wide decimator (a day or two). The only way to a second ALM data point. More than about 5k ALMs beyond shared primitives confirms 2x-plus.
  4. Compile hps_lw for A5ED065BB32AE4S before buying (free, about an hour), to see whether timing holds at 250 MHz on the larger die.

A trigger that needs no extra work: if the full VA layer passes about 24k ALMs on the current path during the ratio-4 stage (F9.1c), the purchase is decided without item 3.

Decisions this ticket is for

  • Whether the engines keep a hardwired pipeline each, or move to one shared programmed datapath. This moves the answer more than a board does.
  • Whether to buy a 065B board, and which.
  • The standing rule this came from (bcox, 2026-10-06): every engine stage states its share of a whole-instrument budget before its design, and an overshoot is raised when it is visible, not at a gate.

Sources

An estimate of what the whole instrument costs on the fabric, made on 2026-10-06 while stage F9.1b slice 1 (branch `f9-1b-slice1`, commit 7523bbcd) was closing. It answers one question: does every layer engine fit the DE25-Standard, and if not, by how much. Nothing was run for the estimate. Figures are read from fit reports, the price ledger and the C++ sources, and each is labeled **measured**, **derived** or **guess**. The estimate is joan's (the FPGA specialist agent); the license and form-factor checks at the end were made separately. ## Verdict - Built the way the VA layer is built today (a hardwired pipeline per engine), the whole instrument is about **2.2x to 2.7x the device in logic** (range 1.5x to 4x). This is the "small multiple" case: not short one or two engines, and not 4x. - **Logic (ALMs) binds first**, block RAM second (about 1.3x to 1.6x), DSP blocks last. - **DSP does not bind if every multiplier is a pool member**: about 50 to 70 blocks for a mixed 128-voice bank, of 188. - The DE25-Standard holds the full VA layer, the mixer and the small effects. It does not hold all twelve engines at once. - **Fewer voices does not rescue it.** Logic buys datapaths, not voices. Device: Agilex 5 A5ED013BB32AE4SCS, 46,800 ALMs, 358 M20K, 188 DSP blocks. Engine clock 250 MHz; a 48 kHz sample is 5,106 cycles. | resource | whole image now (measured) | full VA layer, 128 voices, ratio 4 | whole engine, likely (low to high) | device | |---|---|---|---|---| | ALMs | 25,375 (engine 14,509; other 10,866) | 24k to 29k (guess on a measured base) | 105k to 125k (70k to 190k) | 46,800 | | M20K | 133 (engine 87; other 46) | 340 to 380 with tables (derived; ledger floor 273) | 400 to 500 (310 to 800) | 358 | | DSP blocks | 65 (63 private, 2 pooled) | 66 to 99 pooled (derived); 177 as built (ledger) | 50 to 70 pooled (25 to 480 by workload) | 188 | | cycles a sample | 973 to 4,300 a pass | 4,526 for the ratio-4 skeleton | per engine | 5,106 | "Whole image now" is the `hps_lw` compile at 7523bbcd, which plays 3 of the 19 factory VA patches at ratio 1, one layer, 128 voice indices. ## The measured anchor The part of the verdict that is not a guess: - `u_layer` is 12,388 ALMs in place (measured, `golden_top.fit.rpt` by entity). - The ratio-4 ladders and wide decimator already fitted are 7,614 ALMs (measured, ledger row 16). - That is about 20,000 ALMs with sixteen VA patches' paths still missing, against about 35,900 free after the non-engine image. - Under 16,000 ALMs are then left for eleven more engines, the layer strip and a 65-strip mixer, when single primitives cost 1,300 to 2,000 each. The remaining VA paths are a guess of 4k to 9k ALMs, from slice 1's 4,599 ALMs for about five features. The other engines' 45k to 70k is a sum of guesses by analogy: only one composed layer has ever been fitted. That is the weakest number here. ## What binds, and why **ALMs.** - The layer is register-dominated: 40,001 registers behind a 331-stage pipeline (ledger row 17), and 6,075 of its 16,244 placed ALMs hold registers only. - Its largest pieces by entity: its own glue 3,392, `mod_op` 1,974, the bit-serial reciprocal 1,310, the envelope 1,224, `svf_coefficients` 804, `sync_slave` 792. - Pooling as built costs logic. The pooled multiplier took the layer from 93 DSP blocks to 65 and added 1,177 ALMs and 100 pipeline stages (ledger, "The fit across the slice"). It saved the resource that is not scarce and spent the one that is. - Today's 65 DSP blocks carry about 13k products a sample: roughly 4% utilization. **M20K.** - Decimator histories and tables dominate. Shared ROMs alone are about 115 blocks (derived from table sizes). - 128 modal voices at 128 modes need about 344 blocks; 128 two-layer FM voices at 16x about 490 (derived, ideal packing). Measured state packs at about twice ideal. - One FM patch's spectral tables are up to 4.2 Mbit, 205 M20K, if kept on chip (derived). **Bulk storage is off-chip on any board.** - The software region is 185 MB (`fabric::kRegionPages`) against 64 MB of fabric SDRAM and under 1 MB of M20K in total. - Whether the SDRAM's random-access rate carries 128 waveguide voices (about 1,300 word accesses a sample) is not determined. **DSP, pooled.** One 32x32 pool member gives about 3,600 products a sample at 70% use. - F4 target, 128 VA voices at ratio 1: about 17k products, 10 to 15 blocks. - 128 voices at the factory bank's mix: about 82k products, 50 to 70 blocks. - Every voice an FM pair at 16x: 190k to 576k products, 0.6x to 2.6x of the device. **Cycles.** Each engine's pass must fit 5,106 on its own. These need replicated lanes, paid in ALMs, whatever the board: - a hard-synced VA voice at ratio 4 at 128 voices (128 x 4 x 15 = 7,680); - the FM pair at 16x (2,048 ticks a sample, each with a harmonic loop); - modal at full polyphony. ## Per engine Twelve kinds are registered (`LayerKind`, `plugin/program.h`). Multiplies are per voice-layer per 48 kHz sample, counted from source by hand, not instrumented. Almost none fits one 27x27: operands are 32x32 or 21x39, so a multiplier is 2 DSP blocks. | engine (factory patches) | multiplies | hot state | notes | |---|---|---|---| | VA (19) | about 100 at ratio 1; about 920 with the ladder at 4x | 2.6 kbit measured for 3 patches | 514 of the 920 are the decimator; 8 patches derive 4x | | FM pair (6) | 190 to 750 typical (guess on ratio); 1,485 for a sine pair at 16x | 6 kbit plus 32.8 kbit of history at 16x | operators are additive sums of up to 512 harmonics | | Unvoiced (12) | 72 to 86 | 1.3 kbit | ratio 1 | | Partial (3) | 150 to 350 | 18 kbit | 598 kbit of frames a patch | | Modal (10) | 730 to 1,400 | 55 kbit | 10 a mode, 64 to 128 modes | | Waveguide (8) | 20 to 150 | 7 kbit | 590 kbit of line a voice in the region | | Particle (5) | 80 to 240 average; 3,000+ on a worst sample | about 60 kbit | Poisson scheduler | | Delay, long delay | 13 to 35 | small | 590 kbit a chorus slot; region for the long one | | Reverb | 31 (plate) to 218 (hall) | 2 kbit | 35 to 75 region accesses a sample | | Phaser, shifter | 27 to 53 | 1 to 2.5 kbit | no bulk storage | | Layer strip, a slot | 16; about 60 with the damper | 0.3 kbit | | | Mixer, all 65 strips | up to about 3,470 | about 3 kbit a strip | | The factory bank averages 1.4 layers a patch. ## What the answer hinges on - **A hardwired pipeline per engine, as today:** 2.2x to 2.7x in ALMs. - **One shared, programmed datapath** (pool members, voice state in RAM, a per-engine schedule): ALMs stop scaling with engine count, perhaps 0.8x to 1.5x (guess). M20K still runs about 1.5x and worst-case FM still overruns. Unbuilt and unpriced. This is where "all engines share the multipliers" leads if followed through: the whole datapath is shared, not only the multipliers. - **Frame primitives shared across engines** (envelope, matrix, exp2, coefficients, reciprocal): about 5.5k ALMs paid once instead of per engine. - **Voices per engine.** Capping FM at 16x and modal at about 32 voices each brings M20K to about 1x. - **Where bulk state goes.** Fabric-attached DDR on a larger board removes the SDRAM question. ## The step up, if it is taken The device is the Agilex 5 E-Series 065B: 222,400 ALMs, 1,611 M20K, 846 DSP blocks (Altera's product tables, 2026.08.07). That is 4.75x the logic and 4.5x the memory of the 013B. | board | device | fabric memory | price | |---|---|---|---| | Altera 065B Modular Development Kit, sold by Terasic | A5ED065BB32AE4S | two 8 GB DDR4 banks | $1,995 (Terasic) | | Terasic Atum A5 | same | 4 GB DDR4 fabric-only, 4 GB shared | $2,343 (Terasic) | | Arrow/Trenz AXE5-Eagle-ES | 065B engineering sample | 1 GB LPDDR4 | $995 (LinuxGizmos; Arrow's page timed out) | - **Quartus stays free.** The Agilex 5 E-Series is on Altera's no-cost Quartus Prime Pro license (SW-AGILEX-5E, renewed yearly); the pages read state no density limit. Requesting the license for the 065B part before a purchase confirms it at no cost. The D-Series is not on the free list (a paid license is about $3,645, unverified), and no board carrying one was found. - **No PCIe host is needed.** All three are PCIe-capable and run on a bench from 12 V. The Altera kit is a module on a carrier with a 12 V adapter in the box (confirmed from its contents list). The Atum A5 is described as "tabletop and PCIe form factor"; the AXE5-Eagle is card-shaped and ships with a 12 V supply. The last two are as reported by distributor and news pages; Terasic's own pages did not load. - **None has an audio codec or HSMC; all use FMC or FMC+.** The missing codec is not a cost of moving: the DE25-Standard's SSM2603 is a temporary measure and an audio daughtercard is being built regardless (bcox, 2026-10-06). What the board choice does decide is that card's connector, HSMC on the DE25-Standard against FMC on these, so the card's design should wait for this decision or carry both. The HPS reference design is redone for a new board. - **A larger board does not fix the cycle budget.** These are the same -4 speed grade, so a sample is still 5,106 cycles; the extra ALMs are what pay for replicated datapaths. - DE25-Standard for reference: $586 list. ## Cheapest measurements, in order 1. **Count products in software** (hours, no Quartus): a counting build of `dsp/fixed.h`'s multiply over the factory bank, giving measured products a voice-sample per patch and the FM ratios patches actually derive. Replaces every hand count above. 2. **Re-run `//plugin:state_census` with patch and ratio named** (minutes). Settles M20K per slot, which the ledger still marks unverified. 3. **Fit a second engine's skeleton beside the VA frame**: the modal bank (`CoupledMode`) or the FM tick with a 16x1025 wide decimator (a day or two). The only way to a second ALM data point. More than about 5k ALMs beyond shared primitives confirms 2x-plus. 4. **Compile `hps_lw` for A5ED065BB32AE4S before buying** (free, about an hour), to see whether timing holds at 250 MHz on the larger die. A trigger that needs no extra work: if the full VA layer passes about 24k ALMs on the current path during the ratio-4 stage (F9.1c), the purchase is decided without item 3. ## Decisions this ticket is for - Whether the engines keep a hardwired pipeline each, or move to one shared programmed datapath. This moves the answer more than a board does. - Whether to buy a 065B board, and which. - The standing rule this came from (bcox, 2026-10-06): every engine stage states its share of a whole-instrument budget before its design, and an overshoot is raised when it is visible, not at a gate. ## Sources - `docs/superpowers/ledgers/2026-10-03-fabric-prices.md` on branch `f9-1b-slice1`: rows 15a-c, 16, 17, 18a-h; "The ratio-4 price, stage F9.1a"; "The second voice path, stage F9.1b slice 1". - Fit reports of the `hps_lw` compile and the layer's standalone fit at 7523bbcd (`golden_top.fit.rpt`, `va_layer_fit.fit.rpt`; build outputs, not in git). - `docs/superpowers/specs/2026-10-03-f4-fabric-shape-design.md`; `fabric/fabric.h` (`kRegionPages`); `plugin/program.h` (`LayerKind`). - https://www.intel.com/content/www/us/en/content-details/819593/agilex-5-e-series-no-cost-license.html - https://www.macnica.co.jp/en/business/semiconductor/articles/altera/145133/ - https://www.altera.com/products/devkit/po-3274/agilex-5-fpga-and-soc-e-series-065b-modular-development-kit - https://forum.digikey.com/t/agilex-5-fpga-e-series-065b-modular-development-kit-contents/58803 - https://www.mouser.com/en/new/terasic-technologies/terasic-atum-a5-dev-intel-agilex5 - https://www.cnx-software.com/2024/10/16/trenz-electronic-axe5-eagle-es-devkit-features-intel-agilex-5-e-series-soc-fpga/
Author
Owner

Measurements 1, 2 and 4 of "Cheapest measurements", run 2026-10-06 on main at 36827bd2. Measurement 3 (a second engine's skeleton fit) is not done.

4. hps_lw compiled for A5ED065BB32AE4S (measured)

The current board image with only the part name changed. 11 minutes, no errors, no critical warnings.

  • 25,367 of 222,400 ALMs (11%); 133 of 1,611 M20K (8%); 65 of 846 DSP blocks (8%).
  • Every timing summary passes: worst setup slack +0.270 ns, worst hold 0.000 ns.
  • Engine clock (pll_inst|pll_outclk1, needs 250 MHz): 268.1 MHz, restricted to 258.87 MHz by minimum pulse width.
  • The pin assignments are the DE25-Standard's (same B32A package), so this is a fit and timing result for the die, not a working image. Timing at high utilization on the larger die is untested.
  • Quartus's 1,692 is the Fitter Summary's count of 18x19 multipliers, the unit in which the 013B is 376. In the ticket's unit that is 846 blocks against 188, as the ticket says. (An earlier version of this comment called the ticket's 846 wrong; it is not.)

1. Products per voice-layer per 48 kHz sample (measured)

Branch m170-software-counts (five commits on 36827bd2, not merged): a counting mode for MulExact and Lerp in dsp/fixed.h, a DSP_MUL wrap on the 232 products dsp/ wrote on raw integers, and //plugin:product_census. One note, one voice, every factory patch, at its demo key and its low and high keys; mean over sustain, and the worst single sample.

bazel run --copt=-DTYMBAL_PRODUCT_CENSUS //plugin:product_census

engine hand count (ticket) measured, sustain mean worst sample
VA, ratio 1 about 100 96 to 348, median 140
VA, ratio 4 about 920 869 to 1,214 1,267
FM pair 190 to 750; 1,485 sine pair at 16x 109 to 1,437, median 144 1,563
Unvoiced 72 to 86 66 to 107 124
Partial 150 to 350 154 to 348 351
Modal 730 to 1,400 763 (64 modes) to 1,372 (128) 1,512
Waveguide 20 to 150 15 to 144, median 22 146
Particle 80 to 240 184 to 284 1,457
Delay, long delay 13 to 35 11
Reverb 31 to 218 31 (plate), 218 (room, hall)
Phaser, shifter 27 to 53 29, 52
Leslie no row 163 to 166
Graphic EQ no row 338
Parametric EQ no row 112
Filter bank no row 140
Layer strip 16 16 stereo, 11 mono 24
Fabric strip, EQ and compressor about 53 86 settled, 123 while ramping
  • Moved by more than 1.5x: VA's heavy end at ratio 1 (alpha-juno-hoover, about 3x), FM at both ends, particle's low end, and the mixer (65 strips: 5,590 settled, 7,995 ramping, derived, against about 3,470).
  • Confirmed: VA at ratio 4, modal (about 9.5 a mode), partial, waveguide, reverb, phaser, shifter, the layer strip, and that 8 patches derive ratio 4.
  • Sixteen engine kinds are registered, not twelve, and 21 factory patches carry a VA layer, not 19.
  • FM's cost in the bank is carrier harmonics, not oversampling. The two dearest FM layers run at ratio 1 (hello 1,225 to 1,437, kargyraa 876). Ratios derived across the bank: 1, 2, 4 and 8; no factory patch reaches 16 at any key played, so that case is unmeasured, and a harmonic-rich pair at a high ratio would exceed the ticket's all-FM figure.
  • Bank mix: 472 products a patch-voice with strips and frame, so 60.4k for 128 voices (derived) against "about 82k".
  • Widths: almost nothing fits one 27x27, as the ticket says. VA: 7% fit, 84% need up to 32x32, 8% have an operand past 32 bits. FM 20 / 45 / 35; modal 1 / 61 / 38. The graphic and parametric EQ are entirely past 32 bits (39x25, 40x24).
  • 16.5% of all products were on raw integers and invisible to a fixed.h-only count: 37% of FM, 34% of unvoiced, 32% of partial, 27% of VA.

What the count is not: it counts products performed, and the C++ skips a unity gain, a bypassed band and an untaken branch that a fixed pipeline would spend a turn on. Effect returns were fed silence. Multiplies by small literals and by a sign are left out. Constant operands could be separated only to a floor of 0 to 8% by kind.

2. Hot state per slot (measured, //plugin:state_census, -O3)

Bytes of the C++ layer object a held note's render touches. Not RTL state bits; region storage, tables and patch data reached by pointer are not seen.

engine ticket measured
VA 2.6 kbit (3 patches, RTL) 7.3 to 11.2 kbit at ratio 1; 22.5 to 24.6 at ratio 4
FM pair 6 kbit plus 32.8 history at 16x 4.5 to 4.7 at ratio 1; 7.7 at 2; 11.8 at 4; 19.9 at 8
Unvoiced 1.3 0.4 to 3.0
Partial 18 7.1 to 9.8
Modal 55 35 to 66 (128 modes at the top)
Waveguide 7 3.9 to 8.2
Particle about 60 22.5 to 36 in the slot; cold storage is counted in the frame
Reverb 2 5.0 to 10.6
Shifter 2.5 6.1
  • The ledger's 3,068 B slot is a VA slot at ratio 4, of which two 257-tap decimators are 2,056 B (derived).
  • The ledger's -O0 disagreement is explained and -O3 stands: at -O0 a by-value read of a Sample is a memory copy the sanitizer hooks do not trace (moog-lead reads 632 B, less than its FIR's history). -O1 agrees with -O3 on nine patches.

What this does to the verdict

  • Nothing here measures ALMs, so the 2.2x to 2.7x figure is neither confirmed nor moved. That is measurement 3.
  • DSP, pooled, stays the last resource to bind.
  • Modal at full polyphony is the M20K case: 128 voices at 128 modes is 8.5 Mbit of touched state (derived from 66 kbit a voice), about 425 M20K at ideal packing against the 013B's 358, where the ticket derived 344. It is also about 176k products a sample, about 34 a cycle.
Measurements 1, 2 and 4 of "Cheapest measurements", run 2026-10-06 on main at 36827bd2. Measurement 3 (a second engine's skeleton fit) is not done. ## 4. `hps_lw` compiled for A5ED065BB32AE4S (measured) The current board image with only the part name changed. 11 minutes, no errors, no critical warnings. - 25,367 of 222,400 ALMs (11%); 133 of 1,611 M20K (8%); 65 of 846 DSP blocks (8%). - Every timing summary passes: worst setup slack +0.270 ns, worst hold 0.000 ns. - Engine clock (`pll_inst|pll_outclk1`, needs 250 MHz): 268.1 MHz, restricted to 258.87 MHz by minimum pulse width. - The pin assignments are the DE25-Standard's (same B32A package), so this is a fit and timing result for the die, not a working image. Timing at high utilization on the larger die is untested. - Quartus's 1,692 is the Fitter Summary's count of 18x19 multipliers, the unit in which the 013B is 376. In the ticket's unit that is 846 blocks against 188, as the ticket says. (An earlier version of this comment called the ticket's 846 wrong; it is not.) ## 1. Products per voice-layer per 48 kHz sample (measured) Branch `m170-software-counts` (five commits on 36827bd2, not merged): a counting mode for `MulExact` and `Lerp` in `dsp/fixed.h`, a `DSP_MUL` wrap on the 232 products `dsp/` wrote on raw integers, and `//plugin:product_census`. One note, one voice, every factory patch, at its demo key and its low and high keys; mean over sustain, and the worst single sample. `bazel run --copt=-DTYMBAL_PRODUCT_CENSUS //plugin:product_census` | engine | hand count (ticket) | measured, sustain mean | worst sample | |---|---|---|---| | VA, ratio 1 | about 100 | 96 to 348, median 140 | | | VA, ratio 4 | about 920 | 869 to 1,214 | 1,267 | | FM pair | 190 to 750; 1,485 sine pair at 16x | 109 to 1,437, median 144 | 1,563 | | Unvoiced | 72 to 86 | 66 to 107 | 124 | | Partial | 150 to 350 | 154 to 348 | 351 | | Modal | 730 to 1,400 | 763 (64 modes) to 1,372 (128) | 1,512 | | Waveguide | 20 to 150 | 15 to 144, median 22 | 146 | | Particle | 80 to 240 | 184 to 284 | 1,457 | | Delay, long delay | 13 to 35 | 11 | | | Reverb | 31 to 218 | 31 (plate), 218 (room, hall) | | | Phaser, shifter | 27 to 53 | 29, 52 | | | Leslie | no row | 163 to 166 | | | Graphic EQ | no row | 338 | | | Parametric EQ | no row | 112 | | | Filter bank | no row | 140 | | | Layer strip | 16 | 16 stereo, 11 mono | 24 | | Fabric strip, EQ and compressor | about 53 | 86 settled, 123 while ramping | | - **Moved by more than 1.5x:** VA's heavy end at ratio 1 (alpha-juno-hoover, about 3x), FM at both ends, particle's low end, and the mixer (65 strips: 5,590 settled, 7,995 ramping, derived, against about 3,470). - **Confirmed:** VA at ratio 4, modal (about 9.5 a mode), partial, waveguide, reverb, phaser, shifter, the layer strip, and that 8 patches derive ratio 4. - **Sixteen engine kinds are registered, not twelve**, and 21 factory patches carry a VA layer, not 19. - **FM's cost in the bank is carrier harmonics, not oversampling.** The two dearest FM layers run at ratio 1 (hello 1,225 to 1,437, kargyraa 876). Ratios derived across the bank: 1, 2, 4 and 8; no factory patch reaches 16 at any key played, so that case is unmeasured, and a harmonic-rich pair at a high ratio would exceed the ticket's all-FM figure. - **Bank mix:** 472 products a patch-voice with strips and frame, so 60.4k for 128 voices (derived) against "about 82k". - **Widths:** almost nothing fits one 27x27, as the ticket says. VA: 7% fit, 84% need up to 32x32, 8% have an operand past 32 bits. FM 20 / 45 / 35; modal 1 / 61 / 38. The graphic and parametric EQ are entirely past 32 bits (39x25, 40x24). - **16.5% of all products were on raw integers** and invisible to a `fixed.h`-only count: 37% of FM, 34% of unvoiced, 32% of partial, 27% of VA. What the count is not: it counts products performed, and the C++ skips a unity gain, a bypassed band and an untaken branch that a fixed pipeline would spend a turn on. Effect returns were fed silence. Multiplies by small literals and by a sign are left out. Constant operands could be separated only to a floor of 0 to 8% by kind. ## 2. Hot state per slot (measured, `//plugin:state_census`, `-O3`) Bytes of the C++ layer object a held note's render touches. Not RTL state bits; region storage, tables and patch data reached by pointer are not seen. | engine | ticket | measured | |---|---|---| | VA | 2.6 kbit (3 patches, RTL) | 7.3 to 11.2 kbit at ratio 1; 22.5 to 24.6 at ratio 4 | | FM pair | 6 kbit plus 32.8 history at 16x | 4.5 to 4.7 at ratio 1; 7.7 at 2; 11.8 at 4; 19.9 at 8 | | Unvoiced | 1.3 | 0.4 to 3.0 | | Partial | 18 | 7.1 to 9.8 | | Modal | 55 | 35 to 66 (128 modes at the top) | | Waveguide | 7 | 3.9 to 8.2 | | Particle | about 60 | 22.5 to 36 in the slot; cold storage is counted in the frame | | Reverb | 2 | 5.0 to 10.6 | | Shifter | 2.5 | 6.1 | - The ledger's 3,068 B slot is a VA slot at ratio 4, of which two 257-tap decimators are 2,056 B (derived). - The ledger's `-O0` disagreement is explained and `-O3` stands: at `-O0` a by-value read of a `Sample` is a memory copy the sanitizer hooks do not trace (moog-lead reads 632 B, less than its FIR's history). `-O1` agrees with `-O3` on nine patches. ## What this does to the verdict - Nothing here measures ALMs, so the 2.2x to 2.7x figure is neither confirmed nor moved. That is measurement 3. - DSP, pooled, stays the last resource to bind. - Modal at full polyphony is the M20K case: 128 voices at 128 modes is 8.5 Mbit of touched state (derived from 66 kbit a voice), about 425 M20K at ideal packing against the 013B's 358, where the ticket derived 344. It is also about 176k products a sample, about 34 a cycle.
Author
Owner

Measurement 3, run 2026-10-06: a second engine's skeleton, fitted.

rtl/dsp/modal_skeleton on branch m170-modal-skeleton (714a2d19, not merged): dsp::ModeBank<kModes, CoupledMode>'s whole per-mode work for V voices of M modes in K lanes, a mode a cycle a lane, eleven multiplies a mode. Bit-exact against the header in Verilator (1.26M mode-steps and 93,600 reads at 78 voices of 128 modes in 2 lanes, 0 mismatched; eight injections, all caught).

Fits (measured, A5ED013BB32AE4SCS, alone at 245.76 MHz)

V x M, lanes ALMs M20K DSP blocks restricted fmax
32 x 128, 1 1,997 55 22 308.1 MHz
64 x 128, 2 3,737 110 44 311.9 MHz
128 x 128, 4 7,340 (16%) 220 (61%) 88 (47%) 307.9 MHz
  • Lanes add: nothing merged across them. The one-lane total carries 289 ALMs the fitter charges to the fit top's virtual pins; the lane itself is 1,708.
  • One lane by entity: its eleven multipliers 562 ALMs (seven pool_multiply at 65 to 76 each, four 23 x 39 rotation multipliers at 14 to 18 each); RAM decode and muxes 106; everything else 1,040 (the reads' accumulate, round and saturate 477, the lane's control 163, the inject sums 169, the rotation's adds and requantize 149, delay lines 83).
  • 55 M20K a lane against 44 at ideal packing of its 908,832 bits.
  • 128 x 128 needs four lanes (derived: a lane holds 39 voices of 128 modes in 5,106 cycles; that shape was simulated with 90 cycles to spare). Its 44 multipliers are each busy 80% of a sample, so this workload has no idle multiplier for a pool to reclaim.

Against the ticket's test

The test was: more than about 5k ALMs beyond shared primitives confirms 2x-plus.

  • The skeleton's logic beyond its multipliers and RAM is 1,040 ALMs a lane, 4,160 at 128 x 128. Under 5k, and a floor.
  • Left out, each of which a modal layer needs: ModeBank::RefreshMode (two modes a voice-sample, each a ScaleByOctaves, two Sine lookups and a divide, and 64 more bits a mode, about 52 M20K derived); the junction forces and ceilings; the strings junction, a second walk of a voice's modes; the exciters and their envelopes; the matrix; the envelope follower; the strip. The lane also reads the sites after Advance where the header reads them before, and the correction for weights that move is not priced.
  • So the test is not decided by this fit on logic. My reading (judgment): the whole modal layer passes 5k beyond what it could share, because the VA layer's frame for comparable work (envelope, matrix, exp2, reciprocal) was 5k to 6k on its own.

What it does decide

Logic was the ticket's binding resource. For this engine it is not: block RAM and DSP are.

  • The mode bank alone at 128 x 128 is 61% of the device's M20K and 47% of its DSP blocks, in multipliers that cannot be shared because they are busy.
  • Added to today's image (25,375 ALMs, 133 M20K, 65 DSP; three VA patches at ratio 1): 32.7k ALMs (70%), 353 of 358 M20K, 153 of 188 DSP (derived by addition; not compiled together).
  • The ticket had modal at 128 x 128 as about 344 M20K (derived). Fitted it is 220 for the bank without the refresh's inputs, about 272 with them (derived).
  • Halving either the voices or the modes halves all three figures: 64 x 128 is 3,737 ALMs, 110 M20K, 44 DSP.
  • A shared programmed datapath would save some of the 1,040 ALMs a lane of rounding and control. It saves none of the multipliers and none of the RAM.

So on the DE25-Standard, full-polyphony modal and the full VA layer do not coexist, whatever the architecture; modal at about a quarter of that load does. On the 065B the bank at 128 x 128 is about 3% of the ALMs, 14% of the M20K and 10% of the DSP blocks (derived from the device totals).

Measurement 3, run 2026-10-06: a second engine's skeleton, fitted. `rtl/dsp/modal_skeleton` on branch `m170-modal-skeleton` (714a2d19, not merged): `dsp::ModeBank<kModes, CoupledMode>`'s whole per-mode work for V voices of M modes in K lanes, a mode a cycle a lane, eleven multiplies a mode. Bit-exact against the header in Verilator (1.26M mode-steps and 93,600 reads at 78 voices of 128 modes in 2 lanes, 0 mismatched; eight injections, all caught). ## Fits (measured, A5ED013BB32AE4SCS, alone at 245.76 MHz) | V x M, lanes | ALMs | M20K | DSP blocks | restricted fmax | |---|---|---|---|---| | 32 x 128, 1 | 1,997 | 55 | 22 | 308.1 MHz | | 64 x 128, 2 | 3,737 | 110 | 44 | 311.9 MHz | | 128 x 128, 4 | 7,340 (16%) | 220 (61%) | 88 (47%) | 307.9 MHz | - Lanes add: nothing merged across them. The one-lane total carries 289 ALMs the fitter charges to the fit top's virtual pins; the lane itself is 1,708. - One lane by entity: its eleven multipliers 562 ALMs (seven `pool_multiply` at 65 to 76 each, four 23 x 39 rotation multipliers at 14 to 18 each); RAM decode and muxes 106; everything else 1,040 (the reads' accumulate, round and saturate 477, the lane's control 163, the inject sums 169, the rotation's adds and requantize 149, delay lines 83). - 55 M20K a lane against 44 at ideal packing of its 908,832 bits. - 128 x 128 needs four lanes (derived: a lane holds 39 voices of 128 modes in 5,106 cycles; that shape was simulated with 90 cycles to spare). Its 44 multipliers are each busy 80% of a sample, so this workload has no idle multiplier for a pool to reclaim. ## Against the ticket's test The test was: more than about 5k ALMs beyond shared primitives confirms 2x-plus. - The skeleton's logic beyond its multipliers and RAM is 1,040 ALMs a lane, 4,160 at 128 x 128. Under 5k, and a floor. - Left out, each of which a modal layer needs: `ModeBank::RefreshMode` (two modes a voice-sample, each a `ScaleByOctaves`, two `Sine` lookups and a divide, and 64 more bits a mode, about 52 M20K derived); the junction forces and ceilings; the strings junction, a second walk of a voice's modes; the exciters and their envelopes; the matrix; the envelope follower; the strip. The lane also reads the sites after `Advance` where the header reads them before, and the correction for weights that move is not priced. - So the test is not decided by this fit on logic. My reading (judgment): the whole modal layer passes 5k beyond what it could share, because the VA layer's frame for comparable work (envelope, matrix, exp2, reciprocal) was 5k to 6k on its own. ## What it does decide Logic was the ticket's binding resource. For this engine it is not: block RAM and DSP are. - The mode bank alone at 128 x 128 is 61% of the device's M20K and 47% of its DSP blocks, in multipliers that cannot be shared because they are busy. - Added to today's image (25,375 ALMs, 133 M20K, 65 DSP; three VA patches at ratio 1): 32.7k ALMs (70%), 353 of 358 M20K, 153 of 188 DSP (derived by addition; not compiled together). - The ticket had modal at 128 x 128 as about 344 M20K (derived). Fitted it is 220 for the bank without the refresh's inputs, about 272 with them (derived). - Halving either the voices or the modes halves all three figures: 64 x 128 is 3,737 ALMs, 110 M20K, 44 DSP. - A shared programmed datapath would save some of the 1,040 ALMs a lane of rounding and control. It saves none of the multipliers and none of the RAM. So on the DE25-Standard, full-polyphony modal and the full VA layer do not coexist, whatever the architecture; modal at about a quarter of that load does. On the 065B the bank at 128 x 128 is about 3% of the ALMs, 14% of the M20K and 10% of the DSP blocks (derived from the device totals).
Author
Owner

Decision (bcox, 2026-10-07)

Both boards are targets: the DE25-Standard and the Agilex 5 E-Series 065B Modular Development Kit.

  • DE25-Standard: a set of builds, each a different subset of the engines over one shared framework. One carries the VA engine; another carries the FM pair, and perhaps the partial bank. The model is Korg's Modwave, Opsix and Wavestate: one framework, different sets of functionality.
  • Modular Development Kit: the whole instrument, every engine in one build.

Order of work

  • The kit is on order and is due in about eight weeks.
  • Until it arrives, development continues on the DE25-Standard, as far as that board goes.
  • First, complete what fits on the board. Then plan the reduced-engine builds, so that development can move on to the other engines.
  • The whole instrument in one build is first tested when the kit arrives.

What this settles, of "Decisions this ticket is for"

  • Whether to buy a 065B board, and which: yes, the Modular Development Kit.
  • Hardwired pipeline per engine, or one shared programmed datapath: not settled by this decision.

Recorded in CLAUDE.md under "Targets".

## Decision (bcox, 2026-10-07) Both boards are targets: the DE25-Standard and the Agilex 5 E-Series 065B Modular Development Kit. - **DE25-Standard: a set of builds, each a different subset of the engines over one shared framework.** One carries the VA engine; another carries the FM pair, and perhaps the partial bank. The model is Korg's Modwave, Opsix and Wavestate: one framework, different sets of functionality. - **Modular Development Kit: the whole instrument**, every engine in one build. ## Order of work - The kit is on order and is due in about eight weeks. - Until it arrives, development continues on the DE25-Standard, as far as that board goes. - First, complete what fits on the board. Then plan the reduced-engine builds, so that development can move on to the other engines. - The whole instrument in one build is first tested when the kit arrives. ## What this settles, of "Decisions this ticket is for" - **Whether to buy a 065B board, and which:** yes, the Modular Development Kit. - **Hardwired pipeline per engine, or one shared programmed datapath:** not settled by this decision. Recorded in `CLAUDE.md` under "Targets".
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bcox/tymbal#170
No description provided.