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 singlepipe
import PrevControl
, NextControl
11 from 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 FPNumBase
: #(Elaboratable):
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) # Exponent: IEEE754exp+2 bits, signed
88 self
.s
= Signal(reset_less
=True) # Sign bit
90 self
.mzero
= Const(0, (m_width
, False))
91 m_msb
= 1<<(self
.m_width
-2)
92 self
.msb1
= Const(m_msb
, (m_width
, False))
93 self
.m1s
= Const(-1, (m_width
, False))
94 self
.P128
= Const(e_max
, (e_width
, True))
95 self
.P127
= Const(e_max
-1, (e_width
, True))
96 self
.N127
= Const(-(e_max
-1), (e_width
, True))
97 self
.N126
= Const(-(e_max
-2), (e_width
, True))
99 self
.is_nan
= Signal(reset_less
=True)
100 self
.is_zero
= Signal(reset_less
=True)
101 self
.is_inf
= Signal(reset_less
=True)
102 self
.is_overflowed
= Signal(reset_less
=True)
103 self
.is_denormalised
= Signal(reset_less
=True)
104 self
.exp_128
= Signal(reset_less
=True)
105 self
.exp_sub_n126
= Signal((e_width
, True), reset_less
=True)
106 self
.exp_lt_n126
= Signal(reset_less
=True)
107 self
.exp_gt_n126
= Signal(reset_less
=True)
108 self
.exp_gt127
= Signal(reset_less
=True)
109 self
.exp_n127
= Signal(reset_less
=True)
110 self
.exp_n126
= Signal(reset_less
=True)
111 self
.m_zero
= Signal(reset_less
=True)
112 self
.m_msbzero
= Signal(reset_less
=True)
114 def elaborate(self
, platform
):
116 m
.d
.comb
+= self
.is_nan
.eq(self
._is
_nan
())
117 m
.d
.comb
+= self
.is_zero
.eq(self
._is
_zero
())
118 m
.d
.comb
+= self
.is_inf
.eq(self
._is
_inf
())
119 m
.d
.comb
+= self
.is_overflowed
.eq(self
._is
_overflowed
())
120 m
.d
.comb
+= self
.is_denormalised
.eq(self
._is
_denormalised
())
121 m
.d
.comb
+= self
.exp_128
.eq(self
.e
== self
.P128
)
122 m
.d
.comb
+= self
.exp_sub_n126
.eq(self
.e
- self
.N126
)
123 m
.d
.comb
+= self
.exp_gt_n126
.eq(self
.exp_sub_n126
> 0)
124 m
.d
.comb
+= self
.exp_lt_n126
.eq(self
.exp_sub_n126
< 0)
125 m
.d
.comb
+= self
.exp_gt127
.eq(self
.e
> self
.P127
)
126 m
.d
.comb
+= self
.exp_n127
.eq(self
.e
== self
.N127
)
127 m
.d
.comb
+= self
.exp_n126
.eq(self
.e
== self
.N126
)
128 m
.d
.comb
+= self
.m_zero
.eq(self
.m
== self
.mzero
)
129 m
.d
.comb
+= self
.m_msbzero
.eq(self
.m
[self
.e_start
] == 0)
134 return (self
.exp_128
) & (~self
.m_zero
)
137 return (self
.exp_128
) & (self
.m_zero
)
140 return (self
.exp_n127
) & (self
.m_zero
)
142 def _is_overflowed(self
):
143 return self
.exp_gt127
145 def _is_denormalised(self
):
146 return (self
.exp_n126
) & (self
.m_msbzero
)
154 return [self
.s
.eq(inp
.s
), self
.e
.eq(inp
.e
), self
.m
.eq(inp
.m
)]
157 class FPNumOut(FPNumBase
):
158 """ Floating-point Number Class
160 Contains signals for an incoming copy of the value, decoded into
161 sign / exponent / mantissa.
162 Also contains encoding functions, creation and recognition of
163 zero, NaN and inf (all signed)
165 Four extra bits are included in the mantissa: the top bit
166 (m[-1]) is effectively a carry-overflow. The other three are
167 guard (m[2]), round (m[1]), and sticky (m[0])
169 def __init__(self
, width
, m_extra
=True):
170 FPNumBase
.__init
__(self
, width
, m_extra
)
172 def elaborate(self
, platform
):
173 m
= FPNumBase
.elaborate(self
, platform
)
177 def create(self
, s
, e
, m
):
178 """ creates a value from sign / exponent / mantissa
180 bias is added here, to the exponent
183 self
.v
[-1].eq(s
), # sign
184 self
.v
[self
.e_start
:self
.e_end
].eq(e
+ self
.P127
), # exp (add on bias)
185 self
.v
[0:self
.e_start
].eq(m
) # mantissa
189 return self
.create(s
, self
.P128
, 1<<(self
.e_start
-1))
192 return self
.create(s
, self
.P128
, 0)
195 return self
.create(s
, self
.N127
, 0)
197 def create2(self
, s
, e
, m
):
198 """ creates a value from sign / exponent / mantissa
200 bias is added here, to the exponent
202 e
= e
+ self
.P127
# exp (add on bias)
203 return Cat(m
[0:self
.e_start
],
204 e
[0:self
.e_end
-self
.e_start
],
208 return self
.create2(s
, self
.P128
, self
.msb1
)
211 return self
.create2(s
, self
.P128
, self
.mzero
)
214 return self
.create2(s
, self
.N127
, self
.mzero
)
217 class MultiShiftRMerge(Elaboratable
):
218 """ shifts down (right) and merges lower bits into m[0].
219 m[0] is the "sticky" bit, basically
221 def __init__(self
, width
, s_max
=None):
223 s_max
= int(log(width
) / log(2))
225 self
.m
= Signal(width
, reset_less
=True)
226 self
.inp
= Signal(width
, reset_less
=True)
227 self
.diff
= Signal(s_max
, reset_less
=True)
230 def elaborate(self
, platform
):
233 rs
= Signal(self
.width
, reset_less
=True)
234 m_mask
= Signal(self
.width
, reset_less
=True)
235 smask
= Signal(self
.width
, reset_less
=True)
236 stickybit
= Signal(reset_less
=True)
237 maxslen
= Signal(self
.smax
, reset_less
=True)
238 maxsleni
= Signal(self
.smax
, reset_less
=True)
240 sm
= MultiShift(self
.width
-1)
241 m0s
= Const(0, self
.width
-1)
242 mw
= Const(self
.width
-1, len(self
.diff
))
243 m
.d
.comb
+= [maxslen
.eq(Mux(self
.diff
> mw
, mw
, self
.diff
)),
244 maxsleni
.eq(Mux(self
.diff
> mw
, 0, mw
-self
.diff
)),
248 # shift mantissa by maxslen, mask by inverse
249 rs
.eq(sm
.rshift(self
.inp
[1:], maxslen
)),
250 m_mask
.eq(sm
.rshift(~m0s
, maxsleni
)),
251 smask
.eq(self
.inp
[1:] & m_mask
),
252 # sticky bit combines all mask (and mantissa low bit)
253 stickybit
.eq(smask
.bool() | self
.inp
[0]),
254 # mantissa result contains m[0] already.
255 self
.m
.eq(Cat(stickybit
, rs
))
260 class FPNumShift(FPNumBase
, Elaboratable
):
261 """ Floating-point Number Class for shifting
263 def __init__(self
, mainm
, op
, inv
, width
, m_extra
=True):
264 FPNumBase
.__init
__(self
, width
, m_extra
)
265 self
.latch_in
= Signal()
270 def elaborate(self
, platform
):
271 m
= FPNumBase
.elaborate(self
, platform
)
273 m
.d
.comb
+= self
.s
.eq(op
.s
)
274 m
.d
.comb
+= self
.e
.eq(op
.e
)
275 m
.d
.comb
+= self
.m
.eq(op
.m
)
277 with self
.mainm
.State("align"):
278 with m
.If(self
.e
< self
.inv
.e
):
279 m
.d
.sync
+= self
.shift_down()
283 def shift_down(self
, inp
):
284 """ shifts a mantissa down by one. exponent is increased to compensate
286 accuracy is lost as a result in the mantissa however there are 3
287 guard bits (the latter of which is the "sticky" bit)
289 return [self
.e
.eq(inp
.e
+ 1),
290 self
.m
.eq(Cat(inp
.m
[0] | inp
.m
[1], inp
.m
[2:], 0))
293 def shift_down_multi(self
, diff
):
294 """ shifts a mantissa down. exponent is increased to compensate
296 accuracy is lost as a result in the mantissa however there are 3
297 guard bits (the latter of which is the "sticky" bit)
299 this code works by variable-shifting the mantissa by up to
300 its maximum bit-length: no point doing more (it'll still be
303 the sticky bit is computed by shifting a batch of 1s by
304 the same amount, which will introduce zeros. it's then
305 inverted and used as a mask to get the LSBs of the mantissa.
306 those are then |'d into the sticky bit.
308 sm
= MultiShift(self
.width
)
309 mw
= Const(self
.m_width
-1, len(diff
))
310 maxslen
= Mux(diff
> mw
, mw
, diff
)
311 rs
= sm
.rshift(self
.m
[1:], maxslen
)
312 maxsleni
= mw
- maxslen
313 m_mask
= sm
.rshift(self
.m1s
[1:], maxsleni
) # shift and invert
315 stickybits
= reduce(or_
, self
.m
[1:] & m_mask
) | self
.m
[0]
316 return [self
.e
.eq(self
.e
+ diff
),
317 self
.m
.eq(Cat(stickybits
, rs
))
320 def shift_up_multi(self
, diff
):
321 """ shifts a mantissa up. exponent is decreased to compensate
323 sm
= MultiShift(self
.width
)
324 mw
= Const(self
.m_width
, len(diff
))
325 maxslen
= Mux(diff
> mw
, mw
, diff
)
327 return [self
.e
.eq(self
.e
- diff
),
328 self
.m
.eq(sm
.lshift(self
.m
, maxslen
))
332 class FPNumDecode(FPNumBase
):
333 """ Floating-point Number Class
335 Contains signals for an incoming copy of the value, decoded into
336 sign / exponent / mantissa.
337 Also contains encoding functions, creation and recognition of
338 zero, NaN and inf (all signed)
340 Four extra bits are included in the mantissa: the top bit
341 (m[-1]) is effectively a carry-overflow. The other three are
342 guard (m[2]), round (m[1]), and sticky (m[0])
344 def __init__(self
, op
, width
, m_extra
=True):
345 FPNumBase
.__init
__(self
, width
, m_extra
)
348 def elaborate(self
, platform
):
349 m
= FPNumBase
.elaborate(self
, platform
)
351 m
.d
.comb
+= self
.decode(self
.v
)
356 """ decodes a latched value into sign / exponent / mantissa
358 bias is subtracted here, from the exponent. exponent
359 is extended to 10 bits so that subtract 127 is done on
362 args
= [0] * self
.m_extra
+ [v
[0:self
.e_start
]] # pad with extra zeros
363 #print ("decode", self.e_end)
364 return [self
.m
.eq(Cat(*args
)), # mantissa
365 self
.e
.eq(v
[self
.e_start
:self
.e_end
] - self
.P127
), # exp
366 self
.s
.eq(v
[-1]), # sign
369 class FPNumIn(FPNumBase
):
370 """ Floating-point Number Class
372 Contains signals for an incoming copy of the value, decoded into
373 sign / exponent / mantissa.
374 Also contains encoding functions, creation and recognition of
375 zero, NaN and inf (all signed)
377 Four extra bits are included in the mantissa: the top bit
378 (m[-1]) is effectively a carry-overflow. The other three are
379 guard (m[2]), round (m[1]), and sticky (m[0])
381 def __init__(self
, op
, width
, m_extra
=True):
382 FPNumBase
.__init
__(self
, width
, m_extra
)
383 self
.latch_in
= Signal()
386 def decode2(self
, m
):
387 """ decodes a latched value into sign / exponent / mantissa
389 bias is subtracted here, from the exponent. exponent
390 is extended to 10 bits so that subtract 127 is done on
394 args
= [0] * self
.m_extra
+ [v
[0:self
.e_start
]] # pad with extra zeros
395 #print ("decode", self.e_end)
396 res
= ObjectProxy(m
, pipemode
=False)
397 res
.m
= Cat(*args
) # mantissa
398 res
.e
= v
[self
.e_start
:self
.e_end
] - self
.P127
# exp
403 """ decodes a latched value into sign / exponent / mantissa
405 bias is subtracted here, from the exponent. exponent
406 is extended to 10 bits so that subtract 127 is done on
409 args
= [0] * self
.m_extra
+ [v
[0:self
.e_start
]] # pad with extra zeros
410 #print ("decode", self.e_end)
411 return [self
.m
.eq(Cat(*args
)), # mantissa
412 self
.e
.eq(v
[self
.e_start
:self
.e_end
] - self
.P127
), # exp
413 self
.s
.eq(v
[-1]), # sign
416 def shift_down(self
, inp
):
417 """ shifts a mantissa down by one. exponent is increased to compensate
419 accuracy is lost as a result in the mantissa however there are 3
420 guard bits (the latter of which is the "sticky" bit)
422 return [self
.e
.eq(inp
.e
+ 1),
423 self
.m
.eq(Cat(inp
.m
[0] | inp
.m
[1], inp
.m
[2:], 0))
426 def shift_down_multi(self
, diff
, inp
=None):
427 """ shifts a mantissa down. exponent is increased to compensate
429 accuracy is lost as a result in the mantissa however there are 3
430 guard bits (the latter of which is the "sticky" bit)
432 this code works by variable-shifting the mantissa by up to
433 its maximum bit-length: no point doing more (it'll still be
436 the sticky bit is computed by shifting a batch of 1s by
437 the same amount, which will introduce zeros. it's then
438 inverted and used as a mask to get the LSBs of the mantissa.
439 those are then |'d into the sticky bit.
443 sm
= MultiShift(self
.width
)
444 mw
= Const(self
.m_width
-1, len(diff
))
445 maxslen
= Mux(diff
> mw
, mw
, diff
)
446 rs
= sm
.rshift(inp
.m
[1:], maxslen
)
447 maxsleni
= mw
- maxslen
448 m_mask
= sm
.rshift(self
.m1s
[1:], maxsleni
) # shift and invert
450 #stickybit = reduce(or_, inp.m[1:] & m_mask) | inp.m[0]
451 stickybit
= (inp
.m
[1:] & m_mask
).bool() | inp
.m
[0]
452 return [self
.e
.eq(inp
.e
+ diff
),
453 self
.m
.eq(Cat(stickybit
, rs
))
456 def shift_up_multi(self
, diff
):
457 """ shifts a mantissa up. exponent is decreased to compensate
459 sm
= MultiShift(self
.width
)
460 mw
= Const(self
.m_width
, len(diff
))
461 maxslen
= Mux(diff
> mw
, mw
, diff
)
463 return [self
.e
.eq(self
.e
- diff
),
464 self
.m
.eq(sm
.lshift(self
.m
, maxslen
))
467 class Trigger(Elaboratable
):
470 self
.stb
= Signal(reset
=0)
472 self
.trigger
= Signal(reset_less
=True)
474 def elaborate(self
, platform
):
476 m
.d
.comb
+= self
.trigger
.eq(self
.stb
& self
.ack
)
480 return [self
.stb
.eq(inp
.stb
),
485 return [self
.stb
, self
.ack
]
488 class FPOpIn(PrevControl
):
489 def __init__(self
, width
):
490 PrevControl
.__init
__(self
)
492 self
.v
= Signal(width
)
495 def chain_inv(self
, in_op
, extra
=None):
497 if extra
is not None:
499 return [self
.v
.eq(in_op
.v
), # receive value
500 self
.stb
.eq(stb
), # receive STB
501 in_op
.ack
.eq(~self
.ack
), # send ACK
504 def chain_from(self
, in_op
, extra
=None):
506 if extra
is not None:
508 return [self
.v
.eq(in_op
.v
), # receive value
509 self
.stb
.eq(stb
), # receive STB
510 in_op
.ack
.eq(self
.ack
), # send ACK
514 class FPOpOut(NextControl
):
515 def __init__(self
, width
):
516 NextControl
.__init
__(self
)
518 self
.v
= Signal(width
)
521 def chain_inv(self
, in_op
, extra
=None):
523 if extra
is not None:
525 return [self
.v
.eq(in_op
.v
), # receive value
526 self
.stb
.eq(stb
), # receive STB
527 in_op
.ack
.eq(~self
.ack
), # send ACK
530 def chain_from(self
, in_op
, extra
=None):
532 if extra
is not None:
534 return [self
.v
.eq(in_op
.v
), # receive value
535 self
.stb
.eq(stb
), # receive STB
536 in_op
.ack
.eq(self
.ack
), # send ACK
540 class Overflow
: #(Elaboratable):
542 self
.guard
= Signal(reset_less
=True) # tot[2]
543 self
.round_bit
= Signal(reset_less
=True) # tot[1]
544 self
.sticky
= Signal(reset_less
=True) # tot[0]
545 self
.m0
= Signal(reset_less
=True) # mantissa zero bit
547 self
.roundz
= Signal(reset_less
=True)
556 return [self
.guard
.eq(inp
.guard
),
557 self
.round_bit
.eq(inp
.round_bit
),
558 self
.sticky
.eq(inp
.sticky
),
561 def elaborate(self
, platform
):
563 m
.d
.comb
+= self
.roundz
.eq(self
.guard
& \
564 (self
.round_bit | self
.sticky | self
.m0
))
569 """ IEEE754 Floating Point Base Class
571 contains common functions for FP manipulation, such as
572 extracting and packing operands, normalisation, denormalisation,
576 def get_op(self
, m
, op
, v
, next_state
):
577 """ this function moves to the next state and copies the operand
578 when both stb and ack are 1.
579 acknowledgement is sent by setting ack to ZERO.
583 with m
.If((op
.ready_o
) & (op
.valid_i_test
)):
585 # op is latched in from FPNumIn class on same ack/stb
586 m
.d
.comb
+= ack
.eq(0)
588 m
.d
.comb
+= ack
.eq(1)
591 def denormalise(self
, m
, a
):
592 """ denormalises a number. this is probably the wrong name for
593 this function. for normalised numbers (exponent != minimum)
594 one *extra* bit (the implicit 1) is added *back in*.
595 for denormalised numbers, the mantissa is left alone
596 and the exponent increased by 1.
598 both cases *effectively multiply the number stored by 2*,
599 which has to be taken into account when extracting the result.
601 with m
.If(a
.exp_n127
):
602 m
.d
.sync
+= a
.e
.eq(a
.N126
) # limit a exponent
604 m
.d
.sync
+= a
.m
[-1].eq(1) # set top mantissa bit
606 def op_normalise(self
, m
, op
, next_state
):
607 """ operand normalisation
608 NOTE: just like "align", this one keeps going round every clock
609 until the result's exponent is within acceptable "range"
611 with m
.If((op
.m
[-1] == 0)): # check last bit of mantissa
613 op
.e
.eq(op
.e
- 1), # DECREASE exponent
614 op
.m
.eq(op
.m
<< 1), # shift mantissa UP
619 def normalise_1(self
, m
, z
, of
, next_state
):
620 """ first stage normalisation
622 NOTE: just like "align", this one keeps going round every clock
623 until the result's exponent is within acceptable "range"
624 NOTE: the weirdness of reassigning guard and round is due to
625 the extra mantissa bits coming from tot[0..2]
627 with m
.If((z
.m
[-1] == 0) & (z
.e
> z
.N126
)):
629 z
.e
.eq(z
.e
- 1), # DECREASE exponent
630 z
.m
.eq(z
.m
<< 1), # shift mantissa UP
631 z
.m
[0].eq(of
.guard
), # steal guard bit (was tot[2])
632 of
.guard
.eq(of
.round_bit
), # steal round_bit (was tot[1])
633 of
.round_bit
.eq(0), # reset round bit
639 def normalise_2(self
, m
, z
, of
, next_state
):
640 """ second stage normalisation
642 NOTE: just like "align", this one keeps going round every clock
643 until the result's exponent is within acceptable "range"
644 NOTE: the weirdness of reassigning guard and round is due to
645 the extra mantissa bits coming from tot[0..2]
647 with m
.If(z
.e
< z
.N126
):
649 z
.e
.eq(z
.e
+ 1), # INCREASE exponent
650 z
.m
.eq(z
.m
>> 1), # shift mantissa DOWN
653 of
.round_bit
.eq(of
.guard
),
654 of
.sticky
.eq(of
.sticky | of
.round_bit
)
659 def roundz(self
, m
, z
, roundz
):
660 """ performs rounding on the output. TODO: different kinds of rounding
663 m
.d
.sync
+= z
.m
.eq(z
.m
+ 1) # mantissa rounds up
664 with m
.If(z
.m
== z
.m1s
): # all 1s
665 m
.d
.sync
+= z
.e
.eq(z
.e
+ 1) # exponent rounds up
667 def corrections(self
, m
, z
, next_state
):
668 """ denormalisation and sign-bug corrections
671 # denormalised, correct exponent to zero
672 with m
.If(z
.is_denormalised
):
673 m
.d
.sync
+= z
.e
.eq(z
.N127
)
675 def pack(self
, m
, z
, next_state
):
676 """ packs the result into the output (detects overflow->Inf)
679 # if overflow occurs, return inf
680 with m
.If(z
.is_overflowed
):
681 m
.d
.sync
+= z
.inf(z
.s
)
683 m
.d
.sync
+= z
.create(z
.s
, z
.e
, z
.m
)
685 def put_z(self
, m
, z
, out_z
, next_state
):
686 """ put_z: stores the result in the output. raises stb and waits
687 for ack to be set to 1 before moving to the next state.
688 resets stb back to zero when that occurs, as acknowledgement.
693 with m
.If(out_z
.o_valid
& out_z
.i_ready_test
):
694 m
.d
.sync
+= out_z
.o_valid
.eq(0)
697 m
.d
.sync
+= out_z
.o_valid
.eq(1)
700 class FPState(FPBase
):
701 def __init__(self
, state_from
):
702 self
.state_from
= state_from
704 def set_inputs(self
, inputs
):
706 for k
,v
in inputs
.items():
709 def set_outputs(self
, outputs
):
710 self
.outputs
= outputs
711 for k
,v
in outputs
.items():
716 def __init__(self
, id_wid
):
719 self
.in_mid
= Signal(id_wid
, reset_less
=True)
720 self
.out_mid
= Signal(id_wid
, reset_less
=True)
726 if self
.id_wid
is not None:
727 m
.d
.sync
+= self
.out_mid
.eq(self
.in_mid
)