gateware: add support for SPI-over-LVDS

This commit is contained in:
Sebastien Bourdeauducq 2017-10-23 15:04:01 +08:00
parent 9d356ed93b
commit 4fa823b62a
2 changed files with 56 additions and 24 deletions

View File

@ -5,9 +5,9 @@ from artiq.gateware.rtio.phy.wishbone import RT2WB
class SPIMaster(Module):
def __init__(self, pads, **kwargs):
def __init__(self, pads, pads_n=None, **kwargs):
self.submodules._ll = ClockDomainsRenamer("rio_phy")(
SPIMasterWB(pads, **kwargs))
SPIMasterWB(pads, pads_n, **kwargs))
self.submodules._rt2wb = RT2WB(2, self._ll.bus)
self.rtlink = self._rt2wb.rtlink
self.probes = []

View File

@ -104,7 +104,7 @@ class SPIMaster(Module):
data (address 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:
bus = wishbone.Interface(data_width=32)
self.bus = bus
@ -197,31 +197,63 @@ class SPIMaster(Module):
]
# I/O
if hasattr(pads, "cs_n"):
cs_n_t = TSTriple(len(pads.cs_n))
self.specials += cs_n_t.get_tristate(pads.cs_n)
mosi_oe = Signal()
clk = Signal()
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 += [
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.oe.eq(~config.offline),
clk_t.o.eq(clk),
]
clk_t = TSTriple()
self.specials += clk_t.get_tristate(pads.clk)
self.comb += [
clk_t.oe.eq(~config.offline),
clk_t.o.eq((spi.cg.clk & spi.cs) ^ config.clk_polarity),
]
mosi_t = TSTriple()
self.specials += mosi_t.get_tristate(pads.mosi)
self.comb += [
mosi_t.oe.eq(mosi_oe),
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 += mosi_t.get_tristate(pads.mosi)
self.comb += [
mosi_t.oe.eq(~config.offline & spi.cs &
(spi.oe | ~config.half_duplex)),
mosi_t.o.eq(spi.reg.o),
spi.reg.i.eq(Mux(config.half_duplex, mosi_t.i,
getattr(pads, "miso", mosi_t.i))),
]
self.specials += Instance("IOBUFDS",
i_I=clk, i_T=config.offline,
io_IO=pads.clk, io_IOB=pads_n.clk)
mosi = Signal()
self.specials += Instance("IOBUFDS",
o_O=mosi, i_I=spi.reg.o, i_T=~mosi_oe,
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)