-
-
Save xobs/0e0d686f1d8c411b5102bf71dab4c891 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
#pylint:disable=E1101 | |
from migen import * | |
from litex.soc.interconnect import wishbone | |
from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage | |
from migen.fhdl.specials import Tristate | |
class WbGPIO(Module, AutoCSR): | |
def __init__(self, platform, pads, clock_domain="sys"): | |
self.bus = b = wishbone.Interface() | |
# Create a new `pads_array[]` list that is 32 elements long | |
# and contains either real pins (from the pads[] list), or | |
# unconnected Signals() that are valid, but unused. | |
pads_array = [] | |
for i in range(32): | |
if i >= len(pads): | |
pads_array.append(Signal()) | |
elif pads[i] is None: | |
pads_array.append(Signal()) | |
else: | |
pads_array.append(pads[i]) | |
print("FIXME: figure out how to add to this clock domain") | |
cd = ClockDomain(clock_domain) | |
self.gpio_inputs = Signal(32) | |
self.gpio_outputs = Signal(32) | |
self.gpio_oes = Signal(32) | |
# Buffer the output in a flip flop before it gets sent out | |
self.gpio_outputs_buf = Signal(32) | |
# We assert the ACK or ERR bit on the bus for one cycle. | |
# Use this register to deassert it after one cycle, then let it float. | |
deassert_reg = Signal() | |
# 0x00: Input Value | |
# 0x04: Output Value | |
# 0x08: Output Enable (0: input, 1: output) | |
self.sync += [ | |
self.gpio_outputs.eq(self.gpio_outputs_buf), | |
If(b.stb & b.cyc & ~deassert_reg, | |
If(b.we, | |
Case(b.adr[0:3], { | |
0: [self.gpio_inputs.eq(b.dat_w), b.ack.eq(1), b.err.eq(0)], | |
1: [self.gpio_outputs_buf.eq(b.dat_w), b.ack.eq(1), b.err.eq(0)], | |
2: [self.gpio_oes.eq(b.dat_w), b.ack.eq(1), b.err.eq(0)], | |
"default": [b.ack.eq(0), b.err.eq(1)], | |
}) | |
).Else( | |
# Readback | |
Case(b.adr[0:3], { | |
0: [b.dat_r.eq(self.gpio_inputs), b.ack.eq(1), b.err.eq(0)], | |
1: [b.dat_r.eq(self.gpio_outputs_buf), b.ack.eq(1), b.err.eq(0)], | |
2: [b.dat_r.eq(self.gpio_oes), b.ack.eq(1), b.err.eq(0)], | |
"default": [b.ack.eq(0), b.err.eq(1)], | |
}) | |
), | |
deassert_reg.eq(1), | |
).Elif(deassert_reg, | |
b.ack.eq(0), b.err.eq(1), deassert_reg.eq(0), | |
) | |
] | |
for pad_num in range(0, 32): | |
# Xilinx IOBUF is defined in UG471. | |
# Note that "T" is inverted -- that is, a logic High on "T" disables the output. | |
self.specials += Instance("IOBUF", | |
i_I=self.gpio_inputs[pad_num], | |
i_T=~self.gpio_oes[pad_num], | |
o_O=self.gpio_outputs[pad_num], | |
io_IO=pads_array[pad_num], | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment