feat(iomux, pinmux, stage2): Change terminology from 'bank' to 'mux'/'port'
[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 dummy_pinspec = {"name": "A2", "mux0": "gpio0", "mux1": "UART3_TX",
27 "mux2": "PWM0", "mux3": "sda0"}
28
29 class PinMuxBlockSingle(Elaboratable):
30
31 def __init__(self, wb_wordsize, pinspec):
32 print("1-bit Pin Mux Block with JTAG")
33 self.n_ports = 4
34 self.n_gpios = 1
35 self.wb_wordsize = wb_wordsize # 4 Bytes, 32-bits
36
37 # Create WB bus for the GPIO block
38 class Spec: pass
39 spec = Spec()
40 spec.addr_wid = 30
41 spec.mask_wid = 4
42 spec.reg_wid = self.wb_wordsize*8
43
44 temp = []
45 for i in range(1, self.n_ports):
46 temp_str = "%s" % (pinspec["mux%d" % i])
47 temp.append(Record(name=temp_str, layout=io_layout))
48 self.periph_ports = Array(temp)
49
50 self.pad_port = Record(name=pinspec["name"], layout=io_layout)
51
52 self.iomux = IOMuxBlockSingle(self.n_ports)
53 self.gpio = SimpleGPIO(self.wb_wordsize, self.n_gpios)
54 # This is probably easier to extend in future by bringing out WB
55 # interface to top-level
56 self.bus = self.gpio.bus
57
58 def elaborate(self, platform):
59 m = Module()
60 comb, sync = m.d.comb, m.d.sync
61 iomux = self.iomux
62 gpio = self.gpio
63 bus = self.bus
64 periph_ports = self.periph_ports
65 pad_port = self.pad_port
66
67 # Add blocks to submodules
68 m.submodules.iomux = iomux
69 m.submodules.gpio = gpio
70
71 # Connect up modules and signals
72 # WB bus connection
73 #m.d.comb += [gpio.bus.adr.eq(bus.adr),
74 # gpio.bus.dat_w.eq(bus.dat_w),
75 # bus.dat_r.eq(gpio.bus.dat_r),
76 # gpio.bus.sel.eq(bus.sel),
77 # gpio.bus.cyc.eq(bus.cyc),
78 # gpio.bus.stb.eq(bus.stb),
79 # bus.ack.eq(gpio.bus.ack),
80 # gpio.bus.we.eq(bus.we),
81 # bus.err.eq(gpio.bus.err),
82 # gpio.bus.cti.eq(bus.cti), # Cycle Type Identifier
83 # gpio.bus.bte.eq(bus.bte) # Burst Type Extension
84 # ]
85
86 m.d.comb += iomux.port.eq(gpio.gpio_ports[0].bank)
87
88 # WB GPIO always port0
89 m.d.comb += iomux.periph_ports[0].o.eq(gpio.gpio_ports[0].o)
90 m.d.comb += iomux.periph_ports[0].oe.eq(gpio.gpio_ports[0].oe)
91 m.d.comb += gpio.gpio_ports[0].i.eq(iomux.periph_ports[0].i)
92
93 # ports1-3 external
94 for port in range(0, self.n_ports-1):
95 m.d.comb += iomux.periph_ports[port+1].o.eq(periph_ports[port].o)
96 m.d.comb += iomux.periph_ports[port+1].oe.eq(periph_ports[port].oe)
97 m.d.comb += periph_ports[port].i.eq(iomux.periph_ports[port+1].i)
98
99 m.d.comb += pad_port.o.eq(iomux.out_port.o)
100 m.d.comb += pad_port.oe.eq(iomux.out_port.oe)
101 m.d.comb += iomux.out_port.i.eq(pad_port.i)
102
103 return m
104
105 def __iter__(self):
106 """ Get member signals for Verilog form. """
107 for field in self.pad_port.fields.values():
108 yield field
109 for field in self.bus.fields.values():
110 yield field
111 for port in range(len(self.periph_ports)):
112 for field in self.periph_ports[port].fields.values():
113 yield field
114
115 def ports(self):
116 return list(self)
117
118 def gen_gtkw_doc(module_name, wordsize, n_ports, filename, pinspec):
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[%d:0]' % (wb_data_width-1), 'in'),
136 ('gpio_wb__dat_r[%d:0]' % (wb_data_width-1), 'out'),
137 ('gpio_wb__ack', 'out'),
138 ])
139 traces.append(wb_traces)
140
141 for port in range(0, n_ports):
142 temp_traces = ('mux%d' % port, [
143 ('%s__i' % (pinspec["mux%d" % port]), 'in'),
144 ('%s__o' % (pinspec["mux%d" % port]), 'in'),
145 ('%s__oe' % (pinspec["mux%d" % port]), 'in')
146 ])
147 traces.append(temp_traces)
148
149 temp_traces = ('Misc', [
150 ('port[%d:0]' % ((n_ports-1).bit_length()-1), 'in')
151 ])
152 traces.append(temp_traces)
153 temp_traces = ('IO port to pad named: %s' % pinspec["name"], [
154 ('%s__i' % pinspec["name"], 'in'),
155 ('%s__o' % pinspec["name"], 'in'),
156 ('%s__oe' % pinspec["name"], 'in')
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
168 dut = PinMuxBlockSingle(wb_wordsize, dummy_pinspec)
169 vl = rtlil.convert(dut, ports=dut.ports())
170 with open(filename+".il", "w") as f:
171 f.write(vl)
172
173 print("Bus dir:")
174 print(dut.bus.adr)
175 print(dut.bus.fields)
176
177 m = Module()
178 m.submodules.pinmux = dut
179
180 sim = Simulator(m)
181 sim.add_clock(1e-6)
182
183 sim.add_sync_process(wrap(test_gpio_pinmux(dut)))
184 sim_writer = sim.write_vcd(filename+".vcd")
185 with sim_writer:
186 sim.run()
187
188 gen_gtkw_doc("top.pinmux", wb_wordsize, dut.n_ports, filename,
189 dummy_pinspec)
190
191 def test_gpio_pinmux(dut):
192 print("------START----------------------")
193 #print(dir(dut.periph_ports[0]))
194 #print(dut.periph_ports[0].fields)
195
196 gpios = GPIOManager(dut.gpio, csrbus_layout, dut.bus)
197
198 oe = 1
199 ie = 0
200 puen = 0
201 pden = 1
202 outval = 0
203 port = 0
204 yield from gpios.config("0", oe=1, ie=0, puen=0, pden=1, outval=0, bank=0)
205
206 yield from gpios.set_out("0", outval=1)
207
208 yield from gpios.config("0", oe=1, ie=0, puen=0, pden=1, outval=0, bank=2)
209
210 yield dut.periph_ports[2].o.eq(1)
211 yield
212 yield dut.periph_ports[2].oe.eq(1)
213 yield
214 yield dut.pad_port.i.eq(1)
215 yield
216 yield dut.pad_port.i.eq(0)
217
218
219
220 yield dut.pad_port.i.eq(1)
221 yield
222 yield from gpios.config("0", oe=0, ie=1, puen=0, pden=1, outval=0, bank=0)
223 yield from gpios.rd_input("0")
224
225 print("Finished the 1-bit IO mux block test!")
226
227 if __name__ == '__main__':
228 sim_iomux()
229