Begin work on pipelined cordic
authorMichael Nolan <mtnolan2640@gmail.com>
Wed, 1 Apr 2020 15:13:45 +0000 (11:13 -0400)
committerMichael Nolan <mtnolan2640@gmail.com>
Wed, 1 Apr 2020 15:13:45 +0000 (11:13 -0400)
src/ieee754/cordic/pipe_data.py [new file with mode: 0644]
src/ieee754/cordic/sin_cos.py
src/ieee754/cordic/sin_cos_pipe_stage.py [new file with mode: 0644]

diff --git a/src/ieee754/cordic/pipe_data.py b/src/ieee754/cordic/pipe_data.py
new file mode 100644 (file)
index 0000000..2ed23d6
--- /dev/null
@@ -0,0 +1,29 @@
+from nmigen import Signal
+import math
+
+
+class CordicData:
+
+    def __init__(self, pspec):
+
+        M = pspec.M
+        ZMAX = pspec.ZMAX
+        self.x = Signal(range(-M, M+1), name="x")   # operand a
+        self.y = Signal(range(-M, M+1), name="y")   # operand b
+        self.z = Signal(range(-ZMAX, ZMAX), name="z")     # denormed result
+
+    def __iter__(self):
+        yield from self.x
+        yield from self.y
+        yield from self.z
+
+    def eq(self, i):
+        ret = [self.z.eq(i.z), self.x.eq(i.x), self.y.eq(i.y)]
+        return ret
+
+
+class CordicPipeSpec:
+    def __init__(self, fracbits):
+        self.fracbits = fracbits
+        self.M = (1 << fracbits)
+        self.ZMAX = int(round(self.M * math.pi/2))
index dbe5a18a835691c900cf824c9aaba2629aa195e5..cbcef5ae3ef4f11c5a6d8630f51f2e282b76d843 100644 (file)
@@ -1,3 +1,7 @@
+# This is an unpipelined version of an sin/cos cordic, which will
+# later be used to verify the operation of a pipelined version
+
+# see http://bugs.libre-riscv.org/show_bug.cgi?id=208
 from nmigen import Module, Elaboratable, Signal, Memory, signed
 from nmigen.cli import rtlil
 import math
diff --git a/src/ieee754/cordic/sin_cos_pipe_stage.py b/src/ieee754/cordic/sin_cos_pipe_stage.py
new file mode 100644 (file)
index 0000000..216b019
--- /dev/null
@@ -0,0 +1,41 @@
+from nmigen import Module, Signal, Cat, Mux
+from nmutil.pipemodbase import PipeModBase
+from ieee754.cordic.pipe_data import CordicData
+import math
+
+
+class CordicStage(PipeModBase):
+    def __init__(self, pspec, stagenum):
+        super().__init__(pspec, "cordicstage%d" % stagenum)
+        self.stagenum = stagenum
+
+    def ispec(self):
+        return CordicData(self.pspec, False)
+
+    def ospec(self):
+        return CordicData(self.pspec, False)
+
+    def elaborate(self, platform):
+        m = Module()
+        comb = m.d.comb
+
+        dx = Signal(self.i.x.shape())
+        dy = Signal(self.i.y.shape())
+        dz = Signal(self.i.z.shape())
+        angle = int(round(self.pspec.M *
+                          math.atan(2**(-self.stagenum))))
+
+        comb += dx.eq(self.i.y >> self.stagenum)
+        comb += dy.eq(self.i.x >> self.stagenum)
+        comb += dz.eq(angle)
+
+        with m.If(self.i.z >= 0):
+            comb += self.o.x.eq(self.i.x - dx)
+            comb += self.o.y.eq(self.i.y + dy)
+            comb += self.o.z.eq(self.i.z - dz)
+        with m.Else():
+            comb += self.o.x.eq(self.i.x + dx)
+            comb += self.o.y.eq(self.i.y - dy)
+            comb += self.o.z.eq(self.i.z + dz)
+
+        return m