Added signals to export for il
[pinmux.git] / src / spec / pinmux.py
1 """
2 1-bit pinmux case
3
4 """
5 from random import randint
6 #from math import ceil, floor
7 from nmigen import Elaboratable, Module, Signal, Record, Array, Cat
8 from nmigen.hdl.rec import Layout
9 from nmigen.utils import log2_int
10 from nmigen.cli import rtlil
11 from soc.minerva.wishbone import make_wb_layout
12 from nmutil.util import wrap
13 #from soc.bus.test.wb_rw import wb_read, wb_write
14
15 from nmutil.gtkw import write_gtkw
16
17 cxxsim = False
18 if cxxsim:
19 from nmigen.sim.cxxsim import Simulator, Settle, Delay
20 else:
21 from nmigen.sim import Simulator, Settle, Delay
22
23 from iomux import IOMuxBlockSingle, io_layout
24 from simple_gpio import SimpleGPIO, GPIOManager, csrbus_layout
25
26 class PinMuxBlockSingle(Elaboratable):
27
28 def __init__(self, wb_wordsize):
29 print("1-bit Pin Mux Block with JTAG")
30 self.n_banks = 4
31 self.bank = Signal(log2_int(self.n_banks))
32 self.n_gpios = 1
33 self.wb_wordsize = wb_wordsize # 4 Bytes, 32-bits
34
35 # Create WB bus for the GPIO block
36 class Spec: pass
37 spec = Spec()
38 spec.addr_wid = 30
39 spec.mask_wid = 4
40 spec.reg_wid = self.wb_wordsize*8
41 self.bus = Record(make_wb_layout(spec), name="gpio_wb")
42
43 temp = []
44 for i in range(1, self.n_banks):
45 temp_str = "periph{}".format(i)
46 temp.append(Record(name=temp_str, layout=io_layout))
47 self.periph_ports = Array(temp)
48
49 self.pad_port = Record(name="IOPad", layout=io_layout)
50
51 self.iomux = IOMuxBlockSingle()
52 self.gpio = SimpleGPIO(self.wb_wordsize, self.n_gpios)
53
54 def elaborate(self, platform):
55 m = Module()
56 comb, sync = m.d.comb, m.d.sync
57 iomux = self.iomux
58 gpio = self.gpio
59 bus = self.bus
60 bank = self.bank
61 periph_ports = self.periph_ports
62 pad_port = self.pad_port
63
64 # Add blocks to submodules
65 m.submodules.iomux = iomux
66 m.submodules.gpio = gpio
67
68 # Connect up modules and signals
69 # WB bus connection
70 gpio.bus.adr.eq(bus.adr)
71 gpio.bus.dat_w.eq(bus.dat_w)
72 bus.dat_r.eq(gpio.bus.dat_r)
73 gpio.bus.sel.eq(bus.sel)
74 gpio.bus.cyc.eq(bus.cyc)
75 gpio.bus.stb.eq(bus.stb)
76 bus.ack.eq(gpio.bus.ack)
77 gpio.bus.we.eq(bus.we)
78 bus.err.eq(gpio.bus.err)
79 gpio.bus.cti.eq(bus.cti) # Cycle Type Identifier
80 gpio.bus.bte.eq(bus.bte) # Burst Type Extension
81
82 iomux.bank.eq(gpio.gpio_ports[0].bank)
83
84 # WB GPIO always bank0
85 iomux.bank_ports[0].o.eq(gpio.gpio_ports[0].o)
86 iomux.bank_ports[0].oe.eq(gpio.gpio_ports[0].oe)
87 gpio.gpio_ports[0].i.eq(iomux.bank_ports[0].i)
88
89 # banks1-3 external
90 iomux.bank_ports[1].o.eq(periph_ports[0].o)
91 iomux.bank_ports[1].oe.eq(periph_ports[0].oe)
92 periph_ports[0].i.eq(iomux.bank_ports[1].i)
93 #for bank in range(0, self.n_banks-1):
94 # iomux.bank_ports[bank+1].o.eq(periph_ports[bank].o)
95 # iomux.bank_ports[bank+1].oe.eq(periph_ports[bank].oe)
96 # periph_ports[bank].i.eq(iomux.bank_ports[bank+1].i)
97
98 pad_port.o.eq(iomux.out_port.o)
99 pad_port.oe.eq(iomux.out_port.oe)
100 iomux.out_port.i.eq(pad_port.i)
101
102 return m
103
104 def __iter__(self):
105 """ Get member signals for Verilog form. """
106 for field in self.pad_port.fields.values():
107 yield field
108 for field in self.gpio.bus.fields.values():
109 yield field
110 for bank in range(len(self.periph_ports)):
111 for field in self.periph_ports[bank].fields.values():
112 yield field
113 #yield self.bank
114
115 def ports(self):
116 return list(self)
117
118 def gen_gtkw_doc(module_name, wordsize, n_banks, filename):
119 # GTKWave doc generation
120 style = {
121 '': {'base': 'hex'},
122 'in': {'color': 'orange'},
123 'out': {'color': 'yellow'},
124 'debug': {'module': 'top', 'color': 'red'}
125 }
126
127 # Create a trace list, each block expected to be a tuple()
128 traces = []
129 wb_data_width = wordsize*8
130 wb_traces = ('Wishbone Bus', [
131 ('gpio_wb__cyc', 'in'),
132 ('gpio_wb__stb', 'in'),
133 ('gpio_wb__we', 'in'),
134 ('gpio_wb__adr[27:0]', 'in'),
135 ('gpio_wb__dat_w[{}:0]'.format(wb_data_width-1), 'in'),
136 ('gpio_wb__dat_r[{}:0]'.format(wb_data_width-1), 'out'),
137 ('gpio_wb__ack', 'out'),
138 ])
139 traces.append(wb_traces)
140
141 for bank in range(0, n_banks):
142 temp_traces = ('Bank{}'.format(bank), [
143 ('bank{}__i'.format(bank), 'in'),
144 ('bank{}__o'.format(bank), 'out'),
145 ('bank{}__oe'.format(bank), 'out')
146 ])
147 traces.append(temp_traces)
148
149 temp_traces = ('Misc', [
150 ('bank[1:0]', 'in')
151 ])
152 traces.append(temp_traces)
153 temp_traces = ('IO port to pad', [
154 ('IO__i', 'in'),
155 ('IO__o', 'out'),
156 ('IO__oe', 'out')
157 ])
158 traces.append(temp_traces)
159 #print(traces)
160
161 write_gtkw(filename+".gtkw", filename+".vcd", traces, style,
162 module=module_name)
163
164 def sim_iomux():
165 filename = "test_gpio_pinmux" # Doesn't include extension
166 wb_wordsize = 4
167 dut = PinMuxBlockSingle(wb_wordsize)
168 vl = rtlil.convert(dut, ports=dut.ports())
169 with open(filename+".il", "w") as f:
170 f.write(vl)
171
172 print("Bus dir:")
173 print(dut.gpio.bus.adr)
174 print(dut.gpio.bus.fields)
175
176 m = Module()
177 m.submodules.pinmux = dut
178
179 sim = Simulator(m)
180 sim.add_clock(1e-6)
181
182 sim.add_sync_process(wrap(test_gpio_pinmux(dut)))
183 sim_writer = sim.write_vcd(filename+".vcd")
184 with sim_writer:
185 sim.run()
186
187 gen_gtkw_doc("top.pinmux", wb_wordsize, dut.n_banks, filename)
188
189 def test_gpio_pinmux(dut):
190 print("------START----------------------")
191 #print(dir(dut.bank_ports[0]))
192 #print(dut.bank_ports[0].fields)
193
194 gpios = GPIOManager(dut.gpio, csrbus_layout, dut.bus)
195
196 oe = 1
197 ie = 0
198 puen = 0
199 pden = 1
200 outval = 0
201 bank = 0
202 #yield from gpios.config("0", oe=1, ie=0, puen=0, pden=1, outval=0, bank=2)
203 yield dut.bus.adr.eq(0x1)
204 yield dut.bus.dat_w.eq(0xA5A5)
205
206 yield
207 yield dut.periph_ports[0].o.eq(1)
208 yield dut.periph_ports[0].oe.eq(1)
209 yield dut.pad_port.i.eq(1)
210
211
212 print("Finished the 1-bit IO mux block test!")
213
214 if __name__ == '__main__':
215 sim_iomux()
216