add msbhigh module
[ieee754fpu.git] / src / ieee754 / fpcommon / msbhigh.py
1 """ module for adjusting a mantissa and exponent so that the MSB is always 1
2 """
3
4 from nmigen import Module, Signal, Elaboratable
5 from nmigen.lib.coding import PriorityEncoder
6
7
8 class FPMSBHigh(Elaboratable):
9 """ makes the top mantissa bit hi (i.e. shifts until it is)
10
11 NOTE: this does NOT do any kind of checks. do not pass in
12 zero (empty) stuff, and it's best to check if the MSB is
13 already 1 before calling it. although it'll probably work
14 in both cases...
15
16 * exponent is signed
17 * mantissa is unsigned.
18
19 examples:
20 exp = -30, mantissa = 0b00011 - output: -33, 0b11000
21 exp = 2, mantissa = 0b01111 - output: 1, 0b11110
22 """
23 def __init__(self, m_width, e_width):
24 self.m_width = m_width
25 self.e_width = e_width
26
27 self.m_in = Signal(m_width, reset_less=True)
28 self.e_in = Signal((e_width, True), reset_less=True)
29 self.m_out = Signal(m_width, reset_less=True)
30 self.e_out = Signal((e_width, True), reset_less=True)
31
32 def elaborate(self, platform):
33 m = Module()
34
35 mwid = self.m_width
36 pe = PriorityEncoder(mwid)
37 m.submodules.pe = pe
38
39 # *sigh* not entirely obvious: count leading zeros (clz)
40 # with a PriorityEncoder: to find from the MSB
41 # we reverse the order of the bits.
42 temp = Signal(mwid, reset_less=True)
43 clz = Signal((len(self.e_out), True), reset_less=True)
44 m.d.comb += [
45 pe.i.eq(insel.m[::-1]), # inverted
46 clz.eq(pe.o), # count zeros from MSB down
47 temp.eq((self.m_in << clz)), # shift mantissa UP
48 self.e_out.eq(insel.e - clz), # DECREASE exponent
49 self.m_out.eq(temp),
50 ]
51