From: Luke Kenneth Casson Leighton Date: Sun, 17 Feb 2019 07:42:23 +0000 (+0000) Subject: add double-width divide as well, and preliminary unit test X-Git-Tag: ls180-24jan2020~1933 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aa66b492fd25d9750ad331eb9ffdc6f80ae342ee;p=ieee754fpu.git add double-width divide as well, and preliminary unit test --- diff --git a/src/add/nmigen_div_experiment.py b/src/add/nmigen_div_experiment.py index 918713a0..3ae7a51f 100644 --- a/src/add/nmigen_div_experiment.py +++ b/src/add/nmigen_div_experiment.py @@ -14,7 +14,7 @@ class Div: self.dor = Signal(width) # divisor self.dend = Signal(width) # dividend self.rem = Signal(width) # remainder - self.count = Signal(6) # loop count + self.count = Signal(7) # loop count self.czero = Const(0, width) @@ -22,7 +22,7 @@ class Div: m.d.sync += [ self.quot.eq(self.czero), self.rem.eq(self.czero), - self.count.eq(Const(0, 6)) + self.count.eq(Const(0, 7)) ] @@ -46,7 +46,7 @@ class FPDIV(FPBase): b = FPNum(self.width, False) z = FPNum(self.width, False) - div = Div(51) + div = Div(a.m_width*2 + 3) # double the mantissa width plus g/r/sticky of = Overflow() @@ -135,7 +135,7 @@ class FPDIV(FPBase): m.d.sync += [ z.s.eq(a.s ^ b.s), # sign z.e.eq(a.e - b.e), # exponent - div.dend.eq(a.m<<27), + div.dend.eq(a.m<<(a.m_width+3)), # 3 bits for g/r/sticky div.dor.eq(b.m), ] div.reset(m) @@ -147,7 +147,7 @@ class FPDIV(FPBase): m.next = "divide_2" m.d.sync += [ div.quot.eq(div.quot << 1), - div.rem.eq(Cat(div.dend[50], div.rem[0:])), + div.rem.eq(Cat(div.dend[-1], div.rem[0:])), div.dend.eq(div.dend << 1), ] @@ -176,7 +176,7 @@ class FPDIV(FPBase): with m.State("divide_3"): m.next = "normalise_1" m.d.sync += [ - z.m.eq(div.quot[3:27]), + z.m.eq(div.quot[3:]), of.guard.eq(div.quot[2]), of.round_bit.eq(div.quot[1]), of.sticky.eq(div.quot[0] | (div.rem != 0)) diff --git a/src/add/test_div64.py b/src/add/test_div64.py new file mode 100644 index 00000000..bc5bd47e --- /dev/null +++ b/src/add/test_div64.py @@ -0,0 +1,67 @@ +from nmigen import Module, Signal +from nmigen.compat.sim import run_simulation + +from nmigen_div_experiment import FPDIV + +class ORGate: + def __init__(self): + self.a = Signal() + self.b = Signal() + self.x = Signal() + + def get_fragment(self, platform=None): + + m = Module() + m.d.comb += self.x.eq(self.a | self.b) + + return m + +def check_case(dut, a, b, z): + yield dut.in_a.v.eq(a) + yield dut.in_a.stb.eq(1) + yield + yield + a_ack = (yield dut.in_a.ack) + assert a_ack == 0 + yield dut.in_b.v.eq(b) + yield dut.in_b.stb.eq(1) + b_ack = (yield dut.in_b.ack) + assert b_ack == 0 + + while True: + yield + out_z_stb = (yield dut.out_z.stb) + if not out_z_stb: + continue + yield dut.in_a.stb.eq(0) + yield dut.in_b.stb.eq(0) + yield dut.out_z.ack.eq(1) + yield + yield dut.out_z.ack.eq(0) + yield + yield + break + + out_z = yield dut.out_z.v + assert out_z == z, "Output z 0x%x not equal to expected 0x%x" % (out_z, z) + +def testbench(dut): + yield from check_case(dut, 0x4008000000000000, 0x3FF0000000000000, + 0x4008000000000000) + yield from check_case(dut, 0x3FF0000000000000, 0x4008000000000000, + 0x3FD5555555555555) + + if False: + yield from check_case(dut, 0x3F800000, 0x40000000, 0x3F000000) + yield from check_case(dut, 0x3F800000, 0x40400000, 0x3EAAAAAB) + yield from check_case(dut, 0x40400000, 0x41F80000, 0x3DC6318C) + yield from check_case(dut, 0x41F9EB4D, 0x429A4C70, 0x3ECF52B2) + yield from check_case(dut, 0x7F7FFFFE, 0x70033181, 0x4EF9C4C8) + yield from check_case(dut, 0x7F7FFFFE, 0x70000001, 0x4EFFFFFC) + yield from check_case(dut, 0x7F7FFCFF, 0x70200201, 0x4ECCC7D5) + yield from check_case(dut, 0x70200201, 0x7F7FFCFF, 0x302003E2) + +if __name__ == '__main__': + dut = FPDIV(width=64) + run_simulation(dut, testbench(dut), vcd_name="test_div64.vcd") +