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")
31 self
.bank
= Signal(log2_int(self
.n_banks
))
33 self
.wb_wordsize
= wb_wordsize
# 4 Bytes, 32-bits
35 # Create WB bus for the GPIO block
40 spec
.reg_wid
= self
.wb_wordsize
*8
41 self
.bus
= Record(make_wb_layout(spec
), name
="gpio_wb")
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
)
49 self
.pad_port
= Record(name
="IOPad", layout
=io_layout
)
51 self
.iomux
= IOMuxBlockSingle()
52 self
.gpio
= SimpleGPIO(self
.wb_wordsize
, self
.n_gpios
)
54 def elaborate(self
, platform
):
56 comb
, sync
= m
.d
.comb
, m
.d
.sync
61 periph_ports
= self
.periph_ports
62 pad_port
= self
.pad_port
64 # Add blocks to submodules
65 m
.submodules
.iomux
= iomux
66 m
.submodules
.gpio
= gpio
68 # Connect up modules and signals
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
82 iomux
.bank
.eq(gpio
.gpio_ports
[0].bank
)
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
)
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)
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
)
105 """ Get member signals for Verilog form. """
106 for field
in self
.pad_port
.fields
.values():
108 for field
in self
.gpio
.bus
.fields
.values():
110 for bank
in range(len(self
.periph_ports
)):
111 for field
in self
.periph_ports
[bank
].fields
.values():
118 def gen_gtkw_doc(module_name
, wordsize
, n_banks
, filename
):
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[{}:0]'.format(wb_data_width
-1), 'in'),
136 ('gpio_wb__dat_r[{}:0]'.format(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
= ('Bank{}'.format(bank
), [
143 ('bank{}__i'.format(bank
), 'in'),
144 ('bank{}__o'.format(bank
), 'out'),
145 ('bank{}__oe'.format(bank
), 'out')
147 traces
.append(temp_traces
)
149 temp_traces
= ('Misc', [
152 traces
.append(temp_traces
)
153 temp_traces
= ('IO port to pad', [
158 traces
.append(temp_traces
)
161 write_gtkw(filename
+".gtkw", filename
+".vcd", traces
, style
,
165 filename
= "test_gpio_pinmux" # Doesn't include extension
167 dut
= PinMuxBlockSingle(wb_wordsize
)
168 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
169 with
open(filename
+".il", "w") as f
:
173 print(dut
.gpio
.bus
.adr
)
174 print(dut
.gpio
.bus
.fields
)
177 m
.submodules
.pinmux
= dut
182 sim
.add_sync_process(wrap(test_gpio_pinmux(dut
)))
183 sim_writer
= sim
.write_vcd(filename
+".vcd")
187 gen_gtkw_doc("top.pinmux", wb_wordsize
, dut
.n_banks
, filename
)
189 def test_gpio_pinmux(dut
):
190 print("------START----------------------")
191 #print(dir(dut.bank_ports[0]))
192 #print(dut.bank_ports[0].fields)
194 gpios
= GPIOManager(dut
.gpio
, csrbus_layout
, dut
.bus
)
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)
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)
212 print("Finished the 1-bit IO mux block test!")
214 if __name__
== '__main__':