Skip to content

New IR causes DSP inference issues with Quartus #1148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tpwrules opened this issue Feb 16, 2024 · 1 comment · Fixed by #1152
Closed

New IR causes DSP inference issues with Quartus #1148

tpwrules opened this issue Feb 16, 2024 · 1 comment · Fixed by #1152

Comments

@tpwrules
Copy link
Contributor

The following design (within the Details) infers 2 DSP blocks: Info (21062): Implemented 2 DSP elements.

from amaranth import *
from amaranth.lib import wiring
from amaranth.lib.wiring import In, Out

from amaranth_boards.de10_nano import DE10NanoPlatform

class DSPMACBlock(wiring.Component):
    # using signed 18x18->36 mode
    # https://www.intel.com/content/www/us/en/docs/programmable/683375/current/independent-multiplier-mode.html

    mul_a: In(signed(18)) # A input is 18 bits
    mul_b: In(signed(18)) # B input is 18 bits
    result: Out(signed(36)) # result is len(A)+len(B)

    def elaborate(self, platform):
        m = Module()

        m.d.sync += self.result.eq(self.mul_a * self.mul_b)

        return m

class Top(Elaboratable):
    def elaborate(self, platform):
        m = Module()

        m.submodules.mac = mac = DSPMACBlock()
        m.d.comb += [
            mac.mul_a.eq(Mux(platform.request("switch", 0).i, -1, 0)), # use all bits
            mac.mul_b.eq(Mux(platform.request("switch", 1).i, -1, 0)),
            platform.request("led", 0).o.eq(mac.result[-1])
        ]

        return m

if __name__ == "__main__":
    DE10NanoPlatform().build(Top())

Given that this is a supported DSP mode, I would expect this to infer only 1 block. This worked properly with the old IR. If I make both operands of the * signed by modifying line 107 of the generated Verilog (assign \$1 = ...) then correctly 1 block is inferred.

Not sure if there's any difference in functionality between the two scenarios.

Versions:

@whitequark
Copy link
Member

This worked properly with the old IR.

(Technically we use both IRs right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

2 participants