--- /dev/null
+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))
+# 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
--- /dev/null
+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