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
15 from nmutil
.gtkw
import write_gtkw
19 from nmigen
.sim
.cxxsim
import Simulator
, Settle
, Delay
21 from nmigen
.sim
import Simulator
, Settle
, Delay
23 from iomux
import IOMuxBlockSingle
, io_layout
24 from simple_gpio
import SimpleGPIO
, GPIOManager
, csrbus_layout
26 dummy_pinspec
= {"name": "A2", "mux0": "gpio0", "mux1": "UART3_TX",
27 "mux2": "PWM0", "mux3": "sda0"}
29 class PinMuxBlockSingle(Elaboratable
):
31 def __init__(self
, wb_wordsize
, pinspec
):
32 print("1-bit Pin Mux Block with JTAG")
35 self
.wb_wordsize
= wb_wordsize
# 4 Bytes, 32-bits
37 # Create WB bus for the GPIO block
42 spec
.reg_wid
= self
.wb_wordsize
*8
45 for i
in range(1, self
.n_banks
):
46 temp_str
= "%s" % (pinspec
["mux%d" % i
])
47 temp
.append(Record(name
=temp_str
, layout
=io_layout
))
48 self
.periph_ports
= Array(temp
)
50 self
.pad_port
= Record(name
=pinspec
["name"], layout
=io_layout
)
52 self
.iomux
= IOMuxBlockSingle(self
.n_banks
)
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
58 def elaborate(self
, platform
):
60 comb
, sync
= m
.d
.comb
, m
.d
.sync
64 periph_ports
= self
.periph_ports
65 pad_port
= self
.pad_port
67 # Add blocks to submodules
68 m
.submodules
.iomux
= iomux
69 m
.submodules
.gpio
= gpio
71 # Connect up modules and signals
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
86 m
.d
.comb
+= iomux
.bank
.eq(gpio
.gpio_ports
[0].bank
)
88 # WB GPIO always bank0
89 m
.d
.comb
+= iomux
.bank_ports
[0].o
.eq(gpio
.gpio_ports
[0].o
)
90 m
.d
.comb
+= iomux
.bank_ports
[0].oe
.eq(gpio
.gpio_ports
[0].oe
)
91 m
.d
.comb
+= gpio
.gpio_ports
[0].i
.eq(iomux
.bank_ports
[0].i
)
94 for bank
in range(0, self
.n_banks
-1):
95 m
.d
.comb
+= iomux
.bank_ports
[bank
+1].o
.eq(periph_ports
[bank
].o
)
96 m
.d
.comb
+= iomux
.bank_ports
[bank
+1].oe
.eq(periph_ports
[bank
].oe
)
97 m
.d
.comb
+= periph_ports
[bank
].i
.eq(iomux
.bank_ports
[bank
+1].i
)
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
)
106 """ Get member signals for Verilog form. """
107 for field
in self
.pad_port
.fields
.values():
109 for field
in self
.bus
.fields
.values():
111 for bank
in range(len(self
.periph_ports
)):
112 for field
in self
.periph_ports
[bank
].fields
.values():
118 def gen_gtkw_doc(module_name
, wordsize
, n_banks
, filename
, pinspec
):
119 # GTKWave doc generation
122 'in': {'color': 'orange'},
123 'out': {'color': 'yellow'},
124 'debug': {'module': 'top', 'color': 'red'}
127 # Create a trace list, each block expected to be a tuple()
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'),
139 traces
.append(wb_traces
)
141 for bank
in range(0, n_banks
):
142 temp_traces
= ('mux%d' % bank
, [
143 ('%s__i' % (pinspec
["mux%d" % bank
]), 'in'),
144 ('%s__o' % (pinspec
["mux%d" % bank
]), 'in'),
145 ('%s__oe' % (pinspec
["mux%d" % bank
]), 'in')
147 traces
.append(temp_traces
)
149 temp_traces
= ('Misc', [
150 ('bank[%d:0]' % ((n_banks
-1).bit_length()-1), 'in')
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')
158 traces
.append(temp_traces
)
161 write_gtkw(filename
+".gtkw", filename
+".vcd", traces
, style
,
165 filename
= "test_gpio_pinmux" # Doesn't include extension
168 dut
= PinMuxBlockSingle(wb_wordsize
, dummy_pinspec
)
169 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
170 with
open(filename
+".il", "w") as f
:
175 print(dut
.bus
.fields
)
178 m
.submodules
.pinmux
= dut
183 sim
.add_sync_process(wrap(test_gpio_pinmux(dut
)))
184 sim_writer
= sim
.write_vcd(filename
+".vcd")
188 gen_gtkw_doc("top.pinmux", wb_wordsize
, dut
.n_banks
, filename
,
191 def test_gpio_pinmux(dut
):
192 print("------START----------------------")
193 #print(dir(dut.bank_ports[0]))
194 #print(dut.bank_ports[0].fields)
196 gpios
= GPIOManager(dut
.gpio
, csrbus_layout
, dut
.bus
)
204 yield from gpios
.config("0", oe
=1, ie
=0, puen
=0, pden
=1, outval
=0, bank
=0)
206 yield from gpios
.set_out("0", outval
=1)
208 yield from gpios
.config("0", oe
=1, ie
=0, puen
=0, pden
=1, outval
=0, bank
=2)
210 yield dut
.periph_ports
[2].o
.eq(1)
212 yield dut
.periph_ports
[2].oe
.eq(1)
214 yield dut
.pad_port
.i
.eq(1)
216 yield dut
.pad_port
.i
.eq(0)
220 yield dut
.pad_port
.i
.eq(1)
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")
225 print("Finished the 1-bit IO mux block test!")
227 if __name__
== '__main__':