move gt_combiner out of experiments/
[ieee754fpu.git] / src / ieee754 / part_cmp / gt_combiner.py
diff --git a/src/ieee754/part_cmp/gt_combiner.py b/src/ieee754/part_cmp/gt_combiner.py
new file mode 100644 (file)
index 0000000..419a485
--- /dev/null
@@ -0,0 +1,76 @@
+from nmigen import Signal, Module, Elaboratable, Mux
+from ieee754.part_mul_add.partpoints import PartitionPoints
+
+class Combiner(Elaboratable):
+
+    def __init__(self):
+        self.ina = Signal()
+        self.inb = Signal()
+        self.sel = Signal()
+        self.outa = Signal()
+        self.outb = Signal()
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+
+        comb += self.outa.eq(Mux(self.sel, self.inb, self.ina))
+        comb += self.outb.eq(self.sel & self.ina)
+
+        return m
+
+# This is similar to EQCombiner, except that for a greater than
+# comparison, it needs to deal with both the greater than and equals
+# signals from each partition. The signals are combined using a
+# cascaded AND/OR to give the following effect:
+# When a partition is open, the output is set if either the current
+# partition's greater than flag is set, or the current partition's
+# equal flag is set AND the previous partition's greater than output
+# is true
+
+class GTCombiner(Elaboratable):
+
+    def __init__(self, width):
+        self.width = width
+
+        # These two signals allow this module to do more than just a
+        # partitioned greater than comparison.
+        # - If aux_input is set to 0 and gt_en is set to 1, then this
+        #   module performs a partitioned greater than comparision
+        # - If aux_input is set to 1 and gt_en is set to 0, then this
+        #   module is functionally equivalent to the eq_combiner
+        #   module.
+        # - If aux_input is set to 1 and gt_en is set to 1, then this
+        #   module performs a partitioned greater than or equals
+        #   comparison
+        self.aux_input = Signal(reset_less=True)  # right hand side mux input
+        self.gt_en = Signal(reset_less=True)      # enable or disable gt signal
+
+        self.eqs = Signal(width, reset_less=True) # the flags for EQ
+        self.gts = Signal(width, reset_less=True) # the flags for GT
+        self.gates = Signal(width-1, reset_less=True)
+        self.outputs = Signal(width, reset_less=True)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+
+        previnput = (self.gts[0] & self.gt_en) | (self.eqs[0] & self.aux_input)
+
+        for i in range(self.width-1):
+            m.submodules["mux%d" % i] = mux = Combiner()
+
+            comb += mux.ina.eq(previnput)
+            comb += mux.inb.eq(self.aux_input)
+            comb += mux.sel.eq(self.gates[i])
+            comb += self.outputs[i].eq(mux.outb)
+            previnput = (self.gts[i+1] & self.gt_en) | \
+                        (self.eqs[i+1] & mux.outa)
+
+        comb += self.outputs[-1].eq(previnput)
+
+        return m
+
+    def ports(self):
+        return [self.eqs, self.gts, self.gates, self.outputs,
+                self.gt_en, self.aux_input]