Skip to content

Instantly share code, notes, and snippets.

@xobs

xobs/lxgpio.v Secret

Created September 14, 2018 08:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xobs/0e0d686f1d8c411b5102bf71dab4c891 to your computer and use it in GitHub Desktop.
Save xobs/0e0d686f1d8c411b5102bf71dab4c891 to your computer and use it in GitHub Desktop.
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