Add count leading zeros module (should probably go somewhere else)
[ieee754fpu.git] / src / ieee754 / cordic / clz.py
1 from nmigen import Module, Signal, Elaboratable, Cat, Repl
2 import math
3
4 class CLZ(Elaboratable):
5 def __init__(self, width):
6 self.width = width
7 self.sig_in = Signal(width, reset_less=True)
8 out_width = math.ceil(math.log2(width+1))
9 self.lz = Signal(out_width)
10
11 def generate_pairs(self, m):
12 comb = m.d.comb
13 assert self.width % 2 == 0 # TODO handle odd widths
14 pairs = []
15 for i in range(0, self.width, 2):
16 pair = Signal(2, name="pair%d" % i)
17 comb += pair.eq(self.sig_in[i:i+2])
18
19 pair_cnt = Signal(2, name="cnt_1_%d" % (i/2))
20 with m.Switch(pair):
21 with m.Case(0):
22 comb += pair_cnt.eq(2)
23 with m.Case(1):
24 comb += pair_cnt.eq(1)
25 with m.Default():
26 comb += pair_cnt.eq(0)
27 pairs.append(pair_cnt)
28 return pairs
29
30 def combine_pairs(self, m, iteration, pairs):
31 comb = m.d.comb
32 length = len(pairs)
33 assert length % 2 == 0 # TODO handle non powers of 2
34 ret = []
35 for i in range(0, length, 2):
36 left = pairs[i+1]
37 right = pairs[i]
38 width = left.width + 1
39 print(left)
40 print(f"pair({i}, {i+1}) - cnt_{iteration}_{i}")
41 new_pair = Signal(left.width + 1, name="cnt_%d_%d" %
42 (iteration, i))
43 with m.If(left[-1] == 1):
44 with m.If(right[-1] == 1):
45 comb += new_pair.eq(Cat(Repl(0, width-1), 1))
46 with m.Else():
47 comb += new_pair.eq(Cat(right[0:-1], 0b01))
48 with m.Else():
49 comb += new_pair.eq(Cat(left, 0))
50
51 ret.append(new_pair)
52 return ret
53
54 def elaborate(self, platform):
55 m = Module()
56 comb = m.d.comb
57
58 pairs = self.generate_pairs(m)
59 i = 2
60 while len(pairs) > 1:
61 pairs = self.combine_pairs(m, i, pairs)
62 i += 1
63
64 comb += self.lz.eq(pairs[0])
65
66 return m
67
68