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 class PinMuxBlockSingle(Elaboratable
):
28 def __init__(self
, wb_wordsize
):
29 print("1-bit Pin Mux Block with JTAG")
32 self
.wb_wordsize
= wb_wordsize
# 4 Bytes, 32-bits
34 # Create WB bus for the GPIO block
39 spec
.reg_wid
= self
.wb_wordsize
*8
40 self
.bus
= Record(make_wb_layout(spec
), name
="pinmux_wb")
43 for i
in range(1, self
.n_banks
):
44 temp_str
= "periph{}".format(i
)
45 temp
.append(Record(name
=temp_str
, layout
=io_layout
))
46 self
.periph_ports
= Array(temp
)
48 self
.pad_port
= Record(name
="IOPad", layout
=io_layout
)
50 self
.iomux
= IOMuxBlockSingle()
51 self
.gpio
= SimpleGPIO(self
.wb_wordsize
, self
.n_gpios
)
52 # This is probably easier to extend in future by bringing out WB
53 # interface to top-level
54 #self.bus = self.gpio.bus
56 def elaborate(self
, platform
):
58 comb
, sync
= m
.d
.comb
, m
.d
.sync
62 periph_ports
= self
.periph_ports
63 pad_port
= self
.pad_port
65 # Add blocks to submodules
66 m
.submodules
.iomux
= iomux
67 m
.submodules
.gpio
= gpio
69 # Connect up modules and signals
71 m
.d
.comb
+= [gpio
.bus
.adr
.eq(bus
.adr
),
72 gpio
.bus
.dat_w
.eq(bus
.dat_w
),
73 bus
.dat_r
.eq(gpio
.bus
.dat_r
),
74 gpio
.bus
.sel
.eq(bus
.sel
),
75 gpio
.bus
.cyc
.eq(bus
.cyc
),
76 gpio
.bus
.stb
.eq(bus
.stb
),
77 bus
.ack
.eq(gpio
.bus
.ack
),
78 gpio
.bus
.we
.eq(bus
.we
),
79 bus
.err
.eq(gpio
.bus
.err
),
80 gpio
.bus
.cti
.eq(bus
.cti
), # Cycle Type Identifier
81 gpio
.bus
.bte
.eq(bus
.bte
) # Burst Type Extension
84 m
.d
.comb
+= iomux
.bank
.eq(gpio
.gpio_ports
[0].bank
)
86 # WB GPIO always bank0
87 m
.d
.comb
+= iomux
.bank_ports
[0].o
.eq(gpio
.gpio_ports
[0].o
)
88 m
.d
.comb
+= iomux
.bank_ports
[0].oe
.eq(gpio
.gpio_ports
[0].oe
)
89 m
.d
.comb
+= gpio
.gpio_ports
[0].i
.eq(iomux
.bank_ports
[0].i
)
92 for bank
in range(0, self
.n_banks
-1):
93 m
.d
.comb
+= iomux
.bank_ports
[bank
+1].o
.eq(periph_ports
[bank
].o
)
94 m
.d
.comb
+= iomux
.bank_ports
[bank
+1].oe
.eq(periph_ports
[bank
].oe
)
95 m
.d
.comb
+= periph_ports
[bank
].i
.eq(iomux
.bank_ports
[bank
+1].i
)
97 m
.d
.comb
+= pad_port
.o
.eq(iomux
.out_port
.o
)
98 m
.d
.comb
+= pad_port
.oe
.eq(iomux
.out_port
.oe
)
99 m
.d
.comb
+= iomux
.out_port
.i
.eq(pad_port
.i
)
104 """ Get member signals for Verilog form. """
105 for field
in self
.pad_port
.fields
.values():
107 for field
in self
.gpio
.bus
.fields
.values():
109 for bank
in range(len(self
.periph_ports
)):
110 for field
in self
.periph_ports
[bank
].fields
.values():
116 def gen_gtkw_doc(module_name
, wordsize
, n_banks
, filename
):
117 # GTKWave doc generation
120 'in': {'color': 'orange'},
121 'out': {'color': 'yellow'},
122 'debug': {'module': 'top', 'color': 'red'}
125 # Create a trace list, each block expected to be a tuple()
127 wb_data_width
= wordsize
*8
128 wb_traces
= ('Wishbone Bus', [
129 ('gpio_wb__cyc', 'in'),
130 ('gpio_wb__stb', 'in'),
131 ('gpio_wb__we', 'in'),
132 ('gpio_wb__adr[27:0]', 'in'),
133 ('gpio_wb__dat_w[{}:0]'.format(wb_data_width
-1), 'in'),
134 ('gpio_wb__dat_r[{}:0]'.format(wb_data_width
-1), 'out'),
135 ('gpio_wb__ack', 'out'),
137 traces
.append(wb_traces
)
139 for bank
in range(0, n_banks
):
140 temp_traces
= ('Bank{}'.format(bank
), [
141 ('bank{}__i'.format(bank
), 'in'),
142 ('bank{}__o'.format(bank
), 'out'),
143 ('bank{}__oe'.format(bank
), 'out')
145 traces
.append(temp_traces
)
147 temp_traces
= ('Misc', [
150 traces
.append(temp_traces
)
151 temp_traces
= ('IO port to pad', [
156 traces
.append(temp_traces
)
159 write_gtkw(filename
+".gtkw", filename
+".vcd", traces
, style
,
163 filename
= "test_gpio_pinmux" # Doesn't include extension
165 dut
= PinMuxBlockSingle(wb_wordsize
)
166 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
167 with
open(filename
+".il", "w") as f
:
171 print(dut
.gpio
.bus
.adr
)
172 print(dut
.gpio
.bus
.fields
)
175 m
.submodules
.pinmux
= dut
180 sim
.add_sync_process(wrap(test_gpio_pinmux(dut
)))
181 sim_writer
= sim
.write_vcd(filename
+".vcd")
185 gen_gtkw_doc("top.pinmux", wb_wordsize
, dut
.n_banks
, filename
)
187 def test_gpio_pinmux(dut
):
188 print("------START----------------------")
189 #print(dir(dut.bank_ports[0]))
190 #print(dut.bank_ports[0].fields)
192 gpios
= GPIOManager(dut
.gpio
, csrbus_layout
, dut
.bus
)
200 yield from gpios
.config("0", oe
=1, ie
=0, puen
=0, pden
=1, outval
=0, bank
=2)
203 yield dut
.periph_ports
[0].o
.eq(1)
204 yield dut
.periph_ports
[0].oe
.eq(1)
205 yield dut
.pad_port
.i
.eq(1)
208 print("Finished the 1-bit IO mux block test!")
210 if __name__
== '__main__':