1 """Simple GPIO peripheral on wishbone
3 This is an extremely simple GPIO peripheral intended for use in XICS
4 testing, however it could also be used as an actual GPIO peripheral
6 Modified for use with pinmux, will probably change the class name later.
9 from nmigen
import Elaboratable
, Module
, Signal
, Record
, Array
10 from nmigen
.utils
import log2_int
11 from nmigen
.cli
import rtlil
12 from soc
.minerva
.wishbone
import make_wb_layout
13 from nmutil
.util
import wrap
14 from soc
.bus
.test
.wb_rw
import wb_read
, wb_write
18 from nmigen
.sim
.cxxsim
import Simulator
, Settle
20 from nmigen
.back
.pysim
import Simulator
, Settle
23 class SimpleGPIO(Elaboratable
):
25 def __init__(self
, n_gpio
=16):
32 self
.bus
= Record(make_wb_layout(spec
), name
="gpio_wb")
33 self
.bank_sel
= Array([Signal(3) for _
in range(n_gpio
)])
34 self
.gpio_o
= Signal(n_gpio
)
35 self
.gpio_oe
= Signal(n_gpio
)
36 self
.gpio_i
= Signal(n_gpio
)
38 def elaborate(self
, platform
):
40 comb
, sync
= m
.d
.comb
, m
.d
.sync
43 wb_rd_data
= bus
.dat_r
44 wb_wr_data
= bus
.dat_w
47 bank_sel
= self
.bank_sel
49 gpio_oe
= self
.gpio_oe
54 gpio_addr
= Signal(log2_int(self
.n_gpio
))
55 gpio_a
= Array(list(gpio_o
))
56 bank_sel_list
= Array(list(bank_sel
))
60 gpio_oe_list
= Array(list(gpio_o
))
61 gpio_i_list
= Array(list(gpio_i
))
63 # Address first byte for GPIO (max would be 256 GPIOs)
64 # Address second byte, bit 0 indicates input read
65 with m
.If(bus
.cyc
& bus
.stb
):
66 comb
+= wb_ack
.eq(1) # always ack
67 comb
+= gpio_addr
.eq(bus
.adr
[0:8])
68 with m
.If(bus
.we
): # write
69 # Write to CSR - direction and bank select
70 sync
+= gpio_a
[gpio_addr
].eq(wb_wr_data
[0])
71 sync
+= gpio_oe_list
[gpio_addr
].eq(wb_wr_data
[1])
72 sync
+= bank_sel_list
[gpio_addr
].eq(wb_wr_data
[5:8])
74 # Read the value of the input
75 with m
.If(bus
.adr
[8]):
76 comb
+= wb_rd_data
.eq(gpio_i_list
[gpio_addr
])
77 # Read the state of CSR bits
79 comb
+= wb_rd_data
.eq(gpio_o
[gpio_addr
]
80 + (gpio_oe
[gpio_addr
] << 1)
81 + (bank_sel_list
[gpio_addr
] << 5))
82 #comb += wb_rd_data.eq(gpio_a[gpio_addr])
87 for field
in self
.bus
.fields
.values():
96 def read_gpio(gpio
, addr
):
97 data
= yield from wb_read(gpio
.bus
, addr
)
98 print ("gpio%d" % addr
, hex(data
), bin(data
))
105 data
= yield from read_gpio(gpio
, 0) # read gpio addr 0
107 yield from wb_write(gpio
.bus
, 0, 1) # write gpio addr 0
109 data
= yield from read_gpio(gpio
, 0) # read gpio addr 0
114 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
115 with
open("test_gpio.il", "w") as f
:
119 m
.submodules
.xics_icp
= dut
124 sim
.add_sync_process(wrap(sim_gpio(dut
)))
125 sim_writer
= sim
.write_vcd('test_gpio.vcd')
130 if __name__
== '__main__':