+ get = self.add_state(FPGet2Op("get_ops", "special_cases",
+ self.in_a, self.in_b, self.width))
+ get.setup(m, self.in_a, self.in_b, self.in_t.stb, self.in_t.ack)
+ a = get.out_op1
+ b = get.out_op2
+
+ sc = self.add_state(FPAddSpecialCasesDeNorm(self.width, self.id_wid))
+ sc.setup(m, a, b, self.in_mid)
+
+ alm = self.add_state(FPAddAlignSingleAdd(self.width, self.id_wid))
+ alm.setup(m, sc.out_a, sc.out_b, sc.in_mid)
+
+ 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.out_z.ack.eq(0) # likewise
+ #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),
+ self.out_z.ack.eq(1),
+ ]
+ 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 = "put_z"