+ n1 = self.add_state(FPNormToPack(self.width, self.id_wid))
+ n1.setup(m, alm.out_z, alm.out_of, alm.in_mid)
+
+ ppz = self.add_state(FPPutZ("pack_put_z", n1.out_z, self.out_z,
+ n1.in_mid, self.out_mid))
+
+ pz = self.add_state(FPPutZ("put_z", sc.out_z, self.out_z,
+ sc.in_mid, self.out_mid))
+
+
+class FPADDBase(FPState, FPID):
+
+ def __init__(self, width, id_wid=None, single_cycle=False):
+ """ IEEE754 FP Add
+
+ * width: bit-width of IEEE754. supported: 16, 32, 64
+ * id_wid: an identifier that is sync-connected to the input
+ * single_cycle: True indicates each stage to complete in 1 clock
+ """
+ FPID.__init__(self, id_wid)
+ FPState.__init__(self, "fpadd")
+ self.width = width
+ self.single_cycle = single_cycle
+ self.mod = FPADDBaseMod(width, id_wid, single_cycle)
+
+ self.in_t = Trigger()
+ self.in_a = Signal(width)
+ self.in_b = Signal(width)
+ #self.out_z = FPOp(width)
+
+ self.z_done = Signal(reset_less=True) # connects to out_z Strobe
+ self.in_accept = Signal(reset_less=True)
+ self.add_stb = Signal(reset_less=True)
+ self.add_ack = Signal(reset=0, reset_less=True)
+
+ def setup(self, m, a, b, add_stb, in_mid, out_z, out_mid):
+ self.out_z = out_z
+ self.out_mid = out_mid
+ m.d.comb += [self.in_a.eq(a),
+ self.in_b.eq(b),
+ self.mod.in_a.eq(self.in_a),
+ self.mod.in_b.eq(self.in_b),
+ self.in_mid.eq(in_mid),
+ self.mod.in_mid.eq(self.in_mid),
+ self.z_done.eq(self.mod.out_z.trigger),
+ #self.add_stb.eq(add_stb),
+ self.mod.in_t.stb.eq(self.in_t.stb),
+ self.in_t.ack.eq(self.mod.in_t.ack),
+ self.out_mid.eq(self.mod.out_mid),
+ self.out_z.v.eq(self.mod.out_z.v),
+ self.out_z.stb.eq(self.mod.out_z.stb),
+ self.mod.out_z.ack.eq(self.out_z.ack),
+ ]
+
+ m.d.sync += self.add_stb.eq(add_stb)
+ m.d.sync += self.add_ack.eq(0) # sets to zero when not in active state
+ #m.d.sync += self.in_t.stb.eq(0)
+
+ m.submodules.fpadd = self.mod
+
+ def action(self, m):
+
+ # in_accept is set on incoming strobe HIGH and ack LOW.
+ m.d.comb += self.in_accept.eq((~self.add_ack) & (self.add_stb))
+
+ #with m.If(self.in_t.ack):
+ # m.d.sync += self.in_t.stb.eq(0)
+ with m.If(~self.z_done):
+ # not done: test for accepting an incoming operand pair
+ with m.If(self.in_accept):
+ m.d.sync += [
+ self.add_ack.eq(1), # acknowledge receipt...
+ self.in_t.stb.eq(1), # initiate add
+ ]
+ with m.Else():
+ m.d.sync += [self.add_ack.eq(0),
+ self.in_t.stb.eq(0),
+ ]
+ with m.Else():
+ # done: acknowledge, and write out id and value
+ m.d.sync += [self.add_ack.eq(1),
+ self.in_t.stb.eq(0)
+ ]
+ m.next = "get_a"
+
+ return
+
+ if self.in_mid is not None:
+ m.d.sync += self.out_mid.eq(self.mod.out_mid)
+
+ m.d.sync += [
+ self.out_z.v.eq(self.mod.out_z.v)
+ ]
+ # move to output state on detecting z ack
+ with m.If(self.out_z.trigger):
+ m.d.sync += self.out_z.stb.eq(0)
+ m.next = "put_z"
+ with m.Else():
+ m.d.sync += self.out_z.stb.eq(1)
+
+
+class FPADD(FPID):
+ """ FPADD: stages as follows:
+
+ FPGetOp (a)
+ |
+ FPGetOp (b)
+ |
+ FPAddBase---> FPAddBaseMod
+ | |
+ PutZ GetOps->Specials->Align->Add1/2->Norm->Round/Pack->PutZ
+
+ FPAddBase is tricky: it is both a stage and *has* stages.
+ Connection to FPAddBaseMod therefore requires an in stb/ack
+ and an out stb/ack. Just as with Add1-Norm1 interaction, FPGetOp
+ needs to be the thing that raises the incoming stb.
+ """
+
+ def __init__(self, width, id_wid=None, single_cycle=False):
+ """ IEEE754 FP Add
+
+ * width: bit-width of IEEE754. supported: 16, 32, 64
+ * id_wid: an identifier that is sync-connected to the input
+ * single_cycle: True indicates each stage to complete in 1 clock
+ """
+ self.width = width
+ self.id_wid = id_wid
+ self.single_cycle = single_cycle
+
+ self.ids = FPID(id_wid)
+ self.in_a = FPOp(width)
+ self.in_b = FPOp(width)
+ self.out_z = FPOp(width)
+
+ self.states = []
+
+ def add_state(self, state):
+ self.states.append(state)
+ return state
+
+ def get_fragment(self, platform=None):
+ """ creates the HDL code-fragment for FPAdd
+ """
+ m = Module()
+ m.submodules.in_a = self.in_a
+ m.submodules.in_b = self.in_b
+ m.submodules.out_z = self.out_z
+
+ geta = self.add_state(FPGetOp("get_a", "get_b",
+ self.in_a, self.width))
+ geta.setup(m, self.in_a)
+ a = geta.out_op
+
+ getb = self.add_state(FPGetOp("get_b", "fpadd",
+ self.in_b, self.width))
+ getb.setup(m, self.in_b)
+ b = getb.out_op