# 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
+from nmigen import Module, Elaboratable, Signal, Memory, Cat, Repl, Mux
from nmigen.cli import rtlil
import math
from enum import Enum, unique
def __init__(self, width):
self.z0 = Signal(width, name="z0")
- self.z_record = FPNumBaseRecord(self.z0.width, m_extra=True)
+ self.z_record = FPNumBaseRecord(self.z0.width, False, name="z_record")
self.fracbits = 2 * self.z_record.m_width
self.M = M = (1 << self.fracbits)
self.ZMAX = int(round(self.M * math.pi/2))
+ self.z_out = Signal(range(-self.ZMAX, self.ZMAX-1))
# sin/cos output in 0.ffffff format
self.cos = Signal(range(-M, M+1), reset=0)
comb += self.sin.eq(y)
with m.If(state == CordicState.WAITING):
with m.If(self.start):
+ z_intermed = Signal(z_fixed.shape())
+ shifter = Signal(z_in.e.width)
+ comb += shifter.eq(-z_in.e)
+ # This converts z_in.m to a large fixed point
+ # integer. Right now, I'm ignoring denormals but they
+ # will be added back in when I convert this to the
+ # pipelined implementation (and I can use FPAddDenormMod)
+ comb += z_intermed.eq(Cat(Repl(0, self.fracbits - z_in.rmw),
+ z_in.m[:-1], 1))
+ sync += z_fixed.eq(z_intermed >> shifter)
sync += state.eq(CordicState.INIT)
- sync += z_fixed.eq(z_in.m << (self.fracbits - z_in.rmw))
+ sync += self.ready.eq(0)
with m.If(state == CordicState.INIT):
+ z_temp = Signal(z.shape(), reset_less=True)
+ comb += z_temp.eq(Mux(z_in.s, ~z_fixed + 1, z_fixed))
+ sync += z.eq(z_temp)
+ sync += self.z_out.eq(z_temp)
sync += x.eq(X0)
sync += y.eq(0)
- sync += z.eq(z_fixed)
sync += i.eq(0)
sync += state.eq(CordicState.RUNNING)
sync += anglerom.addr.eq(1)
+ sync += self.ready.eq(1) # debug
with m.If(state == CordicState.RUNNING):
with m.If(z >= 0):
sync += x.eq(x - dx)
m = Module()
- m.submodules.dut = dut = CORDIC(32)
+ m.submodules.dut = dut = CORDIC(16)
z = Signal(dut.z0.width)
start = Signal()
sim.add_clock(1e-6)
def process():
+ asserted = False
yield z.eq(zin.get_bits())
yield start.eq(1)
yield
for i in range(fracbits * 3):
rdy = yield ready
+ zo = yield dut.z_out
+ if rdy and not asserted:
+ frac = self.get_frac(zo, dut.z_out.width - 2)
+ print(f"{zo:x} {frac}")
+ self.assertEqual(str(frac), zin.__str__())
+ asserted = True
yield
sim.add_sync_process(process)
self.run_test(zin=z, fracbits=fracbits)
def test_1(self):
- x = Float32(1.0)
+ x = Float16(.31212)
+ print(x)
self.run_test_assert(x)
# def test_neg(self):
# self.run_test_assert(-6)
- # def test_rand(self):
- # fracbits = 16
- # M = (1 << fracbits)
- # ZMAX = int(round(M * math.pi/2))
- # for i in range(500):
- # z = random.randrange(-ZMAX, ZMAX-1)
- # self.run_test_assert(z, fracbits=fracbits)
+ def test_rand(self):
+ for i in range(500):
+ z = random.uniform(-1, 1)
+ f = Float16(z)
+ self.run_test_assert(f)
+ def get_frac(self, value, bits):
+ return value/(1 << bits)
if __name__ == "__main__":
unittest.main()