use shifter opcode
[soc.git] / src / experiment / alu_hier.py
1 from nmigen import Elaboratable, Signal, Module, Const
2 from nmigen.cli import main
3
4
5 class Adder(Elaboratable):
6 def __init__(self, width):
7 self.a = Signal(width)
8 self.b = Signal(width)
9 self.o = Signal(width)
10
11 def elaborate(self, platform):
12 m = Module()
13 m.d.comb += self.o.eq(self.a + self.b)
14 return m
15
16
17 class Subtractor(Elaboratable):
18 def __init__(self, width):
19 self.a = Signal(width)
20 self.b = Signal(width)
21 self.o = Signal(width)
22
23 def elaborate(self, platform):
24 m = Module()
25 m.d.comb += self.o.eq(self.a - self.b)
26 return m
27
28
29 class Multiplier(Elaboratable):
30 def __init__(self, width):
31 self.a = Signal(width)
32 self.b = Signal(width)
33 self.o = Signal(width)
34
35 def elaborate(self, platform):
36 m = Module()
37 m.d.comb += self.o.eq(self.a * self.b)
38 return m
39
40
41 class Shifter(Elaboratable):
42 def __init__(self, width):
43 self.width = width
44 self.a = Signal(width)
45 self.b = Signal(width)
46 self.o = Signal(width)
47
48 def elaborate(self, platform):
49 m = Module()
50 btrunc = Signal(self.width)
51 m.d.comb += btrunc.eq(self.b & Const((1<<self.width)-1))
52 m.d.comb += self.o.eq(self.a >> btrunc)
53 return m
54
55
56 class ALU(Elaboratable):
57 def __init__(self, width):
58 self.op = Signal(2)
59 self.a = Signal(width)
60 self.b = Signal(width)
61 self.o = Signal(width)
62 self.width = width
63
64 def elaborate(self, platform):
65 m = Module()
66 add = Adder(self.width)
67 sub = Subtractor(self.width)
68 mul = Multiplier(self.width)
69 shf = Shifter(self.width)
70
71 m.submodules.add = add
72 m.submodules.sub = sub
73 m.submodules.mul = mul
74 m.submodules.shf = shf
75 for mod in [add, sub, mul, shf]:
76 m.d.comb += [
77 mod.a.eq(self.a),
78 mod.b.eq(self.b),
79 ]
80 with m.Switch(self.op):
81 with m.Case(0):
82 m.d.comb += self.o.eq(add.o)
83 with m.Case(1):
84 m.d.comb += self.o.eq(sub.o)
85 with m.Case(2):
86 m.d.comb += self.o.eq(mul.o)
87 with m.Case(3):
88 m.d.comb += self.o.eq(shf.o)
89 return m
90
91
92 if __name__ == "__main__":
93 alu = ALU(width=16)
94 main(alu, ports=[alu.op, alu.a, alu.b, alu.o])