From: Michael Nolan Date: Tue, 31 Mar 2020 19:47:52 +0000 (-0400) Subject: Add test for sin_cos.py X-Git-Tag: ls180-24jan2020~108 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cb7e438d901869fbfe5fc8b2745b427f9e817532;p=ieee754fpu.git Add test for sin_cos.py --- diff --git a/src/ieee754/cordic/fptan.py b/src/ieee754/cordic/fptan.py deleted file mode 100644 index d3f54ccd..00000000 --- a/src/ieee754/cordic/fptan.py +++ /dev/null @@ -1,76 +0,0 @@ -from nmigen import Module, Elaboratable, Signal, Cat, Mux -from nmigen.cli import rtlil -import math -from enum import Enum, unique - -class CordicState(Enum): - WAITING = 0 - RUNNING = 1 - - -class CORDIC(Elaboratable): - def __init__(self, fracbits): - self.fracbits = fracbits - self.M = M = (1<> i) - sync += dx.eq(y >> i) - - return m - def ports(self): - return [self.cos, self.sin, self.z0, - self.ready, self.start] - -if __name__ == '__main__': - dut = CORDIC(8) - vl = rtlil.convert(dut, ports=dut.ports()) - with open("cordic.il", "w") as f: - f.write(vl) - diff --git a/src/ieee754/cordic/sin_cos.py b/src/ieee754/cordic/sin_cos.py new file mode 100644 index 00000000..7e72808b --- /dev/null +++ b/src/ieee754/cordic/sin_cos.py @@ -0,0 +1,113 @@ +from nmigen import Module, Elaboratable, Signal, Memory +from nmigen.cli import rtlil +import math +from enum import Enum, unique + + +@unique +class CordicState(Enum): + WAITING = 0 + RUNNING = 1 + + +class CordicROM(Elaboratable): + def __init__(self, fracbits, iterations): + self.fracbits = fracbits + self.iterations = iterations + + M = 1 << fracbits + self.addr = Signal(range(iterations)) + self.data = Signal(range(-M, M-1)) + + angles = [int(round(M*math.atan(2**(-i)))) + for i in range(self.iterations)] + + self.mem = Memory(width=self.data.width, + depth=self.iterations, + init=angles) + + def elaborate(self, platform): + m = Module() + m.submodules.rdport = rdport = self.mem.read_port() + m.d.comb += rdport.addr.eq(self.addr) + m.d.comb += self.data.eq(rdport.data) + return m + + +class CORDIC(Elaboratable): + def __init__(self, fracbits): + self.fracbits = fracbits + self.M = M = (1 << fracbits) + self.ZMAX = ZMAX = int(round(self.M * math.pi/2)) + + # sin/cos output in 0.ffffff format + self.cos = Signal(range(-M, M-1)) + self.sin = Signal(range(-M, M-1)) + # angle input + self.z0 = Signal(range(-ZMAX, ZMAX), reset_less=True) + + # cordic start flag + self.start = Signal(reset_less=True) + # cordic done/ready for input + self.ready = Signal() + + self.width = self.z0.width + self.iterations = self.width - 1 + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + sync = m.d.sync + + + # Calculate initial amplitude? + An = 1.0 + for i in range(self.iterations): + An *= math.sqrt(1 + 2**(-2*i)) + + X0 = int(round(self.M*1/An)) + x = Signal(self.sin.shape()) + y = Signal(self.sin.shape()) + z = Signal(self.z0.shape()) + dx = Signal(self.sin.shape()) + dy = Signal(self.sin.shape()) + dz = Signal(self.z0.shape()) + i = Signal(range(self.iterations)) + + state = Signal(CordicState) + + m.submodules.anglerom = anglerom = \ + CordicROM(self.fracbits, self.iterations) + comb += anglerom.addr.eq(i) + + with m.If(state == CordicState.WAITING): + with m.If(self.start): + sync += x.eq(X0) + sync += y.eq(0) + sync += z.eq(self.z0) + sync += i.eq(0) + sync += self.ready.eq(0) + sync += state.eq(CordicState.RUNNING) + with m.If(state == CordicState.RUNNING): + sync += dx.eq(x >> i) + sync += dx.eq(y >> i) + sync += dz.eq(anglerom.data) + with m.If(i == self.iterations - 1): + sync += self.cos.eq(x) + sync += self.sin.eq(y) + sync += state.eq(CordicState.WAITING) + sync += self.ready.eq(1) + with m.Else(): + sync += i.eq(i+1) + return m + + def ports(self): + return [self.cos, self.sin, self.z0, + self.ready, self.start] + +if __name__ == '__main__': + dut = CORDIC(8) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("cordic.il", "w") as f: + f.write(vl) + diff --git a/src/ieee754/cordic/test/test_sincos.py b/src/ieee754/cordic/test/test_sincos.py new file mode 100644 index 00000000..07ebc80a --- /dev/null +++ b/src/ieee754/cordic/test/test_sincos.py @@ -0,0 +1,41 @@ +from nmigen import Module, Signal +from nmigen.back.pysim import Simulator, Delay +from nmigen.test.utils import FHDLTestCase + +from ieee754.cordic.sin_cos import CORDIC +import unittest + +class SinCosTestCase(FHDLTestCase): + def test_sincos(self): + m = Module() + + fracbits = 8 + + m.submodules.dut = dut = CORDIC(fracbits) + z = Signal(dut.z0.shape()) + start = Signal() + + sin = Signal(dut.sin.shape()) + cos = Signal(dut.cos.shape()) + ready = Signal() + + m.d.comb += [ + dut.z0.eq(z), + dut.start.eq(start), + sin.eq(dut.sin), + cos.eq(dut.cos), + ready.eq(dut.ready)] + + sim = Simulator(m) + sim.add_clock(1e-6) + + def process(): + for i in range(10): + yield + sim.add_sync_process(process) + with sim.write_vcd("sin_cos.vcd", "sin_cos.gtkw", traces=[ + z, cos, sin, ready, start]): + sim.run() + +if __name__ == "__main__": + unittest.main()