forgot to add submodules
[ieee754fpu.git] / src / add / fmul.py
1 from nmigen import Module, Signal, Cat, Mux, Array, Const
2 from nmigen.cli import main, verilog
3
4 from fpbase import FPNumIn, FPNumOut, FPOp, Overflow, FPBase
5 from nmigen_add_experiment import FPState
6
7 class FPMUL(FPBase):
8
9 def __init__(self, width):
10 FPBase.__init__(self)
11 self.width = width
12
13 self.in_a = FPOp(width)
14 self.in_b = FPOp(width)
15 self.out_z = FPOp(width)
16
17 def get_fragment(self, platform=None):
18 """ creates the HDL code-fragment for FPMUL
19 """
20 m = Module()
21
22 # Latches
23 a = FPNumIn(None, self.width, False)
24 b = FPNumIn(None, self.width, False)
25 z = FPNumOut(self.width, False)
26
27 mw = (z.m_width)*2 - 1 + 3 # sticky/round/guard bits + (2*mant) - 1
28 product = Signal(mw)
29
30 of = Overflow()
31 m.submodules.of = of
32 m.submodules.a = a
33 m.submodules.b = b
34 m.submodules.z = z
35
36 with m.FSM() as fsm:
37
38 # ******
39 # gets operand a
40
41 with m.State("get_a"):
42 self.get_op(m, self.in_a, a, "get_b")
43
44 # ******
45 # gets operand b
46
47 with m.State("get_b"):
48 self.get_op(m, self.in_b, b, "special_cases")
49
50 # ******
51 # special cases
52
53 with m.State("special_cases"):
54 #if a or b is NaN return NaN
55 with m.If(a.is_nan | b.is_nan):
56 m.next = "put_z"
57 m.d.sync += z.nan(1)
58 #if a is inf return inf
59 with m.Elif(a.is_inf):
60 m.next = "put_z"
61 m.d.sync += z.inf(a.s ^ b.s)
62 #if b is zero return NaN
63 with m.If(b.is_zero):
64 m.d.sync += z.nan(1)
65 #if b is inf return inf
66 with m.Elif(b.is_inf):
67 m.next = "put_z"
68 m.d.sync += z.inf(a.s ^ b.s)
69 #if a is zero return NaN
70 with m.If(a.is_zero):
71 m.next = "put_z"
72 m.d.sync += z.nan(1)
73 #if a is zero return zero
74 with m.Elif(a.is_zero):
75 m.next = "put_z"
76 m.d.sync += z.zero(a.s ^ b.s)
77 #if b is zero return zero
78 with m.Elif(b.is_zero):
79 m.next = "put_z"
80 m.d.sync += z.zero(a.s ^ b.s)
81 # Denormalised Number checks
82 with m.Else():
83 m.next = "normalise_a"
84 self.denormalise(m, a)
85 self.denormalise(m, b)
86
87 # ******
88 # normalise_a
89
90 with m.State("normalise_a"):
91 self.op_normalise(m, a, "normalise_b")
92
93 # ******
94 # normalise_b
95
96 with m.State("normalise_b"):
97 self.op_normalise(m, b, "multiply_0")
98
99 #multiply_0
100 with m.State("multiply_0"):
101 m.next = "multiply_1"
102 m.d.sync += [
103 z.s.eq(a.s ^ b.s),
104 z.e.eq(a.e + b.e + 1),
105 product.eq(a.m * b.m * 4)
106 ]
107
108 #multiply_1
109 with m.State("multiply_1"):
110 mw = z.m_width
111 m.next = "normalise_1"
112 m.d.sync += [
113 z.m.eq(product[mw+2:]),
114 of.guard.eq(product[mw+1]),
115 of.round_bit.eq(product[mw]),
116 of.sticky.eq(product[0:mw] != 0)
117 ]
118
119 # ******
120 # First stage of normalisation.
121 with m.State("normalise_1"):
122 self.normalise_1(m, z, of, "normalise_2")
123
124 # ******
125 # Second stage of normalisation.
126
127 with m.State("normalise_2"):
128 self.normalise_2(m, z, of, "round")
129
130 # ******
131 # rounding stage
132
133 with m.State("round"):
134 self.roundz(m, z, of.roundz)
135 m.next = "corrections"
136
137 # ******
138 # correction stage
139
140 with m.State("corrections"):
141 self.corrections(m, z, "pack")
142
143 # ******
144 # pack stage
145 with m.State("pack"):
146 self.pack(m, z, "put_z")
147
148 # ******
149 # put_z stage
150
151 with m.State("put_z"):
152 self.put_z(m, z, self.out_z, "get_a")
153
154 return m
155
156
157 if __name__ == "__main__":
158 alu = FPMUL(width=32)
159 main(alu, ports=alu.in_a.ports() + alu.in_b.ports() + alu.out_z.ports())