Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / bus / 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
7 from nmigen import Elaboratable, Module, Signal, Record, Array
8 from nmigen.utils import log2_int
9 from nmigen.cli import rtlil
10 from soc.minerva.wishbone import make_wb_layout
11 from nmutil.util import wrap
12 from soc.bus.test.wb_rw import wb_read, wb_write
13
14 cxxsim = False
15 if cxxsim:
16 from nmigen.sim.cxxsim import Simulator, Settle
17 else:
18 from nmigen.back.pysim import Simulator, Settle
19
20
21 class SimpleGPIO(Elaboratable):
22
23 def __init__(self, n_gpio=16):
24 self.n_gpio = n_gpio
25 class Spec: pass
26 spec = Spec()
27 spec.addr_wid = 30
28 spec.mask_wid = 4
29 spec.reg_wid = 32
30 self.bus = Record(make_wb_layout(spec), name="gpio_wb")
31 self.gpio_o = Signal(n_gpio)
32
33 def elaborate(self, platform):
34 m = Module()
35 comb, sync = m.d.comb, m.d.sync
36
37 bus = self.bus
38 wb_rd_data = bus.dat_r
39 wb_wr_data = bus.dat_w
40 wb_ack = bus.ack
41 gpio_o = self.gpio_o
42
43 comb += wb_ack.eq(0)
44
45 gpio_addr = Signal(log2_int(self.n_gpio))
46 gpio_a = Array(list(gpio_o))
47
48 with m.If(bus.cyc & bus.stb):
49 comb += wb_ack.eq(1) # always ack
50 comb += gpio_addr.eq(bus.adr)
51 with m.If(bus.we): # write
52 sync += gpio_a[gpio_addr].eq(wb_wr_data[0])
53 with m.Else(): # read
54 comb += wb_rd_data.eq(gpio_a[gpio_addr])
55
56 return m
57
58 def __iter__(self):
59 for field in self.bus.fields.values():
60 yield field
61 yield self.gpio_o
62
63 def ports(self):
64 return list(self)
65
66
67
68 def read_gpio(gpio, addr):
69 data = yield from wb_read(gpio.bus, addr)
70 print ("gpio%d" % addr, hex(data), bin(data))
71 return data
72
73
74 def sim_gpio(gpio):
75
76 # GPIO0
77 data = yield from read_gpio(gpio, 0) # read gpio addr 0
78 assert data == 0
79
80 yield from wb_write(gpio.bus, 0, 1) # write gpio addr 0
81
82 data = yield from read_gpio(gpio, 0) # read gpio addr 0
83 assert data == 1
84
85 # GPIO1
86 data = yield from read_gpio(gpio, 1) # read gpio addr 1
87 assert data == 0
88
89 yield from wb_write(gpio.bus, 1, 1) # write gpio addr 1
90
91 data = yield from read_gpio(gpio, 1) # read gpio addr 1
92 assert data == 1
93
94 # GPIO0
95 data = yield from read_gpio(gpio, 0) # read gpio addr 0
96 assert data == 1
97
98 yield from wb_write(gpio.bus, 0, 0) # write gpio addr 0
99
100 data = yield from read_gpio(gpio, 0) # read gpio addr 0
101 assert data == 0
102
103
104 def test_gpio():
105
106 dut = SimpleGPIO()
107 vl = rtlil.convert(dut, ports=dut.ports())
108 with open("test_gpio.il", "w") as f:
109 f.write(vl)
110
111 m = Module()
112 m.submodules.xics_icp = dut
113
114 sim = Simulator(m)
115 sim.add_clock(1e-6)
116
117 sim.add_sync_process(wrap(sim_gpio(dut)))
118 sim_writer = sim.write_vcd('test_gpio.vcd')
119 with sim_writer:
120 sim.run()
121
122
123 if __name__ == '__main__':
124 test_gpio()
125