Source code for hwtLib.examples.arithmetic.multiplierBooth

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from hwt.code import If, Switch, Concat
from hwt.code_utils import rename_signal
from hwt.hdl.types.bits import Bits
from hwt.interfaces.agents.handshaked import HandshakedAgent
from hwt.interfaces.std import Handshaked, HandshakeSync, VectSignal
from hwt.interfaces.utils import addClkRstn
from hwt.math import log2ceil
from hwt.synthesizer.param import Param
from hwt.synthesizer.unit import Unit
from hwtSimApi.hdlSimulator import HdlSimulator


[docs]class TwoOperandsHsAgent(HandshakedAgent):
[docs] def get_data(self): i = self.intf return i.a.read(), i.b.read()
[docs] def set_data(self, data): if data is None: a = None b = None else: a, b = data i = self.intf i.a.write(a) i.b.write(b)
[docs]class TwoOperandsHs(Handshaked): def _declr(self): self.a = VectSignal(self.DATA_WIDTH) self.b = VectSignal(self.DATA_WIDTH) HandshakeSync._declr(self)
[docs] def _initSimAgent(self, sim:HdlSimulator): self._ag = TwoOperandsHsAgent(sim, self)
[docs]class MultiplierBooth(Unit): """ An implementation of Booth's multiplication algorithm .. figure:: ./_static/MultiplierBooth_fsm.png :attention: The input domain is limited to range specified bellow. .. code-block:: python max = 2 ** (DATA_WIDTH - 1) - 1 min = -1 * 2 ** (DATA_WIDTH - 1) .. hwt-autodoc:: """ def _config(self) -> None: self.DATA_WIDTH = Param(4) self.RESULT_WIDTH = Param(None) def _declr(self): if self.RESULT_WIDTH is None: self.RESULT_WIDTH = 2 * self.DATA_WIDTH addClkRstn(self) self.dataIn = TwoOperandsHs() self.dataIn.DATA_WIDTH = self.DATA_WIDTH self.dataOut = Handshaked()._m() self.dataOut.DATA_WIDTH = self.RESULT_WIDTH def _impl(self) -> None: start = self._sig("start") part_res_t = Bits(self.DATA_WIDTH) # High-order n bits of product a = self._reg("a", part_res_t) # multiplicand m = self._reg("m", part_res_t) # Initially holds multiplier, ultimately holds low-order n bits of product q = self._reg("q", part_res_t) # previous bit 0 of q q_1 = self._reg("q_1") din = self.dataIn dout = self.dataOut counter = self._reg( "counter", Bits(log2ceil(self.DATA_WIDTH + 1), signed=False), def_val=0) done = counter._eq(0) waitinOnConsumer = self._reg("waitinOnConsumer", def_val=0) add = rename_signal(self, (a + m)._signed(), "add") sub = rename_signal(self, (a - m)._signed(), "sub") If(start, a(0), m(din.a), q(din.b), q_1(0), counter(self.DATA_WIDTH), ).Elif(~done, Switch(Concat(q[0], q_1)) .Case(0b01, # add multiplicand to left half of product a(add >> 1), q(Concat(add[0], q[:1])), ).Case(0b10, # substract multiplicand from left half of product a(sub >> 1), q(Concat(sub[0], q[:1])), ).Default( a(a._signed() >> 1), q(Concat(a[0], q[:1])), ), q_1(q[0]), counter(counter - 1) ) If(start, waitinOnConsumer(1) ).Elif(done & dout.rd, waitinOnConsumer(0), ) dout.data(Concat(a, q)._vec()) dout.vld(done & waitinOnConsumer) start(din.vld & done & ~waitinOnConsumer) din.rd(done & ~waitinOnConsumer)
if __name__ == "__main__": from hwt.synthesizer.utils import to_rtl_str u = MultiplierBooth() print(to_rtl_str(u))