forked from M-Labs/artiq
gateware: add support for SPI-over-LVDS
This commit is contained in:
parent
9d356ed93b
commit
4fa823b62a
|
@ -5,9 +5,9 @@ from artiq.gateware.rtio.phy.wishbone import RT2WB
|
||||||
|
|
||||||
|
|
||||||
class SPIMaster(Module):
|
class SPIMaster(Module):
|
||||||
def __init__(self, pads, **kwargs):
|
def __init__(self, pads, pads_n=None, **kwargs):
|
||||||
self.submodules._ll = ClockDomainsRenamer("rio_phy")(
|
self.submodules._ll = ClockDomainsRenamer("rio_phy")(
|
||||||
SPIMasterWB(pads, **kwargs))
|
SPIMasterWB(pads, pads_n, **kwargs))
|
||||||
self.submodules._rt2wb = RT2WB(2, self._ll.bus)
|
self.submodules._rt2wb = RT2WB(2, self._ll.bus)
|
||||||
self.rtlink = self._rt2wb.rtlink
|
self.rtlink = self._rt2wb.rtlink
|
||||||
self.probes = []
|
self.probes = []
|
||||||
|
|
|
@ -104,7 +104,7 @@ class SPIMaster(Module):
|
||||||
data (address 0):
|
data (address 0):
|
||||||
M write/read data (reset=0)
|
M write/read data (reset=0)
|
||||||
"""
|
"""
|
||||||
def __init__(self, pads, bus=None):
|
def __init__(self, pads, pads_n=None, bus=None):
|
||||||
if bus is None:
|
if bus is None:
|
||||||
bus = wishbone.Interface(data_width=32)
|
bus = wishbone.Interface(data_width=32)
|
||||||
self.bus = bus
|
self.bus = bus
|
||||||
|
@ -197,31 +197,63 @@ class SPIMaster(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# I/O
|
# I/O
|
||||||
if hasattr(pads, "cs_n"):
|
mosi_oe = Signal()
|
||||||
cs_n_t = TSTriple(len(pads.cs_n))
|
clk = Signal()
|
||||||
self.specials += cs_n_t.get_tristate(pads.cs_n)
|
self.comb += [
|
||||||
|
mosi_oe.eq(
|
||||||
|
~config.offline & spi.cs &
|
||||||
|
(spi.oe | ~config.half_duplex)),
|
||||||
|
clk.eq((spi.cg.clk & spi.cs) ^ config.clk_polarity)
|
||||||
|
]
|
||||||
|
|
||||||
|
if pads_n is None:
|
||||||
|
if hasattr(pads, "cs_n"):
|
||||||
|
cs_n_t = TSTriple(len(pads.cs_n))
|
||||||
|
self.specials += cs_n_t.get_tristate(pads.cs_n)
|
||||||
|
self.comb += [
|
||||||
|
cs_n_t.oe.eq(~config.offline),
|
||||||
|
cs_n_t.o.eq((cs & Replicate(spi.cs, len(cs))) ^
|
||||||
|
Replicate(~config.cs_polarity, len(cs))),
|
||||||
|
]
|
||||||
|
|
||||||
|
clk_t = TSTriple()
|
||||||
|
self.specials += clk_t.get_tristate(pads.clk)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
cs_n_t.oe.eq(~config.offline),
|
clk_t.oe.eq(~config.offline),
|
||||||
cs_n_t.o.eq((cs & Replicate(spi.cs, len(cs))) ^
|
clk_t.o.eq(clk),
|
||||||
Replicate(~config.cs_polarity, len(cs))),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
clk_t = TSTriple()
|
mosi_t = TSTriple()
|
||||||
self.specials += clk_t.get_tristate(pads.clk)
|
self.specials += mosi_t.get_tristate(pads.mosi)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
clk_t.oe.eq(~config.offline),
|
mosi_t.oe.eq(mosi_oe),
|
||||||
clk_t.o.eq((spi.cg.clk & spi.cs) ^ config.clk_polarity),
|
mosi_t.o.eq(spi.reg.o),
|
||||||
]
|
spi.reg.i.eq(Mux(config.half_duplex, mosi_t.i,
|
||||||
|
getattr(pads, "miso", mosi_t.i))),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
if hasattr(pads, "cs_n"):
|
||||||
|
for i in range(len(pads.cs_n)):
|
||||||
|
self.specials += Instance("IOBUFDS",
|
||||||
|
i_I=(cs[i] & spi.cs) ^ ~config.cs_polarity,
|
||||||
|
i_T=config.offline,
|
||||||
|
io_IO=pads.cs_n[i], io_IOB=pads_n.cs_n[i])
|
||||||
|
|
||||||
mosi_t = TSTriple()
|
self.specials += Instance("IOBUFDS",
|
||||||
self.specials += mosi_t.get_tristate(pads.mosi)
|
i_I=clk, i_T=config.offline,
|
||||||
self.comb += [
|
io_IO=pads.clk, io_IOB=pads_n.clk)
|
||||||
mosi_t.oe.eq(~config.offline & spi.cs &
|
|
||||||
(spi.oe | ~config.half_duplex)),
|
mosi = Signal()
|
||||||
mosi_t.o.eq(spi.reg.o),
|
self.specials += Instance("IOBUFDS",
|
||||||
spi.reg.i.eq(Mux(config.half_duplex, mosi_t.i,
|
o_O=mosi, i_I=spi.reg.o, i_T=~mosi_oe,
|
||||||
getattr(pads, "miso", mosi_t.i))),
|
io_IO=pads.mosi, io_IOB=pads_n.mosi)
|
||||||
]
|
if hasattr(pads, "miso"):
|
||||||
|
miso = Signal()
|
||||||
|
self.specials += Instance("IBUFDS",
|
||||||
|
o_O=miso, i_I=pads.miso, i_IB=pads_n.miso)
|
||||||
|
else:
|
||||||
|
miso = mosi
|
||||||
|
self.comb += spi.reg.i.eq(Mux(config.half_duplex, mosi, miso))
|
||||||
|
|
||||||
|
|
||||||
SPI_DATA_ADDR, SPI_XFER_ADDR, SPI_CONFIG_ADDR = range(3)
|
SPI_DATA_ADDR, SPI_XFER_ADDR, SPI_CONFIG_ADDR = range(3)
|
||||||
|
|
Loading…
Reference in New Issue