8891e16dc55fa34880ff154d16c22aab6e28ad4b
[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.sim import Simulator, Settle
21
22 # Bit shift position for CSR word used in WB transactions
23 IADDRSHIFT = 8 # offset needed to tell WB to return input ONLY
24 # Layout of 16-bit configuration word (? is unused):
25 # ? ? ? i | bank_select[3:0] |? pden puen opendrain |? ien oe o
26 ISHIFT = 12
27 BANKSHIFT = 8
28 # Pull-up/down, open-drain, ien have been skipped for now
29 OESHIFT = 1
30 OSHIFT = 0
31
32 class SimpleGPIO(Elaboratable):
33
34 def __init__(self, n_gpio=16):
35 self.n_gpio = n_gpio
36 class Spec: pass
37 spec = Spec()
38 spec.addr_wid = 30
39 spec.mask_wid = 4
40 spec.reg_wid = 32
41 self.bus = Record(make_wb_layout(spec), name="gpio_wb")
42 # ONLY ONE BANK FOR ALL GPIOs atm...
43 self.bank_sel = Signal(4) # set maximum number of banks to 16
44 self.gpio_o = Signal(n_gpio)
45 self.gpio_oe = Signal(n_gpio)
46 self.gpio_i = Signal(n_gpio)
47
48 def elaborate(self, platform):
49 m = Module()
50 comb, sync = m.d.comb, m.d.sync
51
52 bus = self.bus
53 wb_rd_data = bus.dat_r
54 wb_wr_data = bus.dat_w
55 wb_ack = bus.ack
56
57 bank_sel = self.bank_sel
58 gpio_o = self.gpio_o
59 gpio_oe = self.gpio_oe
60 gpio_i = self.gpio_i
61
62 comb += wb_ack.eq(0)
63
64 gpio_addr = Signal(log2_int(self.n_gpio))
65 gpio_o_list = Array(list(gpio_o))
66 print(bank_sel)
67 print(gpio_o_list)
68 gpio_oe_list = Array(list(gpio_oe))
69 gpio_i_list = Array(list(gpio_i))
70
71 # Address first byte for GPIO (max would be 256 GPIOs)
72 # Address second byte, bit 0 indicates input read
73 with m.If(bus.cyc & bus.stb):
74 comb += wb_ack.eq(1) # always ack
75 comb += gpio_addr.eq(bus.adr[0:8])
76 with m.If(bus.we): # write
77 # Write to CSR
78 sync += gpio_o_list[gpio_addr].eq(wb_wr_data[OSHIFT])
79 sync += gpio_oe_list[gpio_addr].eq(wb_wr_data[OESHIFT])
80 sync += bank_sel.eq(wb_wr_data[BANKSHIFT:BANKSHIFT+4])
81 with m.Else(): # read
82 # Read the value of the input
83 with m.If(bus.adr[8]):
84 comb += wb_rd_data.eq(gpio_i_list[gpio_addr])
85 # Read the state of CSR bits
86 with m.Else():
87 comb += wb_rd_data.eq((gpio_o_list[gpio_addr] << OSHIFT)
88 + (gpio_oe_list[gpio_addr] << OESHIFT)
89 + (bank_sel << BANKSHIFT))
90 #comb += wb_rd_data.eq(gpio_a[gpio_addr])
91
92 return m
93
94 def __iter__(self):
95 for field in self.bus.fields.values():
96 yield field
97 yield self.gpio_o
98
99 def ports(self):
100 return list(self)
101
102
103
104 def gpio_configure(dut, gpio, oe, output=0, bank_sel=0):
105 csr_val = ( (bank_sel << BANKSHIFT)
106 | (oe << OESHIFT)
107 | (output << OSHIFT) )
108 # | (PUEN, PDUN, Open-drain etc...)
109 print("Configuring CSR to {0:x}".format(csr_val))
110 yield from wb_write(dut.bus, gpio, csr_val)
111
112 def gpio_rd_csr(dut, gpio):
113 csr_val = yield from wb_read(dut.bus, gpio)
114 print("GPIO{0} | CSR: {1:x}".format(gpio, csr_val))
115 # gpio_parse_csr(csr_val)
116 return data
117
118 def gpio_rd_input(dut, gpio):
119 in_val = yield from wb_read(dut.bus, gpio | (1<<IADDRSHIFT))
120 print("GPIO{0} | Input: {1:b}".format(gpio, in_val))
121 return data
122
123 def gpio_set_out(dut, gpio, output):
124 yield from wb_write(dut.bus, gpio, (output << OSHIFT))
125
126 def gpio_set_in_pad(dut, gpio, in_val):
127 yield dut.gpio_i.eq(in_val)
128
129
130 def sim_gpio(dut):
131
132 # GPIO0
133 #data = yield from read_gpio(gpio, 0) # read gpio addr 0
134 #yield from wb_write(gpio.bus, 0, 1) # write gpio addr 0
135 #data = yield from read_gpio(gpio, 0) # read gpio addr 0
136 print(dir(dut))
137 print(dut)
138 num_gpios = len(dut.gpio_o)
139 bank_sel = 3
140 oe = 1
141 output = 0
142 for gpio in range(0, num_gpios):
143 yield from gpio_configure(dut, gpio, oe, output, bank_sel)
144
145 for gpio in range(0, num_gpios):
146 yield from gpio_set_out(dut, gpio, 1)
147
148 #for gpio in range(0, num_gpios):
149 # yield from gpio_set_in_pad(dut, gpio, 1)
150 yield from gpio_set_in_pad(dut, 0, 1)
151 yield
152 yield from gpio_set_in_pad(dut, 1, 1)
153 yield
154 yield from gpio_set_in_pad(dut, 2, 1)
155 yield
156 yield from gpio_set_in_pad(dut, 3, 1)
157 yield
158 yield from gpio_set_in_pad(dut, 2, 0)
159 yield
160
161 print("Finished the simple GPIO block test!")
162
163 def test_gpio():
164
165 dut = SimpleGPIO()
166 vl = rtlil.convert(dut, ports=dut.ports())
167 with open("test_gpio.il", "w") as f:
168 f.write(vl)
169
170 m = Module()
171 m.submodules.xics_icp = dut
172
173 sim = Simulator(m)
174 sim.add_clock(1e-6)
175
176 sim.add_sync_process(wrap(sim_gpio(dut)))
177 sim_writer = sim.write_vcd('test_gpio.vcd')
178 with sim_writer:
179 sim.run()
180
181
182 if __name__ == '__main__':
183 test_gpio()
184