# gowin:Mapping DSP cells (MULT36x36, MULT18x18 and MULT9x9) during synthesis

**URL:** https://yosyshq.discourse.group/t/gowin-mapping-dsp-cells-mult36x36-mult18x18-and-mult9x9-during-synthesis/91
**Category:** Developers
**Created:** [October 5, 2025, 3:02pm UTC](https://yosyshq.discourse.group/t/gowin-mapping-dsp-cells-mult36x36-mult18x18-and-mult9x9-during-synthesis/91 "2025-10-05T15:02:40Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![plaes](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/plaes/32/27_2.png) [@plaes](https://yosyshq.discourse.group/u/plaes)
#### Post date: [October 5, 2025, 3:02pm UTC](https://yosyshq.discourse.group/t/gowin-mapping-dsp-cells-mult36x36-mult18x18-and-mult9x9-during-synthesis/91/1 "2025-10-05T15:02:40Z")

</div>

I recently discovered a [project utilizing TangNano 20k](https://github.com/ryomuk/TangNanoDCJ11MEM) and tried the FPGA code also with Yosys.

After some tinkering I discovered that currently synthesis doesn’t infer the MULT18x18 block in the DSP. As pointed out from Apicula’s Matrix channel, it is actually supported, but not yet “plugged in” during the synthesis.

So, [here’s my initial attempt](https://github.com/plaes/yosys/commit/b92cb6dadd4680485af0590a9c4a3442eff00838) at enabling the MULT36x36, MULT18x18 and MULT9x9 cells, which is one small step further. Though there are still some issues left:

1. Is the approach valid and dsp techmapping is done at proper location? (I initially struggled a lot because I initially tried inserting the techmap lookup after `synth -run coarse` step, but that failed to find the cells)
2. How to get techmap lookup select the optimal (ie smallest applicable) cell for it. Right now it selects 36x36 for 16 bit multiplication instead of 18x18.

---

<div class="post-metadata">

### Author: ![KrystalDelusion](https://avatars.discourse-cdn.com/v4/letter/k/8baadc/32.png) [@KrystalDelusion](https://yosyshq.discourse.group/u/KrystalDelusion)
#### Post date: [October 5, 2025, 9:22pm UTC](https://yosyshq.discourse.group/t/gowin-mapping-dsp-cells-mult36x36-mult18x18-and-mult9x9-during-synthesis/91/2 "2025-10-05T21:22:06Z")

</div>

Having a quick look at the existing [synth\_nexus](https://github.com/YosysHQ/yosys/blob/main/techlibs/nexus/synth_nexus.cc) pass, it seems they infer DSPs during the latter part of the `coarse` step (I think the important part is to run before `alumacc` gets called). It also looks like they set the min width for the larger DSPs to be greater than the max width for the smaller size:

```cpp
	struct DSPRule {
		int a_maxwidth;
		int b_maxwidth;
		int a_minwidth;
		int b_minwidth;
		std::string prim;
	};

	const std::vector<DSPRule> dsp_rules = {
		{36, 36, 22, 22, "$__NX_MUL36X36"},
		{36, 18, 22, 10, "$__NX_MUL36X18"},
		{18, 18, 10, 4, "$__NX_MUL18X18"},
		{18, 18, 4, 10, "$__NX_MUL18X18"},
		{ 9, 9, 4, 4, "$__NX_MUL9X9"},
	};

```

I’m guessing this prevents using (e.g.) 36x36 if it would have fit in an 18x18. I would also suggest using the same variable name as the flag, i.e. either `if ("-dsp") dsp=true`, or `if("-nodsp")` `nodsp=true`, rather than `if("-dsp") nodsp=false`. `synth_ice40` gives an example for using `-dsp`.

---

<div class="post-metadata">

### Author: ![plaes](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/plaes/32/27_2.png) [@plaes](https://yosyshq.discourse.group/u/plaes)
#### Post date: [October 7, 2025, 7:37pm UTC](https://yosyshq.discourse.group/t/gowin-mapping-dsp-cells-mult36x36-mult18x18-and-mult9x9-during-synthesis/91/3 "2025-10-07T19:37:20Z")

</div>

Thanks, I have create PR based on your hints: [gowin: dsp: Add basic DSP block inferencing for various MULT cells by plaes · Pull Request #5411 · YosysHQ/yosys · GitHub](https://github.com/YosysHQ/yosys/pull/5411)
