code-comments
[soclayout.git] / experiments10_verilog / add.py
1 # generate add.il ilang file with: python3 add.py
2 #
3
4 from nmigen import Elaboratable, Signal, Module, Const, DomainRenamer
5 from nmigen.cli import verilog
6
7 # to get c4m-jtag
8 # clone with $ git clone gitolite3@git.libre-soc.org:nmigen-soc.git
9 # $ git clone gitolite3@git.libre-soc.org:c4m-jtag.git
10 # for each: $ python3 setup.py develop # optional: --user
11
12 from c4m.nmigen.jtag.tap import TAP, IOType
13 from nmigen_soc.wishbone.sram import SRAM
14 from nmigen import Memory
15
16
17 class ADD(Elaboratable):
18 def __init__(self, width):
19 self.width = width
20 self.a = Signal(width)
21 self.b = Signal(width)
22 self.f = Signal(width)
23
24 # set up JTAG - use an irwidth of 4, up to 16 ircodes (1<<4).
25 # change this to add more Wishbone interfaces: see below
26 self.jtag = TAP(ir_width=4)
27 self.jtag.bus.tck.name = 'jtag_tck'
28 self.jtag.bus.tms.name = 'jtag_tms'
29 self.jtag.bus.tdo.name = 'jtag_tdo'
30 self.jtag.bus.tdi.name = 'jtag_tdi'
31
32 # have to create at least one shift register
33 self.sr = self.jtag.add_shiftreg(ircode=4, length=3)
34
35 # decide how many SRAMs you want to create (and what sizes)
36 # simply edit this before running "make lvx"
37 # try not to go above 3 because you run out of JTAG ircodes that way.
38 # if you really really must, then increase ir_width above, first
39 self.memsizes = []
40 #self.memsizes.append((32, 32)) # width, depth
41 self.memsizes.append((32, 16)) # width, depth
42 self.memsizes.append((32, 16)) # width, depth
43
44 # create and connect wishbone(s). okok, a better solution is to
45 # use a Wishbone Arbiter, and only have one WB bus.
46 self.wb = []
47 ircode = 5 # start at 5,6,7 then jump 11,12,13 then 14,15,16 etc. etc.
48 for i, (width, depth) in enumerate(self.memsizes):
49 ircodes = [ircode, ircode+1, ircode+2]
50 if ircode == 5:
51 # next one skips DMI (see below - 8,9,10 already used)
52 ircode = 11
53 else:
54 ircode += 3
55 wb = self.jtag.add_wishbone(ircodes=ircodes, features={'err'},
56 address_width=30, data_width=width,
57 granularity=8, # 8-bit wide
58 name="jtag_wb_%d" % i)
59 self.wb.append(wb)
60
61 # create DMI2JTAG (goes through to dmi_sim())
62 self.dmi = self.jtag.add_dmi(ircodes=[8, 9, 10])
63
64 # add iotypes
65 self.io_a_0 = self.jtag.add_io(name="a_0", iotype=IOType.In)
66 self.io_a_1 = self.jtag.add_io(name="a_1", iotype=IOType.In)
67 self.io_a_2 = self.jtag.add_io(name="a_2", iotype=IOType.In)
68 self.io_a_3 = self.jtag.add_io(name="a_3", iotype=IOType.In)
69 self.io_b_0 = self.jtag.add_io(name="b_0", iotype=IOType.In)
70 self.io_b_1 = self.jtag.add_io(name="b_1", iotype=IOType.In)
71 self.io_b_2 = self.jtag.add_io(name="b_2", iotype=IOType.In)
72 self.io_b_3 = self.jtag.add_io(name="b_3", iotype=IOType.In)
73 self.io_f_0 = self.jtag.add_io(name="f_0", iotype=IOType.Out)
74 self.io_f_1 = self.jtag.add_io(name="f_1", iotype=IOType.Out)
75 self.io_f_2 = self.jtag.add_io(name="f_2", iotype=IOType.Out)
76 self.io_f_3 = self.jtag.add_io(name="f_3", iotype=IOType.Out)
77
78 def elaborate(self, platform):
79 m = Module()
80
81 m.submodules.jtag = jtag = self.jtag
82 m.d.comb += self.sr.i.eq(self.sr.o) # loopback test
83
84 # connect inputs/outputs to pads
85 m.d.comb += self.io_a_0.pad.i.eq(self.a[0])
86 m.d.comb += self.io_a_1.pad.i.eq(self.a[1])
87 m.d.comb += self.io_a_2.pad.i.eq(self.a[2])
88 m.d.comb += self.io_a_3.pad.i.eq(self.a[3])
89 m.d.comb += self.io_b_0.pad.i.eq(self.b[0])
90 m.d.comb += self.io_b_1.pad.i.eq(self.b[1])
91 m.d.comb += self.io_b_2.pad.i.eq(self.b[2])
92 m.d.comb += self.io_b_3.pad.i.eq(self.b[3])
93 m.d.comb += self.f[0].eq(self.io_f_0.pad.o)
94 m.d.comb += self.f[1].eq(self.io_f_1.pad.o)
95 m.d.comb += self.f[2].eq(self.io_f_2.pad.o)
96 m.d.comb += self.f[3].eq(self.io_f_3.pad.o)
97
98 # internal signals (not external pads basically)
99 a = Signal(self.width)
100 b = Signal(self.width)
101 f = Signal(self.width)
102
103 # and now the internal signals to the core
104 m.d.comb += a[0].eq(self.io_a_0.core.i)
105 m.d.comb += a[1].eq(self.io_a_1.core.i)
106 m.d.comb += a[2].eq(self.io_a_2.core.i)
107 m.d.comb += a[3].eq(self.io_a_3.core.i)
108 m.d.comb += b[0].eq(self.io_b_0.core.i)
109 m.d.comb += b[1].eq(self.io_b_1.core.i)
110 m.d.comb += b[2].eq(self.io_b_2.core.i)
111 m.d.comb += b[3].eq(self.io_b_3.core.i)
112 m.d.comb += self.io_f_0.core.o.eq(f[0])
113 m.d.comb += self.io_f_1.core.o.eq(f[1])
114 m.d.comb += self.io_f_2.core.o.eq(f[2])
115 m.d.comb += self.io_f_3.core.o.eq(f[3])
116
117 # create Memories, each with their own individual JTAG bus
118 for i, (width, depth) in enumerate(self.memsizes):
119 memory = Memory(width=width, depth=depth)
120 sram = SRAM(memory=memory, granularity=8)
121 m.submodules['sram%d' % i] = sram
122 wb = self.wb[i]
123
124 m.d.comb += sram.bus.cyc.eq(wb.cyc)
125 m.d.comb += sram.bus.stb.eq(wb.stb)
126 m.d.comb += sram.bus.we.eq(wb.we)
127 m.d.comb += sram.bus.sel.eq(wb.sel)
128 m.d.comb += sram.bus.adr.eq(wb.adr)
129 m.d.comb += sram.bus.dat_w.eq(wb.dat_w)
130
131 m.d.comb += wb.ack.eq(sram.bus.ack)
132 m.d.comb += wb.dat_r.eq(sram.bus.dat_r)
133
134 # do a simple "add"
135 m.d.sync += f.eq(a + b)
136
137 return m
138
139
140 def create_verilog(dut, ports, test_name):
141 vl = verilog.convert(dut, name=test_name, ports=ports)
142 with open("%s.v" % test_name, "w") as f:
143 f.write(vl)
144
145 if __name__ == "__main__":
146 alu = DomainRenamer("sys")(ADD(width=4))
147 create_verilog(alu, [alu.a, alu.b, alu.f,
148 alu.jtag.bus.tck,
149 alu.jtag.bus.tms,
150 alu.jtag.bus.tdo,
151 alu.jtag.bus.tdi], "add")