From: Michael Nolan Date: Wed, 1 Apr 2020 15:13:45 +0000 (-0400) Subject: Begin work on pipelined cordic X-Git-Tag: ls180-24jan2020~104 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4a87a35d05ef709882e79df82b4872e2e44ec918;p=ieee754fpu.git Begin work on pipelined cordic --- diff --git a/src/ieee754/cordic/pipe_data.py b/src/ieee754/cordic/pipe_data.py new file mode 100644 index 00000000..2ed23d69 --- /dev/null +++ b/src/ieee754/cordic/pipe_data.py @@ -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)) diff --git a/src/ieee754/cordic/sin_cos.py b/src/ieee754/cordic/sin_cos.py index dbe5a18a..cbcef5ae 100644 --- a/src/ieee754/cordic/sin_cos.py +++ b/src/ieee754/cordic/sin_cos.py @@ -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 index 00000000..216b0193 --- /dev/null +++ b/src/ieee754/cordic/sin_cos_pipe_stage.py @@ -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