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): 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 = []

View File

@ -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)