1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
, Cat
, Mux
6 from nmigen
.lib
.coding
import PriorityEncoder
7 from nmigen
.cli
import main
, verilog
9 from fpbase
import FPNumIn
, FPNumOut
, FPOp
, Overflow
, FPBase
, FPNumBase
10 from fpbase
import MultiShiftRMerge
, Trigger
11 #from fpbase import FPNumShiftMultiRight
13 class FPState(FPBase
):
14 def __init__(self
, state_from
):
15 self
.state_from
= state_from
17 def set_inputs(self
, inputs
):
19 for k
,v
in inputs
.items():
22 def set_outputs(self
, outputs
):
23 self
.outputs
= outputs
24 for k
,v
in outputs
.items():
29 def __init__(self
, width
):
30 self
.in_op
= FPOp(width
)
31 self
.out_op
= Signal(width
)
32 self
.out_decode
= Signal(reset_less
=True)
34 def elaborate(self
, platform
):
36 m
.d
.comb
+= self
.out_decode
.eq((self
.in_op
.ack
) & (self
.in_op
.stb
))
37 #m.submodules.get_op_in = self.in_op
38 m
.submodules
.get_op_out
= self
.out_op
39 with m
.If(self
.out_decode
):
41 self
.out_op
.eq(self
.in_op
.v
),
46 class FPGetOp(FPState
):
50 def __init__(self
, in_state
, out_state
, in_op
, width
):
51 FPState
.__init
__(self
, in_state
)
52 self
.out_state
= out_state
53 self
.mod
= FPGetOpMod(width
)
55 self
.out_op
= Signal(width
)
56 self
.out_decode
= Signal(reset_less
=True)
58 def setup(self
, m
, in_op
):
59 """ links module to inputs and outputs
61 setattr(m
.submodules
, self
.state_from
, self
.mod
)
62 m
.d
.comb
+= self
.mod
.in_op
.copy(in_op
)
63 #m.d.comb += self.out_op.eq(self.mod.out_op)
64 m
.d
.comb
+= self
.out_decode
.eq(self
.mod
.out_decode
)
67 with m
.If(self
.out_decode
):
68 m
.next
= self
.out_state
71 self
.out_op
.eq(self
.mod
.out_op
)
74 m
.d
.sync
+= self
.in_op
.ack
.eq(1)
77 class FPGet2OpMod(Trigger
):
78 def __init__(self
, width
):
79 Trigger
.__init
__(self
)
80 self
.in_op1
= Signal(width
, reset_less
=True)
81 self
.in_op2
= Signal(width
, reset_less
=True)
82 self
.out_op1
= FPNumIn(None, width
)
83 self
.out_op2
= FPNumIn(None, width
)
85 def elaborate(self
, platform
):
86 m
= Trigger
.elaborate(self
, platform
)
87 #m.submodules.get_op_in = self.in_op
88 m
.submodules
.get_op1_out
= self
.out_op1
89 m
.submodules
.get_op2_out
= self
.out_op2
90 with m
.If(self
.trigger
):
92 self
.out_op1
.decode(self
.in_op1
),
93 self
.out_op2
.decode(self
.in_op2
),
98 class FPGet2Op(FPState
):
102 def __init__(self
, in_state
, out_state
, in_op1
, in_op2
, width
):
103 FPState
.__init
__(self
, in_state
)
104 self
.out_state
= out_state
105 self
.mod
= FPGet2OpMod(width
)
108 self
.out_op1
= FPNumIn(None, width
)
109 self
.out_op2
= FPNumIn(None, width
)
110 self
.in_stb
= Signal(reset_less
=True)
111 self
.out_ack
= Signal(reset_less
=True)
112 self
.out_decode
= Signal(reset_less
=True)
114 def setup(self
, m
, in_op1
, in_op2
, in_stb
):
115 """ links module to inputs and outputs
117 m
.submodules
.get_ops
= self
.mod
118 m
.d
.comb
+= self
.mod
.in_op1
.eq(in_op1
)
119 m
.d
.comb
+= self
.mod
.in_op2
.eq(in_op2
)
120 m
.d
.comb
+= self
.mod
.stb
.eq(in_stb
)
121 m
.d
.comb
+= self
.out_ack
.eq(self
.mod
.ack
)
122 m
.d
.comb
+= self
.out_decode
.eq(self
.mod
.trigger
)
123 #m.d.comb += self.out_op1.v.eq(self.mod.out_op1.v)
124 #m.d.comb += self.out_op2.v.eq(self.mod.out_op2.v)
127 with m
.If(self
.out_decode
):
128 m
.next
= self
.out_state
131 #self.out_op1.v.eq(self.mod.out_op1.v),
132 #self.out_op2.v.eq(self.mod.out_op2.v),
133 self
.out_op1
.copy(self
.mod
.out_op1
),
134 self
.out_op2
.copy(self
.mod
.out_op2
)
137 m
.d
.sync
+= self
.mod
.ack
.eq(1)
140 class FPAddSpecialCasesMod
:
141 """ special cases: NaNs, infs, zeros, denormalised
142 NOTE: some of these are unique to add. see "Special Operations"
143 https://steve.hollasch.net/cgindex/coding/ieeefloat.html
146 def __init__(self
, width
):
147 self
.in_a
= FPNumBase(width
)
148 self
.in_b
= FPNumBase(width
)
149 self
.out_z
= FPNumOut(width
, False)
150 self
.out_do_z
= Signal(reset_less
=True)
152 def elaborate(self
, platform
):
155 m
.submodules
.sc_in_a
= self
.in_a
156 m
.submodules
.sc_in_b
= self
.in_b
157 m
.submodules
.sc_out_z
= self
.out_z
160 m
.d
.comb
+= s_nomatch
.eq(self
.in_a
.s
!= self
.in_b
.s
)
163 m
.d
.comb
+= m_match
.eq(self
.in_a
.m
== self
.in_b
.m
)
165 # if a is NaN or b is NaN return NaN
166 with m
.If(self
.in_a
.is_nan | self
.in_b
.is_nan
):
167 m
.d
.comb
+= self
.out_do_z
.eq(1)
168 m
.d
.comb
+= self
.out_z
.nan(0)
170 # XXX WEIRDNESS for FP16 non-canonical NaN handling
173 ## if a is zero and b is NaN return -b
174 #with m.If(a.is_zero & (a.s==0) & b.is_nan):
175 # m.d.comb += self.out_do_z.eq(1)
176 # m.d.comb += z.create(b.s, b.e, Cat(b.m[3:-2], ~b.m[0]))
178 ## if b is zero and a is NaN return -a
179 #with m.Elif(b.is_zero & (b.s==0) & a.is_nan):
180 # m.d.comb += self.out_do_z.eq(1)
181 # m.d.comb += z.create(a.s, a.e, Cat(a.m[3:-2], ~a.m[0]))
183 ## if a is -zero and b is NaN return -b
184 #with m.Elif(a.is_zero & (a.s==1) & b.is_nan):
185 # m.d.comb += self.out_do_z.eq(1)
186 # m.d.comb += z.create(a.s & b.s, b.e, Cat(b.m[3:-2], 1))
188 ## if b is -zero and a is NaN return -a
189 #with m.Elif(b.is_zero & (b.s==1) & a.is_nan):
190 # m.d.comb += self.out_do_z.eq(1)
191 # m.d.comb += z.create(a.s & b.s, a.e, Cat(a.m[3:-2], 1))
193 # if a is inf return inf (or NaN)
194 with m
.Elif(self
.in_a
.is_inf
):
195 m
.d
.comb
+= self
.out_do_z
.eq(1)
196 m
.d
.comb
+= self
.out_z
.inf(self
.in_a
.s
)
197 # if a is inf and signs don't match return NaN
198 with m
.If(self
.in_b
.exp_128
& s_nomatch
):
199 m
.d
.comb
+= self
.out_z
.nan(0)
201 # if b is inf return inf
202 with m
.Elif(self
.in_b
.is_inf
):
203 m
.d
.comb
+= self
.out_do_z
.eq(1)
204 m
.d
.comb
+= self
.out_z
.inf(self
.in_b
.s
)
206 # if a is zero and b zero return signed-a/b
207 with m
.Elif(self
.in_a
.is_zero
& self
.in_b
.is_zero
):
208 m
.d
.comb
+= self
.out_do_z
.eq(1)
209 m
.d
.comb
+= self
.out_z
.create(self
.in_a
.s
& self
.in_b
.s
,
213 # if a is zero return b
214 with m
.Elif(self
.in_a
.is_zero
):
215 m
.d
.comb
+= self
.out_do_z
.eq(1)
216 m
.d
.comb
+= self
.out_z
.create(self
.in_b
.s
, self
.in_b
.e
,
219 # if b is zero return a
220 with m
.Elif(self
.in_b
.is_zero
):
221 m
.d
.comb
+= self
.out_do_z
.eq(1)
222 m
.d
.comb
+= self
.out_z
.create(self
.in_a
.s
, self
.in_a
.e
,
225 # if a equal to -b return zero (+ve zero)
226 with m
.Elif(s_nomatch
& m_match
& (self
.in_a
.e
== self
.in_b
.e
)):
227 m
.d
.comb
+= self
.out_do_z
.eq(1)
228 m
.d
.comb
+= self
.out_z
.zero(0)
230 # Denormalised Number checks
232 m
.d
.comb
+= self
.out_do_z
.eq(0)
238 def __init__(self
, id_wid
):
241 self
.in_mid
= Signal(id_wid
, reset_less
=True)
242 self
.out_mid
= Signal(id_wid
, reset_less
=True)
248 if self
.id_wid
is not None:
249 m
.d
.sync
+= self
.out_mid
.eq(self
.in_mid
)
252 class FPAddSpecialCases(FPState
, FPID
):
253 """ special cases: NaNs, infs, zeros, denormalised
254 NOTE: some of these are unique to add. see "Special Operations"
255 https://steve.hollasch.net/cgindex/coding/ieeefloat.html
258 def __init__(self
, width
, id_wid
):
259 FPState
.__init
__(self
, "special_cases")
260 FPID
.__init
__(self
, id_wid
)
261 self
.mod
= FPAddSpecialCasesMod(width
)
262 self
.out_z
= FPNumOut(width
, False)
263 self
.out_do_z
= Signal(reset_less
=True)
265 def setup(self
, m
, in_a
, in_b
, in_mid
):
266 """ links module to inputs and outputs
268 m
.submodules
.specialcases
= self
.mod
269 m
.d
.comb
+= self
.mod
.in_a
.copy(in_a
)
270 m
.d
.comb
+= self
.mod
.in_b
.copy(in_b
)
271 #m.d.comb += self.out_z.v.eq(self.mod.out_z.v)
272 m
.d
.comb
+= self
.out_do_z
.eq(self
.mod
.out_do_z
)
273 if self
.in_mid
is not None:
274 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
278 with m
.If(self
.out_do_z
):
279 m
.d
.sync
+= self
.out_z
.v
.eq(self
.mod
.out_z
.v
) # only take the output
282 m
.next
= "denormalise"
285 class FPAddDeNormMod(FPState
):
287 def __init__(self
, width
):
288 self
.in_a
= FPNumBase(width
)
289 self
.in_b
= FPNumBase(width
)
290 self
.out_a
= FPNumBase(width
)
291 self
.out_b
= FPNumBase(width
)
293 def elaborate(self
, platform
):
295 m
.submodules
.denorm_in_a
= self
.in_a
296 m
.submodules
.denorm_in_b
= self
.in_b
297 m
.submodules
.denorm_out_a
= self
.out_a
298 m
.submodules
.denorm_out_b
= self
.out_b
299 # hmmm, don't like repeating identical code
300 m
.d
.comb
+= self
.out_a
.copy(self
.in_a
)
301 with m
.If(self
.in_a
.exp_n127
):
302 m
.d
.comb
+= self
.out_a
.e
.eq(self
.in_a
.N126
) # limit a exponent
304 m
.d
.comb
+= self
.out_a
.m
[-1].eq(1) # set top mantissa bit
306 m
.d
.comb
+= self
.out_b
.copy(self
.in_b
)
307 with m
.If(self
.in_b
.exp_n127
):
308 m
.d
.comb
+= self
.out_b
.e
.eq(self
.in_b
.N126
) # limit a exponent
310 m
.d
.comb
+= self
.out_b
.m
[-1].eq(1) # set top mantissa bit
315 class FPAddDeNorm(FPState
, FPID
):
317 def __init__(self
, width
, id_wid
):
318 FPState
.__init
__(self
, "denormalise")
319 FPID
.__init
__(self
, id_wid
)
320 self
.mod
= FPAddDeNormMod(width
)
321 self
.out_a
= FPNumBase(width
)
322 self
.out_b
= FPNumBase(width
)
324 def setup(self
, m
, in_a
, in_b
, in_mid
):
325 """ links module to inputs and outputs
327 m
.submodules
.denormalise
= self
.mod
328 m
.d
.comb
+= self
.mod
.in_a
.copy(in_a
)
329 m
.d
.comb
+= self
.mod
.in_b
.copy(in_b
)
330 if self
.in_mid
is not None:
331 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
335 # Denormalised Number checks
337 m
.d
.sync
+= self
.out_a
.copy(self
.mod
.out_a
)
338 m
.d
.sync
+= self
.out_b
.copy(self
.mod
.out_b
)
341 class FPAddAlignMultiMod(FPState
):
343 def __init__(self
, width
):
344 self
.in_a
= FPNumBase(width
)
345 self
.in_b
= FPNumBase(width
)
346 self
.out_a
= FPNumIn(None, width
)
347 self
.out_b
= FPNumIn(None, width
)
348 self
.exp_eq
= Signal(reset_less
=True)
350 def elaborate(self
, platform
):
351 # This one however (single-cycle) will do the shift
356 m
.submodules
.align_in_a
= self
.in_a
357 m
.submodules
.align_in_b
= self
.in_b
358 m
.submodules
.align_out_a
= self
.out_a
359 m
.submodules
.align_out_b
= self
.out_b
361 # NOTE: this does *not* do single-cycle multi-shifting,
362 # it *STAYS* in the align state until exponents match
364 # exponent of a greater than b: shift b down
365 m
.d
.comb
+= self
.exp_eq
.eq(0)
366 m
.d
.comb
+= self
.out_a
.copy(self
.in_a
)
367 m
.d
.comb
+= self
.out_b
.copy(self
.in_b
)
368 agtb
= Signal(reset_less
=True)
369 altb
= Signal(reset_less
=True)
370 m
.d
.comb
+= agtb
.eq(self
.in_a
.e
> self
.in_b
.e
)
371 m
.d
.comb
+= altb
.eq(self
.in_a
.e
< self
.in_b
.e
)
373 m
.d
.comb
+= self
.out_b
.shift_down(self
.in_b
)
374 # exponent of b greater than a: shift a down
376 m
.d
.comb
+= self
.out_a
.shift_down(self
.in_a
)
377 # exponents equal: move to next stage.
379 m
.d
.comb
+= self
.exp_eq
.eq(1)
383 class FPAddAlignMulti(FPState
, FPID
):
385 def __init__(self
, width
, id_wid
):
386 FPID
.__init
__(self
, id_wid
)
387 FPState
.__init
__(self
, "align")
388 self
.mod
= FPAddAlignMultiMod(width
)
389 self
.out_a
= FPNumIn(None, width
)
390 self
.out_b
= FPNumIn(None, width
)
391 self
.exp_eq
= Signal(reset_less
=True)
393 def setup(self
, m
, in_a
, in_b
, in_mid
):
394 """ links module to inputs and outputs
396 m
.submodules
.align
= self
.mod
397 m
.d
.comb
+= self
.mod
.in_a
.copy(in_a
)
398 m
.d
.comb
+= self
.mod
.in_b
.copy(in_b
)
399 #m.d.comb += self.out_a.copy(self.mod.out_a)
400 #m.d.comb += self.out_b.copy(self.mod.out_b)
401 m
.d
.comb
+= self
.exp_eq
.eq(self
.mod
.exp_eq
)
402 if self
.in_mid
is not None:
403 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
407 m
.d
.sync
+= self
.out_a
.copy(self
.mod
.out_a
)
408 m
.d
.sync
+= self
.out_b
.copy(self
.mod
.out_b
)
409 with m
.If(self
.exp_eq
):
413 class FPAddAlignSingleMod
:
415 def __init__(self
, width
):
417 self
.in_a
= FPNumBase(width
)
418 self
.in_b
= FPNumBase(width
)
419 self
.out_a
= FPNumIn(None, width
)
420 self
.out_b
= FPNumIn(None, width
)
422 def elaborate(self
, platform
):
423 """ Aligns A against B or B against A, depending on which has the
424 greater exponent. This is done in a *single* cycle using
425 variable-width bit-shift
427 the shifter used here is quite expensive in terms of gates.
428 Mux A or B in (and out) into temporaries, as only one of them
429 needs to be aligned against the other
433 m
.submodules
.align_in_a
= self
.in_a
434 m
.submodules
.align_in_b
= self
.in_b
435 m
.submodules
.align_out_a
= self
.out_a
436 m
.submodules
.align_out_b
= self
.out_b
438 # temporary (muxed) input and output to be shifted
439 t_inp
= FPNumBase(self
.width
)
440 t_out
= FPNumIn(None, self
.width
)
441 espec
= (len(self
.in_a
.e
), True)
442 msr
= MultiShiftRMerge(self
.in_a
.m_width
, espec
)
443 m
.submodules
.align_t_in
= t_inp
444 m
.submodules
.align_t_out
= t_out
445 m
.submodules
.multishift_r
= msr
447 ediff
= Signal(espec
, reset_less
=True)
448 ediffr
= Signal(espec
, reset_less
=True)
449 tdiff
= Signal(espec
, reset_less
=True)
450 elz
= Signal(reset_less
=True)
451 egz
= Signal(reset_less
=True)
453 # connect multi-shifter to t_inp/out mantissa (and tdiff)
454 m
.d
.comb
+= msr
.inp
.eq(t_inp
.m
)
455 m
.d
.comb
+= msr
.diff
.eq(tdiff
)
456 m
.d
.comb
+= t_out
.m
.eq(msr
.m
)
457 m
.d
.comb
+= t_out
.e
.eq(t_inp
.e
+ tdiff
)
458 m
.d
.comb
+= t_out
.s
.eq(t_inp
.s
)
460 m
.d
.comb
+= ediff
.eq(self
.in_a
.e
- self
.in_b
.e
)
461 m
.d
.comb
+= ediffr
.eq(self
.in_b
.e
- self
.in_a
.e
)
462 m
.d
.comb
+= elz
.eq(self
.in_a
.e
< self
.in_b
.e
)
463 m
.d
.comb
+= egz
.eq(self
.in_a
.e
> self
.in_b
.e
)
465 # default: A-exp == B-exp, A and B untouched (fall through)
466 m
.d
.comb
+= self
.out_a
.copy(self
.in_a
)
467 m
.d
.comb
+= self
.out_b
.copy(self
.in_b
)
468 # only one shifter (muxed)
469 #m.d.comb += t_out.shift_down_multi(tdiff, t_inp)
470 # exponent of a greater than b: shift b down
472 m
.d
.comb
+= [t_inp
.copy(self
.in_b
),
474 self
.out_b
.copy(t_out
),
475 self
.out_b
.s
.eq(self
.in_b
.s
), # whoops forgot sign
477 # exponent of b greater than a: shift a down
479 m
.d
.comb
+= [t_inp
.copy(self
.in_a
),
481 self
.out_a
.copy(t_out
),
482 self
.out_a
.s
.eq(self
.in_a
.s
), # whoops forgot sign
487 class FPAddAlignSingle(FPState
, FPID
):
489 def __init__(self
, width
, id_wid
):
490 FPState
.__init
__(self
, "align")
491 FPID
.__init
__(self
, id_wid
)
492 self
.mod
= FPAddAlignSingleMod(width
)
493 self
.out_a
= FPNumIn(None, width
)
494 self
.out_b
= FPNumIn(None, width
)
496 def setup(self
, m
, in_a
, in_b
, in_mid
):
497 """ links module to inputs and outputs
499 m
.submodules
.align
= self
.mod
500 m
.d
.comb
+= self
.mod
.in_a
.copy(in_a
)
501 m
.d
.comb
+= self
.mod
.in_b
.copy(in_b
)
502 if self
.in_mid
is not None:
503 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
507 # NOTE: could be done as comb
508 m
.d
.sync
+= self
.out_a
.copy(self
.mod
.out_a
)
509 m
.d
.sync
+= self
.out_b
.copy(self
.mod
.out_b
)
513 class FPAddStage0Mod
:
515 def __init__(self
, width
):
516 self
.in_a
= FPNumBase(width
)
517 self
.in_b
= FPNumBase(width
)
518 self
.in_z
= FPNumBase(width
, False)
519 self
.out_z
= FPNumBase(width
, False)
520 self
.out_tot
= Signal(self
.out_z
.m_width
+ 4, reset_less
=True)
522 def elaborate(self
, platform
):
524 m
.submodules
.add0_in_a
= self
.in_a
525 m
.submodules
.add0_in_b
= self
.in_b
526 m
.submodules
.add0_out_z
= self
.out_z
528 m
.d
.comb
+= self
.out_z
.e
.eq(self
.in_a
.e
)
530 # store intermediate tests (and zero-extended mantissas)
531 seq
= Signal(reset_less
=True)
532 mge
= Signal(reset_less
=True)
533 am0
= Signal(len(self
.in_a
.m
)+1, reset_less
=True)
534 bm0
= Signal(len(self
.in_b
.m
)+1, reset_less
=True)
535 m
.d
.comb
+= [seq
.eq(self
.in_a
.s
== self
.in_b
.s
),
536 mge
.eq(self
.in_a
.m
>= self
.in_b
.m
),
537 am0
.eq(Cat(self
.in_a
.m
, 0)),
538 bm0
.eq(Cat(self
.in_b
.m
, 0))
540 # same-sign (both negative or both positive) add mantissas
543 self
.out_tot
.eq(am0
+ bm0
),
544 self
.out_z
.s
.eq(self
.in_a
.s
)
546 # a mantissa greater than b, use a
549 self
.out_tot
.eq(am0
- bm0
),
550 self
.out_z
.s
.eq(self
.in_a
.s
)
552 # b mantissa greater than a, use b
555 self
.out_tot
.eq(bm0
- am0
),
556 self
.out_z
.s
.eq(self
.in_b
.s
)
561 class FPAddStage0(FPState
, FPID
):
562 """ First stage of add. covers same-sign (add) and subtract
563 special-casing when mantissas are greater or equal, to
564 give greatest accuracy.
567 def __init__(self
, width
, id_wid
):
568 FPState
.__init
__(self
, "add_0")
569 FPID
.__init
__(self
, id_wid
)
570 self
.mod
= FPAddStage0Mod(width
)
571 self
.out_z
= FPNumBase(width
, False)
572 self
.out_tot
= Signal(self
.out_z
.m_width
+ 4, reset_less
=True)
574 def setup(self
, m
, in_a
, in_b
, in_mid
):
575 """ links module to inputs and outputs
577 m
.submodules
.add0
= self
.mod
578 m
.d
.comb
+= self
.mod
.in_a
.copy(in_a
)
579 m
.d
.comb
+= self
.mod
.in_b
.copy(in_b
)
580 if self
.in_mid
is not None:
581 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
585 # NOTE: these could be done as combinatorial (merge add0+add1)
586 m
.d
.sync
+= self
.out_z
.copy(self
.mod
.out_z
)
587 m
.d
.sync
+= self
.out_tot
.eq(self
.mod
.out_tot
)
591 class FPAddStage1Mod(FPState
):
592 """ Second stage of add: preparation for normalisation.
593 detects when tot sum is too big (tot[27] is kinda a carry bit)
596 def __init__(self
, width
):
597 self
.out_norm
= Signal(reset_less
=True)
598 self
.in_z
= FPNumBase(width
, False)
599 self
.in_tot
= Signal(self
.in_z
.m_width
+ 4, reset_less
=True)
600 self
.out_z
= FPNumBase(width
, False)
601 self
.out_of
= Overflow()
603 def elaborate(self
, platform
):
605 #m.submodules.norm1_in_overflow = self.in_of
606 #m.submodules.norm1_out_overflow = self.out_of
607 #m.submodules.norm1_in_z = self.in_z
608 #m.submodules.norm1_out_z = self.out_z
609 m
.d
.comb
+= self
.out_z
.copy(self
.in_z
)
610 # tot[27] gets set when the sum overflows. shift result down
611 with m
.If(self
.in_tot
[-1]):
613 self
.out_z
.m
.eq(self
.in_tot
[4:]),
614 self
.out_of
.m0
.eq(self
.in_tot
[4]),
615 self
.out_of
.guard
.eq(self
.in_tot
[3]),
616 self
.out_of
.round_bit
.eq(self
.in_tot
[2]),
617 self
.out_of
.sticky
.eq(self
.in_tot
[1] | self
.in_tot
[0]),
618 self
.out_z
.e
.eq(self
.in_z
.e
+ 1)
623 self
.out_z
.m
.eq(self
.in_tot
[3:]),
624 self
.out_of
.m0
.eq(self
.in_tot
[3]),
625 self
.out_of
.guard
.eq(self
.in_tot
[2]),
626 self
.out_of
.round_bit
.eq(self
.in_tot
[1]),
627 self
.out_of
.sticky
.eq(self
.in_tot
[0])
632 class FPAddStage1(FPState
, FPID
):
634 def __init__(self
, width
, id_wid
):
635 FPState
.__init
__(self
, "add_1")
636 FPID
.__init
__(self
, id_wid
)
637 self
.mod
= FPAddStage1Mod(width
)
638 self
.out_z
= FPNumBase(width
, False)
639 self
.out_of
= Overflow()
640 self
.norm_stb
= Signal()
642 def setup(self
, m
, in_tot
, in_z
, in_mid
):
643 """ links module to inputs and outputs
645 m
.submodules
.add1
= self
.mod
646 m
.submodules
.add1_out_overflow
= self
.out_of
648 m
.d
.comb
+= self
.mod
.in_z
.copy(in_z
)
649 m
.d
.comb
+= self
.mod
.in_tot
.eq(in_tot
)
651 m
.d
.sync
+= self
.norm_stb
.eq(0) # sets to zero when not in add1 state
653 if self
.in_mid
is not None:
654 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
658 m
.d
.sync
+= self
.out_of
.copy(self
.mod
.out_of
)
659 m
.d
.sync
+= self
.out_z
.copy(self
.mod
.out_z
)
660 m
.d
.sync
+= self
.norm_stb
.eq(1)
661 m
.next
= "normalise_1"
664 class FPNorm1ModSingle
:
666 def __init__(self
, width
):
668 self
.in_select
= Signal(reset_less
=True)
669 self
.out_norm
= Signal(reset_less
=True)
670 self
.in_z
= FPNumBase(width
, False)
671 self
.in_of
= Overflow()
672 self
.temp_z
= FPNumBase(width
, False)
673 self
.temp_of
= Overflow()
674 self
.out_z
= FPNumBase(width
, False)
675 self
.out_of
= Overflow()
677 def elaborate(self
, platform
):
680 mwid
= self
.out_z
.m_width
+2
681 pe
= PriorityEncoder(mwid
)
682 m
.submodules
.norm_pe
= pe
684 m
.submodules
.norm1_out_z
= self
.out_z
685 m
.submodules
.norm1_out_overflow
= self
.out_of
686 m
.submodules
.norm1_temp_z
= self
.temp_z
687 m
.submodules
.norm1_temp_of
= self
.temp_of
688 m
.submodules
.norm1_in_z
= self
.in_z
689 m
.submodules
.norm1_in_overflow
= self
.in_of
691 in_z
= FPNumBase(self
.width
, False)
693 m
.submodules
.norm1_insel_z
= in_z
694 m
.submodules
.norm1_insel_overflow
= in_of
696 espec
= (len(in_z
.e
), True)
697 ediff_n126
= Signal(espec
, reset_less
=True)
698 msr
= MultiShiftRMerge(mwid
, espec
)
699 m
.submodules
.multishift_r
= msr
701 # select which of temp or in z/of to use
702 with m
.If(self
.in_select
):
703 m
.d
.comb
+= in_z
.copy(self
.in_z
)
704 m
.d
.comb
+= in_of
.copy(self
.in_of
)
706 m
.d
.comb
+= in_z
.copy(self
.temp_z
)
707 m
.d
.comb
+= in_of
.copy(self
.temp_of
)
708 # initialise out from in (overridden below)
709 m
.d
.comb
+= self
.out_z
.copy(in_z
)
710 m
.d
.comb
+= self
.out_of
.copy(in_of
)
711 # normalisation increase/decrease conditions
712 decrease
= Signal(reset_less
=True)
713 increase
= Signal(reset_less
=True)
714 m
.d
.comb
+= decrease
.eq(in_z
.m_msbzero
& in_z
.exp_gt_n126
)
715 m
.d
.comb
+= increase
.eq(in_z
.exp_lt_n126
)
716 m
.d
.comb
+= self
.out_norm
.eq(0) # loop-end condition
719 # *sigh* not entirely obvious: count leading zeros (clz)
720 # with a PriorityEncoder: to find from the MSB
721 # we reverse the order of the bits.
722 temp_m
= Signal(mwid
, reset_less
=True)
723 temp_s
= Signal(mwid
+1, reset_less
=True)
724 clz
= Signal((len(in_z
.e
), True), reset_less
=True)
725 # make sure that the amount to decrease by does NOT
726 # go below the minimum non-INF/NaN exponent
727 limclz
= Mux(in_z
.exp_sub_n126
> pe
.o
, pe
.o
,
730 # cat round and guard bits back into the mantissa
731 temp_m
.eq(Cat(in_of
.round_bit
, in_of
.guard
, in_z
.m
)),
732 pe
.i
.eq(temp_m
[::-1]), # inverted
733 clz
.eq(limclz
), # count zeros from MSB down
734 temp_s
.eq(temp_m
<< clz
), # shift mantissa UP
735 self
.out_z
.e
.eq(in_z
.e
- clz
), # DECREASE exponent
736 self
.out_z
.m
.eq(temp_s
[2:]), # exclude bits 0&1
737 self
.out_of
.m0
.eq(temp_s
[2]), # copy of mantissa[0]
738 # overflow in bits 0..1: got shifted too (leave sticky)
739 self
.out_of
.guard
.eq(temp_s
[1]), # guard
740 self
.out_of
.round_bit
.eq(temp_s
[0]), # round
743 with m
.Elif(increase
):
744 temp_m
= Signal(mwid
+1, reset_less
=True)
746 temp_m
.eq(Cat(in_of
.sticky
, in_of
.round_bit
, in_of
.guard
,
748 ediff_n126
.eq(in_z
.N126
- in_z
.e
),
749 # connect multi-shifter to inp/out mantissa (and ediff)
751 msr
.diff
.eq(ediff_n126
),
752 self
.out_z
.m
.eq(msr
.m
[3:]),
753 self
.out_of
.m0
.eq(temp_s
[3]), # copy of mantissa[0]
754 # overflow in bits 0..1: got shifted too (leave sticky)
755 self
.out_of
.guard
.eq(temp_s
[2]), # guard
756 self
.out_of
.round_bit
.eq(temp_s
[1]), # round
757 self
.out_of
.sticky
.eq(temp_s
[0]), # sticky
758 self
.out_z
.e
.eq(in_z
.e
+ ediff_n126
),
764 class FPNorm1ModMulti
:
766 def __init__(self
, width
, single_cycle
=True):
768 self
.in_select
= Signal(reset_less
=True)
769 self
.out_norm
= Signal(reset_less
=True)
770 self
.in_z
= FPNumBase(width
, False)
771 self
.in_of
= Overflow()
772 self
.temp_z
= FPNumBase(width
, False)
773 self
.temp_of
= Overflow()
774 self
.out_z
= FPNumBase(width
, False)
775 self
.out_of
= Overflow()
777 def elaborate(self
, platform
):
780 m
.submodules
.norm1_out_z
= self
.out_z
781 m
.submodules
.norm1_out_overflow
= self
.out_of
782 m
.submodules
.norm1_temp_z
= self
.temp_z
783 m
.submodules
.norm1_temp_of
= self
.temp_of
784 m
.submodules
.norm1_in_z
= self
.in_z
785 m
.submodules
.norm1_in_overflow
= self
.in_of
787 in_z
= FPNumBase(self
.width
, False)
789 m
.submodules
.norm1_insel_z
= in_z
790 m
.submodules
.norm1_insel_overflow
= in_of
792 # select which of temp or in z/of to use
793 with m
.If(self
.in_select
):
794 m
.d
.comb
+= in_z
.copy(self
.in_z
)
795 m
.d
.comb
+= in_of
.copy(self
.in_of
)
797 m
.d
.comb
+= in_z
.copy(self
.temp_z
)
798 m
.d
.comb
+= in_of
.copy(self
.temp_of
)
799 # initialise out from in (overridden below)
800 m
.d
.comb
+= self
.out_z
.copy(in_z
)
801 m
.d
.comb
+= self
.out_of
.copy(in_of
)
802 # normalisation increase/decrease conditions
803 decrease
= Signal(reset_less
=True)
804 increase
= Signal(reset_less
=True)
805 m
.d
.comb
+= decrease
.eq(in_z
.m_msbzero
& in_z
.exp_gt_n126
)
806 m
.d
.comb
+= increase
.eq(in_z
.exp_lt_n126
)
807 m
.d
.comb
+= self
.out_norm
.eq(decrease | increase
) # loop-end
811 self
.out_z
.e
.eq(in_z
.e
- 1), # DECREASE exponent
812 self
.out_z
.m
.eq(in_z
.m
<< 1), # shift mantissa UP
813 self
.out_z
.m
[0].eq(in_of
.guard
), # steal guard (was tot[2])
814 self
.out_of
.guard
.eq(in_of
.round_bit
), # round (was tot[1])
815 self
.out_of
.round_bit
.eq(0), # reset round bit
816 self
.out_of
.m0
.eq(in_of
.guard
),
819 with m
.Elif(increase
):
821 self
.out_z
.e
.eq(in_z
.e
+ 1), # INCREASE exponent
822 self
.out_z
.m
.eq(in_z
.m
>> 1), # shift mantissa DOWN
823 self
.out_of
.guard
.eq(in_z
.m
[0]),
824 self
.out_of
.m0
.eq(in_z
.m
[1]),
825 self
.out_of
.round_bit
.eq(in_of
.guard
),
826 self
.out_of
.sticky
.eq(in_of
.sticky | in_of
.round_bit
)
832 class FPNorm1(FPState
, FPID
):
834 def __init__(self
, width
, id_wid
, single_cycle
=True):
835 FPID
.__init
__(self
, id_wid
)
836 FPState
.__init
__(self
, "normalise_1")
838 self
.mod
= FPNorm1ModSingle(width
)
840 self
.mod
= FPNorm1ModMulti(width
)
841 self
.stb
= Signal(reset_less
=True)
842 self
.ack
= Signal(reset
=0, reset_less
=True)
843 self
.out_norm
= Signal(reset_less
=True)
844 self
.in_accept
= Signal(reset_less
=True)
845 self
.temp_z
= FPNumBase(width
)
846 self
.temp_of
= Overflow()
847 self
.out_z
= FPNumBase(width
)
848 self
.out_roundz
= Signal(reset_less
=True)
850 def setup(self
, m
, in_z
, in_of
, norm_stb
, in_mid
):
851 """ links module to inputs and outputs
853 m
.submodules
.normalise_1
= self
.mod
855 m
.d
.comb
+= self
.mod
.in_z
.copy(in_z
)
856 m
.d
.comb
+= self
.mod
.in_of
.copy(in_of
)
858 m
.d
.comb
+= self
.mod
.in_select
.eq(self
.in_accept
)
859 m
.d
.comb
+= self
.mod
.temp_z
.copy(self
.temp_z
)
860 m
.d
.comb
+= self
.mod
.temp_of
.copy(self
.temp_of
)
862 m
.d
.comb
+= self
.out_z
.copy(self
.mod
.out_z
)
863 m
.d
.comb
+= self
.out_norm
.eq(self
.mod
.out_norm
)
865 m
.d
.comb
+= self
.stb
.eq(norm_stb
)
866 m
.d
.sync
+= self
.ack
.eq(0) # sets to zero when not in normalise_1 state
868 if self
.in_mid
is not None:
869 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
873 m
.d
.comb
+= self
.in_accept
.eq((~self
.ack
) & (self
.stb
))
874 m
.d
.sync
+= self
.temp_of
.copy(self
.mod
.out_of
)
875 m
.d
.sync
+= self
.temp_z
.copy(self
.out_z
)
876 with m
.If(self
.out_norm
):
877 with m
.If(self
.in_accept
):
882 m
.d
.sync
+= self
.ack
.eq(0)
884 # normalisation not required (or done).
886 m
.d
.sync
+= self
.ack
.eq(1)
887 m
.d
.sync
+= self
.out_roundz
.eq(self
.mod
.out_of
.roundz
)
892 def __init__(self
, width
):
893 self
.in_roundz
= Signal(reset_less
=True)
894 self
.in_z
= FPNumBase(width
, False)
895 self
.out_z
= FPNumBase(width
, False)
897 def elaborate(self
, platform
):
899 m
.d
.comb
+= self
.out_z
.copy(self
.in_z
)
900 with m
.If(self
.in_roundz
):
901 m
.d
.comb
+= self
.out_z
.m
.eq(self
.in_z
.m
+ 1) # mantissa rounds up
902 with m
.If(self
.in_z
.m
== self
.in_z
.m1s
): # all 1s
903 m
.d
.comb
+= self
.out_z
.e
.eq(self
.in_z
.e
+ 1) # exponent up
907 class FPRound(FPState
, FPID
):
909 def __init__(self
, width
, id_wid
):
910 FPState
.__init
__(self
, "round")
911 FPID
.__init
__(self
, id_wid
)
912 self
.mod
= FPRoundMod(width
)
913 self
.out_z
= FPNumBase(width
)
915 def setup(self
, m
, in_z
, roundz
, in_mid
):
916 """ links module to inputs and outputs
918 m
.submodules
.roundz
= self
.mod
920 m
.d
.comb
+= self
.mod
.in_z
.copy(in_z
)
921 m
.d
.comb
+= self
.mod
.in_roundz
.eq(roundz
)
922 if self
.in_mid
is not None:
923 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
927 m
.d
.sync
+= self
.out_z
.copy(self
.mod
.out_z
)
928 m
.next
= "corrections"
931 class FPCorrectionsMod
:
933 def __init__(self
, width
):
934 self
.in_z
= FPNumOut(width
, False)
935 self
.out_z
= FPNumOut(width
, False)
937 def elaborate(self
, platform
):
939 m
.submodules
.corr_in_z
= self
.in_z
940 m
.submodules
.corr_out_z
= self
.out_z
941 m
.d
.comb
+= self
.out_z
.copy(self
.in_z
)
942 with m
.If(self
.in_z
.is_denormalised
):
943 m
.d
.comb
+= self
.out_z
.e
.eq(self
.in_z
.N127
)
947 class FPCorrections(FPState
, FPID
):
949 def __init__(self
, width
, id_wid
):
950 FPState
.__init
__(self
, "corrections")
951 FPID
.__init
__(self
, id_wid
)
952 self
.mod
= FPCorrectionsMod(width
)
953 self
.out_z
= FPNumBase(width
)
955 def setup(self
, m
, in_z
, in_mid
):
956 """ links module to inputs and outputs
958 m
.submodules
.corrections
= self
.mod
959 m
.d
.comb
+= self
.mod
.in_z
.copy(in_z
)
960 if self
.in_mid
is not None:
961 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
965 m
.d
.sync
+= self
.out_z
.copy(self
.mod
.out_z
)
971 def __init__(self
, width
):
972 self
.in_z
= FPNumOut(width
, False)
973 self
.out_z
= FPNumOut(width
, False)
975 def elaborate(self
, platform
):
977 m
.submodules
.pack_in_z
= self
.in_z
978 with m
.If(self
.in_z
.is_overflowed
):
979 m
.d
.comb
+= self
.out_z
.inf(self
.in_z
.s
)
981 m
.d
.comb
+= self
.out_z
.create(self
.in_z
.s
, self
.in_z
.e
, self
.in_z
.m
)
985 class FPPack(FPState
, FPID
):
987 def __init__(self
, width
, id_wid
):
988 FPState
.__init
__(self
, "pack")
989 FPID
.__init
__(self
, id_wid
)
990 self
.mod
= FPPackMod(width
)
991 self
.out_z
= FPNumOut(width
, False)
993 def setup(self
, m
, in_z
, in_mid
):
994 """ links module to inputs and outputs
996 m
.submodules
.pack
= self
.mod
997 m
.d
.comb
+= self
.mod
.in_z
.copy(in_z
)
998 if self
.in_mid
is not None:
999 m
.d
.comb
+= self
.in_mid
.eq(in_mid
)
1001 def action(self
, m
):
1003 m
.d
.sync
+= self
.out_z
.v
.eq(self
.mod
.out_z
.v
)
1004 m
.next
= "pack_put_z"
1007 class FPPutZ(FPState
):
1009 def __init__(self
, state
, in_z
, out_z
, in_mid
, out_mid
):
1010 FPState
.__init
__(self
, state
)
1013 self
.in_mid
= in_mid
1014 self
.out_mid
= out_mid
1016 def action(self
, m
):
1017 if self
.in_mid
is not None:
1018 m
.d
.sync
+= self
.out_mid
.eq(self
.in_mid
)
1020 self
.out_z
.v
.eq(self
.in_z
.v
)
1022 with m
.If(self
.out_z
.stb
& self
.out_z
.ack
):
1023 m
.d
.sync
+= self
.out_z
.stb
.eq(0)
1026 m
.d
.sync
+= self
.out_z
.stb
.eq(1)
1029 class FPADDBaseMod(FPID
):
1031 def __init__(self
, width
, id_wid
=None, single_cycle
=False):
1034 * width: bit-width of IEEE754. supported: 16, 32, 64
1035 * id_wid: an identifier that is sync-connected to the input
1036 * single_cycle: True indicates each stage to complete in 1 clock
1038 FPID
.__init
__(self
, id_wid
)
1040 self
.single_cycle
= single_cycle
1042 self
.in_t
= Trigger()
1043 self
.in_a
= Signal(width
)
1044 self
.in_b
= Signal(width
)
1045 self
.out_z
= FPOp(width
)
1049 def add_state(self
, state
):
1050 self
.states
.append(state
)
1053 def get_fragment(self
, platform
=None):
1054 """ creates the HDL code-fragment for FPAdd
1057 m
.submodules
.out_z
= self
.out_z
1058 m
.submodules
.in_t
= self
.in_t
1060 get
= self
.add_state(FPGet2Op("get_ops", "special_cases",
1061 self
.in_a
, self
.in_b
, self
.width
))
1062 get
.setup(m
, self
.in_a
, self
.in_b
, self
.in_t
.stb
)
1063 m
.d
.comb
+= self
.in_t
.ack
.eq(get
.mod
.ack
)
1067 sc
= self
.add_state(FPAddSpecialCases(self
.width
, self
.id_wid
))
1068 sc
.setup(m
, a
, b
, self
.in_mid
)
1070 dn
= self
.add_state(FPAddDeNorm(self
.width
, self
.id_wid
))
1071 dn
.setup(m
, a
, b
, sc
.in_mid
)
1073 if self
.single_cycle
:
1074 alm
= self
.add_state(FPAddAlignSingle(self
.width
, self
.id_wid
))
1075 alm
.setup(m
, dn
.out_a
, dn
.out_b
, dn
.in_mid
)
1077 alm
= self
.add_state(FPAddAlignMulti(self
.width
, self
.id_wid
))
1078 alm
.setup(m
, dn
.out_a
, dn
.out_b
, dn
.in_mid
)
1080 add0
= self
.add_state(FPAddStage0(self
.width
, self
.id_wid
))
1081 add0
.setup(m
, alm
.out_a
, alm
.out_b
, alm
.in_mid
)
1083 add1
= self
.add_state(FPAddStage1(self
.width
, self
.id_wid
))
1084 add1
.setup(m
, add0
.out_tot
, add0
.out_z
, add0
.in_mid
)
1086 n1
= self
.add_state(FPNorm1(self
.width
, self
.id_wid
))
1087 n1
.setup(m
, add1
.out_z
, add1
.out_of
, add1
.norm_stb
, add0
.in_mid
)
1089 rn
= self
.add_state(FPRound(self
.width
, self
.id_wid
))
1090 rn
.setup(m
, n1
.out_z
, n1
.out_roundz
, n1
.in_mid
)
1092 cor
= self
.add_state(FPCorrections(self
.width
, self
.id_wid
))
1093 cor
.setup(m
, rn
.out_z
, rn
.in_mid
)
1095 pa
= self
.add_state(FPPack(self
.width
, self
.id_wid
))
1096 pa
.setup(m
, cor
.out_z
, rn
.in_mid
)
1098 ppz
= self
.add_state(FPPutZ("pack_put_z", pa
.out_z
, self
.out_z
,
1099 pa
.in_mid
, self
.out_mid
))
1101 pz
= self
.add_state(FPPutZ("put_z", sc
.out_z
, self
.out_z
,
1102 pa
.in_mid
, self
.out_mid
))
1104 with m
.FSM() as fsm
:
1106 for state
in self
.states
:
1107 with m
.State(state
.state_from
):
1112 class FPADDBase(FPID
):
1114 def __init__(self
, width
, id_wid
=None, single_cycle
=False):
1117 * width: bit-width of IEEE754. supported: 16, 32, 64
1118 * id_wid: an identifier that is sync-connected to the input
1119 * single_cycle: True indicates each stage to complete in 1 clock
1121 FPID
.__init
__(self
, id_wid
)
1123 self
.single_cycle
= single_cycle
1124 self
.mod
= FPADDBaseMod(width
, id_wid
, single_cycle
)
1126 self
.in_t
= Trigger()
1127 self
.in_a
= Signal(width
)
1128 self
.in_b
= Signal(width
)
1129 self
.out_z
= FPOp(width
)
1131 self
.in_accept
= Signal(reset_less
=True)
1132 self
.stb
= Signal(reset_less
=True)
1133 self
.ack
= Signal(reset
=0, reset_less
=True)
1135 def setup(self
, a
, b
, add_stb
):
1136 m
.d
.comb
+= [self
.in_a
.eq(a
),
1138 self
.in_mid
.eq(self
.in_mod
),
1142 m
.d
.comb
+= self
.stb
.eq(add_stb
)
1143 m
.d
.sync
+= self
.ack
.eq(0) # sets to zero when not in normalise_1 state
1145 m
.submodules
.add
= ab
1147 def action(self
, m
):
1149 m
.d
.comb
+= self
.in_accept
.eq((~self
.ack
) & (self
.stb
))
1151 with m
.If(self
.out_norm
):
1152 with m
.If(self
.in_accept
):
1157 m
.d
.sync
+= self
.ack
.eq(0)
1159 # normalisation not required (or done).
1161 m
.d
.sync
+= self
.ack
.eq(1)
1162 m
.d
.sync
+= self
.out_roundz
.eq(self
.mod
.out_of
.roundz
)
1164 if self
.in_mid
is not None:
1165 m
.d
.sync
+= self
.out_mid
.eq(self
.in_mid
)
1168 self
.out_z
.v
.eq(self
.in_z
.v
)
1170 # move to output state on detecting z
1171 with m
.If(self
.out_z
.stb
& self
.out_z
.ack
):
1172 m
.d
.sync
+= self
.out_z
.stb
.eq(0)
1175 m
.d
.sync
+= self
.out_z
.stb
.eq(1)
1179 """ FPADD: stages as follows:
1185 FPAddBase---> GetOps->Specials->Align->Add1/2->Norm->Round/Pack->PutZ
1189 FPAddBase is tricky: it is both a stage and *has* stages.
1192 def __init__(self
, width
, id_wid
=None, single_cycle
=False):
1195 * width: bit-width of IEEE754. supported: 16, 32, 64
1196 * id_wid: an identifier that is sync-connected to the input
1197 * single_cycle: True indicates each stage to complete in 1 clock
1199 FPID
.__init
__(self
, id_wid
)
1201 self
.id_wid
= id_wid
1202 self
.single_cycle
= single_cycle
1204 self
.in_a
= FPOp(width
)
1205 self
.in_b
= FPOp(width
)
1206 self
.out_z
= FPOp(width
)
1210 def add_state(self
, state
):
1211 self
.states
.append(state
)
1214 def get_fragment(self
, platform
=None):
1215 """ creates the HDL code-fragment for FPAdd
1218 m
.submodules
.in_a
= self
.in_a
1219 m
.submodules
.in_b
= self
.in_b
1220 m
.submodules
.out_z
= self
.out_z
1222 geta
= self
.add_state(FPGetOp("get_a", "get_b",
1223 self
.in_a
, self
.width
))
1224 geta
.setup(m
, self
.in_a
)
1227 getb
= self
.add_state(FPGetOp("get_b", "add",
1228 self
.in_b
, self
.width
))
1229 getb
.setup(m
, self
.in_b
)
1232 ab
= FPADDBase(self
.width
, self
.id_wid
, self
.single_cycle
))
1233 ab
= self
.add_state("add", ab
)
1235 pz
= self
.add_state(FPPutZ("put_z", ab
.out_z
, self
.out_z
,
1236 ab
.out_mid
, self
.out_mid
))
1238 with m
.FSM() as fsm
:
1240 for state
in self
.states
:
1241 with m
.State(state
.state_from
):
1247 if __name__
== "__main__":
1248 alu
= FPADDBase(width
=32, id_wid
=5, single_cycle
=True)
1249 main(alu
, ports
=[alu
.in_a
, alu
.in_b
] + \
1250 alu
.in_t
.ports() + \
1251 alu
.out_z
.ports() + \
1252 [alu
.in_mid
, alu
.out_mid
])
1255 # works... but don't use, just do "python fname.py convert -t v"
1256 #print (verilog.convert(alu, ports=[
1257 # ports=alu.in_a.ports() + \
1258 # alu.in_b.ports() + \
1259 # alu.out_z.ports())