2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-26 03:38:25 +08:00

gateware.spi: delay only writes to data register, update doc

This commit is contained in:
Robert Jördens 2016-03-01 14:14:38 +01:00
parent f2ec8692c0
commit c2fe9a08ae

View File

@ -205,12 +205,15 @@ class SPIMaster(Module):
Transfers submitted this way are chained and executed without Transfers submitted this way are chained and executed without
deasserting cs. Once a transfer completes, the previous transfer's deasserting cs. Once a transfer completes, the previous transfer's
read data is available in the data register. read data is available in the data register.
* A wishbone transaction is ack-ed when the transfer has been written * Writes to the config register take effect immediately. Writes to xfer
to the intermediate buffer. It will be started when there are no and data are synchronized to the start of a transfer.
other transactions being executed. Writes take one cycle when * A wishbone data register write is ack-ed when the transfer has
there is either no transfer being executed, no data in the been written to the intermediate buffer. It will be started when
intermediate buffer, or a transfer just completing. Reads always there are no other transactions being executed, either starting
finish in one cycle. a new SPI transfer of chained to an in-flight transfer.
Writes take two cycles unless the write is to the data register
and another chained transfer is pending and the transfer being
executed is not complete. Reads always finish in two cycles.
Transaction Sequence: Transaction Sequence:
* If desired, write the config register to set up the core. * If desired, write the config register to set up the core.
@ -218,16 +221,17 @@ class SPIMaster(Module):
* Write the data register (also for zero-length writes), * Write the data register (also for zero-length writes),
writing triggers the transfer and when the transfer is accepted to writing triggers the transfer and when the transfer is accepted to
the inermediate buffer, the write is ack-ed. the inermediate buffer, the write is ack-ed.
* If desired, read the data register. * If desired, read the data register corresponding to the last
* If desired, write data for the next, chained, transfer. completed transfer.
* If desired, change xfer register for the next transfer.
* If desired, write data queuing the next (possibly chained) transfer.
Register address and bit map: Register address and bit map:
config (address 2): config (address 2):
1 offline: all pins high-z (reset=1) 1 offline: all pins high-z (reset=1)
1 active: cs/transfer active (read-only) 1 active: cs/transfer active (read-only)
1 pending: transfer pending in intermediate buffer, bus writes will 1 pending: transfer pending in intermediate buffer (read-only)
block (read-only)
1 cs_polarity: active level of chip select (reset=0) 1 cs_polarity: active level of chip select (reset=0)
1 clk_polarity: idle level of clk (reset=0) 1 clk_polarity: idle level of clk (reset=0)
1 clk_phase: first edge after cs assertion to sample data on (reset=0) 1 clk_phase: first edge after cs assertion to sample data on (reset=0)
@ -246,18 +250,18 @@ class SPIMaster(Module):
8 div_read: ditto for the read clock 8 div_read: ditto for the read clock
xfer (address 1): xfer (address 1):
16 cs: active high bit mask of chip selects to assert 16 cs: active high bit mask of chip selects to assert (reset=0)
6 write_len: 0-M bits 6 write_len: 0-M bits (reset=0)
2 undefined 2 undefined
6 read_len: 0-M bits 6 read_len: 0-M bits (reset=0)
2 undefined 2 undefined
data (address 0): data (address 0):
M write/read data M write/read data (reset=0)
""" """
def __init__(self, pads, bus=None, data_width=32): def __init__(self, pads, bus=None):
if bus is None: if bus is None:
bus = wishbone.Interface(data_width=data_width) bus = wishbone.Interface(data_width=32)
self.bus = bus self.bus = bus
### ###
@ -289,7 +293,8 @@ class SPIMaster(Module):
assert len(xfer) <= len(bus.dat_w) assert len(xfer) <= len(bus.dat_w)
self.submodules.spi = spi = SPIMachine( self.submodules.spi = spi = SPIMachine(
data_width, clock_width=len(config.div_read), data_width=len(bus.dat_w),
clock_width=len(config.div_read),
bits_width=len(xfer.read_length)) bits_width=len(xfer.read_length))
pending = Signal() pending = Signal()
@ -318,17 +323,23 @@ class SPIMaster(Module):
spi.reg.data.eq(data_write), spi.reg.data.eq(data_write),
pending.eq(0), pending.eq(0),
), ),
bus.ack.eq(bus.cyc & bus.stb & (~bus.we | ~pending | spi.done)), # wb.ack a transaction if any of the following:
# a) reading,
# b) writing to non-data register
# c) writing to data register and no pending transfer
# d) writing to data register and pending and swapping buffers
bus.ack.eq(bus.cyc & bus.stb &
(~bus.we | (bus.adr != 0) | ~pending | spi.done)),
If(bus.ack, If(bus.ack,
bus.ack.eq(0), bus.ack.eq(0),
), If(bus.we,
If(bus.we & bus.ack,
Array([data_write, xfer.raw_bits(), config.raw_bits() Array([data_write, xfer.raw_bits(), config.raw_bits()
])[bus.adr].eq(bus.dat_w), ])[bus.adr].eq(bus.dat_w),
If(bus.adr == 0, # data register If(bus.adr == 0, # data register
pending.eq(1), pending.eq(1),
), ),
), ),
),
config.active.eq(spi.cs), config.active.eq(spi.cs),
config.pending.eq(pending), config.pending.eq(pending),
] ]