Started on implementing i/oe/bank_sel
[pinmux.git] / src / spec / simple_gpio.py
1 """Simple GPIO peripheral on wishbone
2
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
5
6 Modified for use with pinmux, will probably change the class name later.
7 """
8
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
15
16 cxxsim = False
17 if cxxsim:
18 from nmigen.sim.cxxsim import Simulator, Settle
19 else:
20 from nmigen.back.pysim import Simulator, Settle
21
22
23 class SimpleGPIO(Elaboratable):
24
25 def __init__(self, n_gpio=16):
26 self.n_gpio = n_gpio
27 class Spec: pass
28 spec = Spec()
29 spec.addr_wid = 30
30 spec.mask_wid = 4
31 spec.reg_wid = 32
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)
37
38 def elaborate(self, platform):
39 m = Module()
40 comb, sync = m.d.comb, m.d.sync
41
42 bus = self.bus
43 wb_rd_data = bus.dat_r
44 wb_wr_data = bus.dat_w
45 wb_ack = bus.ack
46
47 bank_sel = self.bank_sel
48 gpio_o = self.gpio_o
49 gpio_oe = self.gpio_oe
50 gpio_i = self.gpio_i
51
52 comb += wb_ack.eq(0)
53
54 gpio_addr = Signal(log2_int(self.n_gpio))
55 gpio_a = Array(list(gpio_o))
56 bank_sel_list = Array(list(bank_sel))
57 print(bank_sel)
58 print(bank_sel_list)
59 print(gpio_a)
60 gpio_oe_list = Array(list(gpio_o))
61 gpio_i_list = Array(list(gpio_i))
62
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])
73 with m.Else(): # read
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
78 with m.Else():
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])
83
84 return m
85
86 def __iter__(self):
87 for field in self.bus.fields.values():
88 yield field
89 yield self.gpio_o
90
91 def ports(self):
92 return list(self)
93
94
95
96 def read_gpio(gpio, addr):
97 data = yield from wb_read(gpio.bus, addr)
98 print ("gpio%d" % addr, hex(data), bin(data))
99 return data
100
101
102 def sim_gpio(gpio):
103
104 # GPIO0
105 data = yield from read_gpio(gpio, 0) # read gpio addr 0
106
107 yield from wb_write(gpio.bus, 0, 1) # write gpio addr 0
108
109 data = yield from read_gpio(gpio, 0) # read gpio addr 0
110
111 def test_gpio():
112
113 dut = SimpleGPIO()
114 vl = rtlil.convert(dut, ports=dut.ports())
115 with open("test_gpio.il", "w") as f:
116 f.write(vl)
117
118 m = Module()
119 m.submodules.xics_icp = dut
120
121 sim = Simulator(m)
122 sim.add_clock(1e-6)
123
124 sim.add_sync_process(wrap(sim_gpio(dut)))
125 sim_writer = sim.write_vcd('test_gpio.vcd')
126 with sim_writer:
127 sim.run()
128
129
130 if __name__ == '__main__':
131 test_gpio()
132