1 # generate add.il ilang file with: python3 add.py
4 from nmigen
import (Elaboratable
, Signal
, Module
, Const
, DomainRenamer
,
5 ClockSignal
, ResetSignal
)
6 from nmigen
.cli
import verilog
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
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
19 class Core(Elaboratable
):
20 def __init__(self
, width
):
22 self
.a
= Signal(width
)
23 self
.b
= Signal(width
)
24 self
.f
= Signal(width
)
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'
34 # have to create at least one shift register
35 self
.sr
= self
.jtag
.add_shiftreg(ircode
=4, length
=3)
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
42 #self.memsizes.append((32, 32)) # width, depth
43 self
.memsizes
.append((32, 16)) # width, depth
44 #self.memsizes.append((32, 16)) # width, depth
46 # create and connect wishbone(s). okok, a better solution is to
47 # use a Wishbone Arbiter, and only have one WB bus.
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]
53 # next one skips DMI (see below - 8,9,10 already used)
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
)
63 # create DMI2JTAG (goes through to dmi_sim())
64 self
.dmi
= self
.jtag
.add_dmi(ircodes
=[8, 9, 10])
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
)
80 def elaborate(self
, platform
):
84 m
.submodules
.jtag
= jtag
= self
.jtag
85 m
.d
.comb
+= self
.sr
.i
.eq(self
.sr
.o
) # loopback test
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
)
101 # internal signals (not external pads basically)
102 a
= Signal(self
.width
)
103 b
= Signal(self
.width
)
104 f
= Signal(self
.width
)
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])
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
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
)
134 m
.d
.comb
+= wb
.ack
.eq(sram
.bus
.ack
)
135 m
.d
.comb
+= wb
.dat_r
.eq(sram
.bus
.dat_r
)
138 m
.d
.sync
+= f
.eq(a
+ b
)
142 class ADD(Elaboratable
):
143 def __init__(self
, 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)
153 # PLL input mode and test signals
156 self
.pll_vco
= Signal()
157 self
.pll_test
= Signal()
160 self
.dummypll
= DummyPLL(instance
=True)
163 self
.core
= Core(width
)
165 def elaborate(self
, platform
):
169 m
.submodules
.wrappll
= pll
= self
.dummypll
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
)
180 dr
= DomainRenamer("coresync")
181 m
.submodules
.core
= core
= dr(self
.core
)
184 sys_rst
= ResetSignal()
185 core_rst
= ResetSignal("coresync")
186 m
.d
.comb
+= core_rst
.eq(sys_rst
)
188 # connect core from PLL
189 core_clk
= ClockSignal("coresync")
190 m
.d
.comb
+= core_clk
.eq(pll
.clk_pll_o
)
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
)
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
)
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
:
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
218 alu
.jtag_tdi
], "add")