+class MultiShiftRMerge:
+ """ shifts down (right) and merges lower bits into m[0].
+ m[0] is the "sticky" bit, basically
+ """
+ def __init__(self, width, s_max=None):
+ if s_max is None:
+ s_max = int(log(width) / log(2))
+ self.smax = s_max
+ self.m = Signal(width, reset_less=True)
+ self.inp = Signal(width, reset_less=True)
+ self.diff = Signal(s_max, reset_less=True)
+ self.width = width
+
+ def elaborate(self, platform):
+ m = Module()
+
+ rs = Signal(self.width, reset_less=True)
+ m_mask = Signal(self.width, reset_less=True)
+ smask = Signal(self.width, reset_less=True)
+ stickybit = Signal(reset_less=True)
+ maxslen = Signal(self.smax, reset_less=True)
+ maxsleni = Signal(self.smax, reset_less=True)
+
+ sm = MultiShift(self.width-1)
+ m0s = Const(0, self.width-1)
+ mw = Const(self.width-1, len(self.diff))
+ m.d.comb += [maxslen.eq(Mux(self.diff > mw, mw, self.diff)),
+ maxsleni.eq(Mux(self.diff > mw, 0, mw-self.diff)),
+ ]
+
+ m.d.comb += [
+ # shift mantissa by maxslen, mask by inverse
+ rs.eq(sm.rshift(self.inp[1:], maxslen)),
+ m_mask.eq(sm.rshift(~m0s, maxsleni)),
+ smask.eq(self.inp[1:] & m_mask),
+ # sticky bit combines all mask (and mantissa low bit)
+ stickybit.eq(smask.bool() | self.inp[0]),
+ # mantissa result contains m[0] already.
+ self.m.eq(Cat(stickybit, rs))
+ ]
+ return m
+
+