add dummy pll to experiments10_verilog
[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 ClockSignal, ResetSignal)
6 from nmigen.cli import verilog
7
8 # to get c4m-jtag
9 # clone with $ git clone gitolite3@git.libre-soc.org:nmigen-soc.git
10 # $ git clone gitolite3@git.libre-soc.org:c4m-jtag.git
11 # for each: $ python3 setup.py develop # optional: --user
12
13 from c4m.nmigen.jtag.tap import TAP, IOType
14 from nmigen_soc.wishbone.sram import SRAM
15 from nmigen import Memory
16 from dummypll import DummyPLL
17
18
19 class Core(Elaboratable):
20 def __init__(self, width):
21 self.width = width
22 self.a = Signal(width)
23 self.b = Signal(width)
24 self.f = Signal(width)
25
26 # set up JTAG - use an irwidth of 4, up to 16 ircodes (1<<4).
27 # change this to add more Wishbone interfaces: see below
28 self.jtag = TAP(ir_width=4)
29 self.jtag.bus.tck.name = 'jtag_tck'
30 self.jtag.bus.tms.name = 'jtag_tms'
31 self.jtag.bus.tdo.name = 'jtag_tdo'
32 self.jtag.bus.tdi.name = 'jtag_tdi'
33
34 # have to create at least one shift register
35 self.sr = self.jtag.add_shiftreg(ircode=4, length=3)
36
37 # decide how many SRAMs you want to create (and what sizes)
38 # simply edit this before running "make lvx"
39 # try not to go above 3 because you run out of JTAG ircodes that way.
40 # if you really really must, then increase ir_width above, first
41 self.memsizes = []
42 #self.memsizes.append((32, 32)) # width, depth
43 self.memsizes.append((32, 16)) # width, depth
44 #self.memsizes.append((32, 16)) # width, depth
45
46 # create and connect wishbone(s). okok, a better solution is to
47 # use a Wishbone Arbiter, and only have one WB bus.
48 self.wb = []
49 ircode = 5 # start at 5,6,7 then jump 11,12,13 then 14,15,16 etc. etc.
50 for i, (width, depth) in enumerate(self.memsizes):
51 ircodes = [ircode, ircode+1, ircode+2]
52 if ircode == 5:
53 # next one skips DMI (see below - 8,9,10 already used)
54 ircode = 11
55 else:
56 ircode += 3
57 wb = self.jtag.add_wishbone(ircodes=ircodes, features={'err'},
58 address_width=30, data_width=width,
59 granularity=8, # 8-bit wide
60 name="jtag_wb_%d" % i)
61 self.wb.append(wb)
62
63 # create DMI2JTAG (goes through to dmi_sim())
64 self.dmi = self.jtag.add_dmi(ircodes=[8, 9, 10])
65
66 # add iotypes
67 self.io_a_0 = self.jtag.add_io(name="a_0", iotype=IOType.In)
68 self.io_a_1 = self.jtag.add_io(name="a_1", iotype=IOType.In)
69 self.io_a_2 = self.jtag.add_io(name="a_2", iotype=IOType.In)
70 self.io_a_3 = self.jtag.add_io(name="a_3", iotype=IOType.In)
71 self.io_b_0 = self.jtag.add_io(name="b_0", iotype=IOType.In)
72 self.io_b_1 = self.jtag.add_io(name="b_1", iotype=IOType.In)
73 self.io_b_2 = self.jtag.add_io(name="b_2", iotype=IOType.In)
74 self.io_b_3 = self.jtag.add_io(name="b_3", iotype=IOType.In)
75 self.io_f_0 = self.jtag.add_io(name="f_0", iotype=IOType.Out)
76 self.io_f_1 = self.jtag.add_io(name="f_1", iotype=IOType.Out)
77 self.io_f_2 = self.jtag.add_io(name="f_2", iotype=IOType.Out)
78 self.io_f_3 = self.jtag.add_io(name="f_3", iotype=IOType.Out)
79
80 def elaborate(self, platform):
81 m = Module()
82
83 # create JTAG module
84 m.submodules.jtag = jtag = self.jtag
85 m.d.comb += self.sr.i.eq(self.sr.o) # loopback test
86
87 # connect inputs/outputs to pads
88 m.d.comb += self.io_a_0.pad.i.eq(self.a[0])
89 m.d.comb += self.io_a_1.pad.i.eq(self.a[1])
90 m.d.comb += self.io_a_2.pad.i.eq(self.a[2])
91 m.d.comb += self.io_a_3.pad.i.eq(self.a[3])
92 m.d.comb += self.io_b_0.pad.i.eq(self.b[0])
93 m.d.comb += self.io_b_1.pad.i.eq(self.b[1])
94 m.d.comb += self.io_b_2.pad.i.eq(self.b[2])
95 m.d.comb += self.io_b_3.pad.i.eq(self.b[3])
96 m.d.comb += self.f[0].eq(self.io_f_0.pad.o)
97 m.d.comb += self.f[1].eq(self.io_f_1.pad.o)
98 m.d.comb += self.f[2].eq(self.io_f_2.pad.o)
99 m.d.comb += self.f[3].eq(self.io_f_3.pad.o)
100
101 # internal signals (not external pads basically)
102 a = Signal(self.width)
103 b = Signal(self.width)
104 f = Signal(self.width)
105
106 # and now the internal signals to the core
107 m.d.comb += a[0].eq(self.io_a_0.core.i)
108 m.d.comb += a[1].eq(self.io_a_1.core.i)
109 m.d.comb += a[2].eq(self.io_a_2.core.i)
110 m.d.comb += a[3].eq(self.io_a_3.core.i)
111 m.d.comb += b[0].eq(self.io_b_0.core.i)
112 m.d.comb += b[1].eq(self.io_b_1.core.i)
113 m.d.comb += b[2].eq(self.io_b_2.core.i)
114 m.d.comb += b[3].eq(self.io_b_3.core.i)
115 m.d.comb += self.io_f_0.core.o.eq(f[0])
116 m.d.comb += self.io_f_1.core.o.eq(f[1])
117 m.d.comb += self.io_f_2.core.o.eq(f[2])
118 m.d.comb += self.io_f_3.core.o.eq(f[3])
119
120 # create Memories, each with their own individual JTAG bus
121 for i, (width, depth) in enumerate(self.memsizes):
122 memory = Memory(width=width, depth=depth)
123 sram = SRAM(memory=memory, granularity=8)
124 m.submodules['sram%d' % i] = sram
125 wb = self.wb[i]
126
127 m.d.comb += sram.bus.cyc.eq(wb.cyc)
128 m.d.comb += sram.bus.stb.eq(wb.stb)
129 m.d.comb += sram.bus.we.eq(wb.we)
130 m.d.comb += sram.bus.sel.eq(wb.sel)
131 m.d.comb += sram.bus.adr.eq(wb.adr)
132 m.d.comb += sram.bus.dat_w.eq(wb.dat_w)
133
134 m.d.comb += wb.ack.eq(sram.bus.ack)
135 m.d.comb += wb.dat_r.eq(sram.bus.dat_r)
136
137 # do a simple "add"
138 m.d.sync += f.eq(a + b)
139
140 return m
141
142 class ADD(Elaboratable):
143 def __init__(self, width):
144 self.width = width
145 self.a = Signal(width)
146 self.b = Signal(width)
147 self.f = Signal(width)
148 self.jtag_tck = Signal(reset_less=True)
149 self.jtag_tms = Signal(reset_less=True)
150 self.jtag_tdi = Signal(reset_less=True)
151 self.jtag_tdo = Signal(reset_less=True)
152
153 # PLL input mode and test signals
154 self.a0 = Signal()
155 self.a1 = Signal()
156 self.pll_vco = Signal()
157 self.pll_test = Signal()
158
159 # QTY 1, dummy PLL
160 self.dummypll = DummyPLL(instance=True)
161
162 # core
163 self.core = Core(width)
164
165 def elaborate(self, platform):
166 m = Module()
167
168 # create PLL module
169 m.submodules.wrappll = pll = self.dummypll
170
171 # connect up PLL
172 sys_clk = ClockSignal()
173 m.d.comb += pll.clk_24_i.eq(sys_clk)
174 m.d.comb += pll.clk_sel_i[0].eq(self.a0)
175 m.d.comb += pll.clk_sel_i[1].eq(self.a1)
176 m.d.comb += self.pll_vco.eq(pll.pll_vco_o)
177 m.d.comb += self.pll_test.eq(pll.pll_test_o)
178
179 # create core module
180 dr = DomainRenamer("coresync")
181 m.submodules.core = core = dr(self.core)
182
183 # connect reset
184 sys_rst = ResetSignal()
185 core_rst = ResetSignal("coresync")
186 m.d.comb += core_rst.eq(sys_rst)
187
188 # connect core from PLL
189 core_clk = ClockSignal("coresync")
190 m.d.comb += core_clk.eq(pll.clk_pll_o)
191
192 # and now the internal signals to the core
193 m.d.comb += core.a.eq(self.a)
194 m.d.comb += core.b.eq(self.b)
195 m.d.comb += self.f.eq(core.f)
196
197 # and to JTAG
198 m.d.comb += self.jtag_tdo.eq(self.core.jtag.bus.tdo)
199 m.d.comb += self.core.jtag.bus.tdi.eq(self.jtag_tdi)
200 m.d.comb += self.core.jtag.bus.tms.eq(self.jtag_tms)
201 m.d.comb += self.core.jtag.bus.tck.eq(self.jtag_tck)
202 return m
203
204
205 def create_verilog(dut, ports, test_name):
206 vl = verilog.convert(dut, name=test_name, ports=ports)
207 with open("%s.v" % test_name, "w") as f:
208 f.write(vl)
209
210 if __name__ == "__main__":
211 alu = DomainRenamer("sys")(ADD(width=4))
212 create_verilog(alu, [alu.a, alu.b, alu.f,
213 alu.a0, alu.a1, # PLL mode
214 alu.pll_test, alu.pll_vco, # PLL test
215 alu.jtag_tck,
216 alu.jtag_tms,
217 alu.jtag_tdo,
218 alu.jtag_tdi], "add")