1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Signal
, Cat
, Const
, Mux
, Module
, Elaboratable
7 from operator
import or_
8 from functools
import reduce
10 from nmutil
.singlepipe
import PrevControl
, NextControl
11 from nmutil
.pipeline
import ObjectProxy
16 def __init__(self
, width
):
18 self
.smax
= int(log(width
) / log(2))
19 self
.i
= Signal(width
, reset_less
=True)
20 self
.s
= Signal(self
.smax
, reset_less
=True)
21 self
.o
= Signal(width
, reset_less
=True)
23 def elaborate(self
, platform
):
25 m
.d
.comb
+= self
.o
.eq(self
.i
>> self
.s
)
30 """ Generates variable-length single-cycle shifter from a series
31 of conditional tests on each bit of the left/right shift operand.
32 Each bit tested produces output shifted by that number of bits,
33 in a binary fashion: bit 1 if set shifts by 1 bit, bit 2 if set
34 shifts by 2 bits, each partial result cascading to the next Mux.
36 Could be adapted to do arithmetic shift by taking copies of the
40 def __init__(self
, width
):
42 self
.smax
= int(log(width
) / log(2))
44 def lshift(self
, op
, s
):
48 for i
in range(self
.smax
):
50 res
= Mux(s
& (1<<i
), Cat(zeros
, res
[0:-(1<<i
)]), res
)
53 def rshift(self
, op
, s
):
57 for i
in range(self
.smax
):
59 res
= Mux(s
& (1<<i
), Cat(res
[(1<<i
):], zeros
), res
)
63 class FPNumBaseRecord
:
64 """ Floating-point Base Number Class
66 def __init__(self
, width
, m_extra
=True):
68 m_width
= {16: 11, 32: 24, 64: 53}[width
] # 1 extra bit (overflow)
69 e_width
= {16: 7, 32: 10, 64: 13}[width
] # 2 extra bits (overflow)
70 e_max
= 1<<(e_width
-3)
71 self
.rmw
= m_width
# real mantissa width (not including extras)
74 # mantissa extra bits (top,guard,round)
76 m_width
+= self
.m_extra
79 #print (m_width, e_width, e_max, self.rmw, self.m_extra)
80 self
.m_width
= m_width
81 self
.e_width
= e_width
82 self
.e_start
= self
.rmw
- 1
83 self
.e_end
= self
.rmw
+ self
.e_width
- 3 # for decoding
85 self
.v
= Signal(width
, reset_less
=True) # Latched copy of value
86 self
.m
= Signal(m_width
, reset_less
=True) # Mantissa
87 self
.e
= Signal((e_width
, True), reset_less
=True) # exp+2 bits, signed
88 self
.s
= Signal(reset_less
=True) # Sign bit
93 def drop_in(self
, fp
):
100 fp
.e_width
= self
.e_width
101 fp
.e_max
= self
.e_max
102 fp
.m_width
= self
.m_width
103 fp
.e_start
= self
.e_start
104 fp
.e_end
= self
.e_end
105 fp
.m_extra
= self
.m_extra
107 m_width
= self
.m_width
109 e_width
= self
.e_width
111 self
.mzero
= Const(0, (m_width
, False))
112 m_msb
= 1<<(self
.m_width
-2)
113 self
.msb1
= Const(m_msb
, (m_width
, False))
114 self
.m1s
= Const(-1, (m_width
, False))
115 self
.P128
= Const(e_max
, (e_width
, True))
116 self
.P127
= Const(e_max
-1, (e_width
, True))
117 self
.N127
= Const(-(e_max
-1), (e_width
, True))
118 self
.N126
= Const(-(e_max
-2), (e_width
, True))
120 def create(self
, s
, e
, m
):
121 """ creates a value from sign / exponent / mantissa
123 bias is added here, to the exponent
126 self
.v
[-1].eq(s
), # sign
127 self
.v
[self
.e_start
:self
.e_end
].eq(e
+ self
.fp
.P127
), # (add on bias)
128 self
.v
[0:self
.e_start
].eq(m
) # mantissa
132 return (s
, self
.fp
.P128
, 1<<(self
.e_start
-1))
135 return (s
, self
.fp
.P128
, 0)
138 return (s
, self
.fp
.N127
, 0)
141 return self
.create(*self
._nan
(s
))
144 return self
.create(*self
._inf
(s
))
147 return self
.create(*self
._zero
(s
))
149 def create2(self
, s
, e
, m
):
150 """ creates a value from sign / exponent / mantissa
152 bias is added here, to the exponent
154 e
= e
+ self
.P127
# exp (add on bias)
155 return Cat(m
[0:self
.e_start
],
156 e
[0:self
.e_end
-self
.e_start
],
160 return self
.create2(s
, self
.P128
, self
.msb1
)
163 return self
.create2(s
, self
.P128
, self
.mzero
)
166 return self
.create2(s
, self
.N127
, self
.mzero
)
174 return [self
.s
.eq(inp
.s
), self
.e
.eq(inp
.e
), self
.m
.eq(inp
.m
)]
177 class FPNumBase(FPNumBaseRecord
, Elaboratable
):
178 """ Floating-point Base Number Class
180 def __init__(self
, fp
):
185 self
.is_nan
= Signal(reset_less
=True)
186 self
.is_zero
= Signal(reset_less
=True)
187 self
.is_inf
= Signal(reset_less
=True)
188 self
.is_overflowed
= Signal(reset_less
=True)
189 self
.is_denormalised
= Signal(reset_less
=True)
190 self
.exp_128
= Signal(reset_less
=True)
191 self
.exp_sub_n126
= Signal((e_width
, True), reset_less
=True)
192 self
.exp_lt_n126
= Signal(reset_less
=True)
193 self
.exp_gt_n126
= Signal(reset_less
=True)
194 self
.exp_gt127
= Signal(reset_less
=True)
195 self
.exp_n127
= Signal(reset_less
=True)
196 self
.exp_n126
= Signal(reset_less
=True)
197 self
.m_zero
= Signal(reset_less
=True)
198 self
.m_msbzero
= Signal(reset_less
=True)
200 def elaborate(self
, platform
):
202 m
.d
.comb
+= self
.is_nan
.eq(self
._is
_nan
())
203 m
.d
.comb
+= self
.is_zero
.eq(self
._is
_zero
())
204 m
.d
.comb
+= self
.is_inf
.eq(self
._is
_inf
())
205 m
.d
.comb
+= self
.is_overflowed
.eq(self
._is
_overflowed
())
206 m
.d
.comb
+= self
.is_denormalised
.eq(self
._is
_denormalised
())
207 m
.d
.comb
+= self
.exp_128
.eq(self
.e
== self
.fp
.P128
)
208 m
.d
.comb
+= self
.exp_sub_n126
.eq(self
.e
- self
.fp
.N126
)
209 m
.d
.comb
+= self
.exp_gt_n126
.eq(self
.exp_sub_n126
> 0)
210 m
.d
.comb
+= self
.exp_lt_n126
.eq(self
.exp_sub_n126
< 0)
211 m
.d
.comb
+= self
.exp_gt127
.eq(self
.e
> self
.fp
.P127
)
212 m
.d
.comb
+= self
.exp_n127
.eq(self
.e
== self
.fp
.N127
)
213 m
.d
.comb
+= self
.exp_n126
.eq(self
.e
== self
.fp
.N126
)
214 m
.d
.comb
+= self
.m_zero
.eq(self
.m
== self
.fp
.mzero
)
215 m
.d
.comb
+= self
.m_msbzero
.eq(self
.m
[self
.fp
.e_start
] == 0)
220 return (self
.exp_128
) & (~self
.m_zero
)
223 return (self
.exp_128
) & (self
.m_zero
)
226 return (self
.exp_n127
) & (self
.m_zero
)
228 def _is_overflowed(self
):
229 return self
.exp_gt127
231 def _is_denormalised(self
):
232 return (self
.exp_n126
) & (self
.m_msbzero
)
235 class FPNumOut(FPNumBase
):
236 """ Floating-point Number Class
238 Contains signals for an incoming copy of the value, decoded into
239 sign / exponent / mantissa.
240 Also contains encoding functions, creation and recognition of
241 zero, NaN and inf (all signed)
243 Four extra bits are included in the mantissa: the top bit
244 (m[-1]) is effectively a carry-overflow. The other three are
245 guard (m[2]), round (m[1]), and sticky (m[0])
247 def __init__(self
, fp
):
248 FPNumBase
.__init
__(self
, fp
)
250 def elaborate(self
, platform
):
251 m
= FPNumBase
.elaborate(self
, platform
)
256 class MultiShiftRMerge(Elaboratable
):
257 """ shifts down (right) and merges lower bits into m[0].
258 m[0] is the "sticky" bit, basically
260 def __init__(self
, width
, s_max
=None):
262 s_max
= int(log(width
) / log(2))
264 self
.m
= Signal(width
, reset_less
=True)
265 self
.inp
= Signal(width
, reset_less
=True)
266 self
.diff
= Signal(s_max
, reset_less
=True)
269 def elaborate(self
, platform
):
272 rs
= Signal(self
.width
, reset_less
=True)
273 m_mask
= Signal(self
.width
, reset_less
=True)
274 smask
= Signal(self
.width
, reset_less
=True)
275 stickybit
= Signal(reset_less
=True)
276 maxslen
= Signal(self
.smax
, reset_less
=True)
277 maxsleni
= Signal(self
.smax
, reset_less
=True)
279 sm
= MultiShift(self
.width
-1)
280 m0s
= Const(0, self
.width
-1)
281 mw
= Const(self
.width
-1, len(self
.diff
))
282 m
.d
.comb
+= [maxslen
.eq(Mux(self
.diff
> mw
, mw
, self
.diff
)),
283 maxsleni
.eq(Mux(self
.diff
> mw
, 0, mw
-self
.diff
)),
287 # shift mantissa by maxslen, mask by inverse
288 rs
.eq(sm
.rshift(self
.inp
[1:], maxslen
)),
289 m_mask
.eq(sm
.rshift(~m0s
, maxsleni
)),
290 smask
.eq(self
.inp
[1:] & m_mask
),
291 # sticky bit combines all mask (and mantissa low bit)
292 stickybit
.eq(smask
.bool() | self
.inp
[0]),
293 # mantissa result contains m[0] already.
294 self
.m
.eq(Cat(stickybit
, rs
))
299 class FPNumShift(FPNumBase
, Elaboratable
):
300 """ Floating-point Number Class for shifting
302 def __init__(self
, mainm
, op
, inv
, width
, m_extra
=True):
303 FPNumBase
.__init
__(self
, width
, m_extra
)
304 self
.latch_in
= Signal()
309 def elaborate(self
, platform
):
310 m
= FPNumBase
.elaborate(self
, platform
)
312 m
.d
.comb
+= self
.s
.eq(op
.s
)
313 m
.d
.comb
+= self
.e
.eq(op
.e
)
314 m
.d
.comb
+= self
.m
.eq(op
.m
)
316 with self
.mainm
.State("align"):
317 with m
.If(self
.e
< self
.inv
.e
):
318 m
.d
.sync
+= self
.shift_down()
322 def shift_down(self
, inp
):
323 """ shifts a mantissa down by one. exponent is increased to compensate
325 accuracy is lost as a result in the mantissa however there are 3
326 guard bits (the latter of which is the "sticky" bit)
328 return [self
.e
.eq(inp
.e
+ 1),
329 self
.m
.eq(Cat(inp
.m
[0] | inp
.m
[1], inp
.m
[2:], 0))
332 def shift_down_multi(self
, diff
):
333 """ shifts a mantissa down. exponent is increased to compensate
335 accuracy is lost as a result in the mantissa however there are 3
336 guard bits (the latter of which is the "sticky" bit)
338 this code works by variable-shifting the mantissa by up to
339 its maximum bit-length: no point doing more (it'll still be
342 the sticky bit is computed by shifting a batch of 1s by
343 the same amount, which will introduce zeros. it's then
344 inverted and used as a mask to get the LSBs of the mantissa.
345 those are then |'d into the sticky bit.
347 sm
= MultiShift(self
.width
)
348 mw
= Const(self
.m_width
-1, len(diff
))
349 maxslen
= Mux(diff
> mw
, mw
, diff
)
350 rs
= sm
.rshift(self
.m
[1:], maxslen
)
351 maxsleni
= mw
- maxslen
352 m_mask
= sm
.rshift(self
.m1s
[1:], maxsleni
) # shift and invert
354 stickybits
= reduce(or_
, self
.m
[1:] & m_mask
) | self
.m
[0]
355 return [self
.e
.eq(self
.e
+ diff
),
356 self
.m
.eq(Cat(stickybits
, rs
))
359 def shift_up_multi(self
, diff
):
360 """ shifts a mantissa up. exponent is decreased to compensate
362 sm
= MultiShift(self
.width
)
363 mw
= Const(self
.m_width
, len(diff
))
364 maxslen
= Mux(diff
> mw
, mw
, diff
)
366 return [self
.e
.eq(self
.e
- diff
),
367 self
.m
.eq(sm
.lshift(self
.m
, maxslen
))
371 class FPNumDecode(FPNumBase
):
372 """ Floating-point Number Class
374 Contains signals for an incoming copy of the value, decoded into
375 sign / exponent / mantissa.
376 Also contains encoding functions, creation and recognition of
377 zero, NaN and inf (all signed)
379 Four extra bits are included in the mantissa: the top bit
380 (m[-1]) is effectively a carry-overflow. The other three are
381 guard (m[2]), round (m[1]), and sticky (m[0])
383 def __init__(self
, op
, fp
):
384 FPNumBase
.__init
__(self
, fp
)
387 def elaborate(self
, platform
):
388 m
= FPNumBase
.elaborate(self
, platform
)
390 m
.d
.comb
+= self
.decode(self
.v
)
395 """ decodes a latched value into sign / exponent / mantissa
397 bias is subtracted here, from the exponent. exponent
398 is extended to 10 bits so that subtract 127 is done on
401 args
= [0] * self
.m_extra
+ [v
[0:self
.e_start
]] # pad with extra zeros
402 #print ("decode", self.e_end)
403 return [self
.m
.eq(Cat(*args
)), # mantissa
404 self
.e
.eq(v
[self
.e_start
:self
.e_end
] - self
.fp
.P127
), # exp
405 self
.s
.eq(v
[-1]), # sign
408 class FPNumIn(FPNumBase
):
409 """ Floating-point Number Class
411 Contains signals for an incoming copy of the value, decoded into
412 sign / exponent / mantissa.
413 Also contains encoding functions, creation and recognition of
414 zero, NaN and inf (all signed)
416 Four extra bits are included in the mantissa: the top bit
417 (m[-1]) is effectively a carry-overflow. The other three are
418 guard (m[2]), round (m[1]), and sticky (m[0])
420 def __init__(self
, op
, fp
):
421 FPNumBase
.__init
__(self
, fp
)
422 self
.latch_in
= Signal()
425 def decode2(self
, m
):
426 """ decodes a latched value into sign / exponent / mantissa
428 bias is subtracted here, from the exponent. exponent
429 is extended to 10 bits so that subtract 127 is done on
433 args
= [0] * self
.m_extra
+ [v
[0:self
.e_start
]] # pad with extra zeros
434 #print ("decode", self.e_end)
435 res
= ObjectProxy(m
, pipemode
=False)
436 res
.m
= Cat(*args
) # mantissa
437 res
.e
= v
[self
.e_start
:self
.e_end
] - self
.fp
.P127
# exp
442 """ decodes a latched value into sign / exponent / mantissa
444 bias is subtracted here, from the exponent. exponent
445 is extended to 10 bits so that subtract 127 is done on
448 args
= [0] * self
.m_extra
+ [v
[0:self
.e_start
]] # pad with extra zeros
449 #print ("decode", self.e_end)
450 return [self
.m
.eq(Cat(*args
)), # mantissa
451 self
.e
.eq(v
[self
.e_start
:self
.e_end
] - self
.P127
), # exp
452 self
.s
.eq(v
[-1]), # sign
455 def shift_down(self
, inp
):
456 """ shifts a mantissa down by one. exponent is increased to compensate
458 accuracy is lost as a result in the mantissa however there are 3
459 guard bits (the latter of which is the "sticky" bit)
461 return [self
.e
.eq(inp
.e
+ 1),
462 self
.m
.eq(Cat(inp
.m
[0] | inp
.m
[1], inp
.m
[2:], 0))
465 def shift_down_multi(self
, diff
, inp
=None):
466 """ shifts a mantissa down. exponent is increased to compensate
468 accuracy is lost as a result in the mantissa however there are 3
469 guard bits (the latter of which is the "sticky" bit)
471 this code works by variable-shifting the mantissa by up to
472 its maximum bit-length: no point doing more (it'll still be
475 the sticky bit is computed by shifting a batch of 1s by
476 the same amount, which will introduce zeros. it's then
477 inverted and used as a mask to get the LSBs of the mantissa.
478 those are then |'d into the sticky bit.
482 sm
= MultiShift(self
.width
)
483 mw
= Const(self
.m_width
-1, len(diff
))
484 maxslen
= Mux(diff
> mw
, mw
, diff
)
485 rs
= sm
.rshift(inp
.m
[1:], maxslen
)
486 maxsleni
= mw
- maxslen
487 m_mask
= sm
.rshift(self
.m1s
[1:], maxsleni
) # shift and invert
489 #stickybit = reduce(or_, inp.m[1:] & m_mask) | inp.m[0]
490 stickybit
= (inp
.m
[1:] & m_mask
).bool() | inp
.m
[0]
491 return [self
.e
.eq(inp
.e
+ diff
),
492 self
.m
.eq(Cat(stickybit
, rs
))
495 def shift_up_multi(self
, diff
):
496 """ shifts a mantissa up. exponent is decreased to compensate
498 sm
= MultiShift(self
.width
)
499 mw
= Const(self
.m_width
, len(diff
))
500 maxslen
= Mux(diff
> mw
, mw
, diff
)
502 return [self
.e
.eq(self
.e
- diff
),
503 self
.m
.eq(sm
.lshift(self
.m
, maxslen
))
506 class Trigger(Elaboratable
):
509 self
.stb
= Signal(reset
=0)
511 self
.trigger
= Signal(reset_less
=True)
513 def elaborate(self
, platform
):
515 m
.d
.comb
+= self
.trigger
.eq(self
.stb
& self
.ack
)
519 return [self
.stb
.eq(inp
.stb
),
524 return [self
.stb
, self
.ack
]
527 class FPOpIn(PrevControl
):
528 def __init__(self
, width
):
529 PrevControl
.__init
__(self
)
536 def chain_inv(self
, in_op
, extra
=None):
538 if extra
is not None:
540 return [self
.v
.eq(in_op
.v
), # receive value
541 self
.stb
.eq(stb
), # receive STB
542 in_op
.ack
.eq(~self
.ack
), # send ACK
545 def chain_from(self
, in_op
, extra
=None):
547 if extra
is not None:
549 return [self
.v
.eq(in_op
.v
), # receive value
550 self
.stb
.eq(stb
), # receive STB
551 in_op
.ack
.eq(self
.ack
), # send ACK
555 class FPOpOut(NextControl
):
556 def __init__(self
, width
):
557 NextControl
.__init
__(self
)
564 def chain_inv(self
, in_op
, extra
=None):
566 if extra
is not None:
568 return [self
.v
.eq(in_op
.v
), # receive value
569 self
.stb
.eq(stb
), # receive STB
570 in_op
.ack
.eq(~self
.ack
), # send ACK
573 def chain_from(self
, in_op
, extra
=None):
575 if extra
is not None:
577 return [self
.v
.eq(in_op
.v
), # receive value
578 self
.stb
.eq(stb
), # receive STB
579 in_op
.ack
.eq(self
.ack
), # send ACK
583 class Overflow
: #(Elaboratable):
585 self
.guard
= Signal(reset_less
=True) # tot[2]
586 self
.round_bit
= Signal(reset_less
=True) # tot[1]
587 self
.sticky
= Signal(reset_less
=True) # tot[0]
588 self
.m0
= Signal(reset_less
=True) # mantissa zero bit
590 #self.roundz = Signal(reset_less=True)
599 return [self
.guard
.eq(inp
.guard
),
600 self
.round_bit
.eq(inp
.round_bit
),
601 self
.sticky
.eq(inp
.sticky
),
606 return self
.guard
& (self
.round_bit | self
.sticky | self
.m0
)
610 """ IEEE754 Floating Point Base Class
612 contains common functions for FP manipulation, such as
613 extracting and packing operands, normalisation, denormalisation,
617 def get_op(self
, m
, op
, v
, next_state
):
618 """ this function moves to the next state and copies the operand
619 when both stb and ack are 1.
620 acknowledgement is sent by setting ack to ZERO.
624 with m
.If((op
.ready_o
) & (op
.valid_i_test
)):
626 # op is latched in from FPNumIn class on same ack/stb
627 m
.d
.comb
+= ack
.eq(0)
629 m
.d
.comb
+= ack
.eq(1)
632 def denormalise(self
, m
, a
):
633 """ denormalises a number. this is probably the wrong name for
634 this function. for normalised numbers (exponent != minimum)
635 one *extra* bit (the implicit 1) is added *back in*.
636 for denormalised numbers, the mantissa is left alone
637 and the exponent increased by 1.
639 both cases *effectively multiply the number stored by 2*,
640 which has to be taken into account when extracting the result.
642 with m
.If(a
.exp_n127
):
643 m
.d
.sync
+= a
.e
.eq(a
.fp
.N126
) # limit a exponent
645 m
.d
.sync
+= a
.m
[-1].eq(1) # set top mantissa bit
647 def op_normalise(self
, m
, op
, next_state
):
648 """ operand normalisation
649 NOTE: just like "align", this one keeps going round every clock
650 until the result's exponent is within acceptable "range"
652 with m
.If((op
.m
[-1] == 0)): # check last bit of mantissa
654 op
.e
.eq(op
.e
- 1), # DECREASE exponent
655 op
.m
.eq(op
.m
<< 1), # shift mantissa UP
660 def normalise_1(self
, m
, z
, of
, next_state
):
661 """ first stage normalisation
663 NOTE: just like "align", this one keeps going round every clock
664 until the result's exponent is within acceptable "range"
665 NOTE: the weirdness of reassigning guard and round is due to
666 the extra mantissa bits coming from tot[0..2]
668 with m
.If((z
.m
[-1] == 0) & (z
.e
> z
.fp
.N126
)):
670 z
.e
.eq(z
.e
- 1), # DECREASE exponent
671 z
.m
.eq(z
.m
<< 1), # shift mantissa UP
672 z
.m
[0].eq(of
.guard
), # steal guard bit (was tot[2])
673 of
.guard
.eq(of
.round_bit
), # steal round_bit (was tot[1])
674 of
.round_bit
.eq(0), # reset round bit
680 def normalise_2(self
, m
, z
, of
, next_state
):
681 """ second stage normalisation
683 NOTE: just like "align", this one keeps going round every clock
684 until the result's exponent is within acceptable "range"
685 NOTE: the weirdness of reassigning guard and round is due to
686 the extra mantissa bits coming from tot[0..2]
688 with m
.If(z
.e
< z
.fp
.N126
):
690 z
.e
.eq(z
.e
+ 1), # INCREASE exponent
691 z
.m
.eq(z
.m
>> 1), # shift mantissa DOWN
694 of
.round_bit
.eq(of
.guard
),
695 of
.sticky
.eq(of
.sticky | of
.round_bit
)
700 def roundz(self
, m
, z
, roundz
):
701 """ performs rounding on the output. TODO: different kinds of rounding
704 m
.d
.sync
+= z
.m
.eq(z
.m
+ 1) # mantissa rounds up
705 with m
.If(z
.m
== z
.fp
.m1s
): # all 1s
706 m
.d
.sync
+= z
.e
.eq(z
.e
+ 1) # exponent rounds up
708 def corrections(self
, m
, z
, next_state
):
709 """ denormalisation and sign-bug corrections
712 # denormalised, correct exponent to zero
713 with m
.If(z
.is_denormalised
):
714 m
.d
.sync
+= z
.e
.eq(z
.fp
.N127
)
716 def pack(self
, m
, z
, next_state
):
717 """ packs the result into the output (detects overflow->Inf)
720 # if overflow occurs, return inf
721 with m
.If(z
.is_overflowed
):
722 m
.d
.sync
+= z
.inf(z
.s
)
724 m
.d
.sync
+= z
.create(z
.s
, z
.e
, z
.m
)
726 def put_z(self
, m
, z
, out_z
, next_state
):
727 """ put_z: stores the result in the output. raises stb and waits
728 for ack to be set to 1 before moving to the next state.
729 resets stb back to zero when that occurs, as acknowledgement.
734 with m
.If(out_z
.valid_o
& out_z
.ready_i_test
):
735 m
.d
.sync
+= out_z
.valid_o
.eq(0)
738 m
.d
.sync
+= out_z
.valid_o
.eq(1)
741 class FPState(FPBase
):
742 def __init__(self
, state_from
):
743 self
.state_from
= state_from
745 def set_inputs(self
, inputs
):
747 for k
,v
in inputs
.items():
750 def set_outputs(self
, outputs
):
751 self
.outputs
= outputs
752 for k
,v
in outputs
.items():
757 def __init__(self
, id_wid
):
760 self
.in_mid
= Signal(id_wid
, reset_less
=True)
761 self
.out_mid
= Signal(id_wid
, reset_less
=True)
767 if self
.id_wid
is not None:
768 m
.d
.sync
+= self
.out_mid
.eq(self
.in_mid
)