I2S_LEFT_JUSTIFIED = 2
class S7I2S(Module, AutoCSR, AutoDoc):
- def __init__(self, pads, fifo_depth=256, master=False, concatenate_channels=True, sample_width=16, frame_format=I2S_FORMAT.I2S_LEFT_JUSTIFIED, lrck_ref_freq=100e6, lrck_freq=44100, bits_per_channel=28):
+ def __init__(self, pads, fifo_depth=256, controller=False, master=False, concatenate_channels=True, sample_width=16, frame_format=I2S_FORMAT.I2S_LEFT_JUSTIFIED, lrck_ref_freq=100e6, lrck_freq=44100, bits_per_channel=28):
+ if master == True:
+ print("Master/slave terminology deprecated, please use controller/peripheral. Please see http://oshwa.org/a-resolution-to-redefine-spi-signal-names.")
+ controller = True
+
self.intro = ModuleDoc("""Intro
- I2S master/slave creates a master/slave audio interface instance depending on a configured master variable.
+ I2S controller/peripheral creates a controller/peripheral audio interface instance depending on a configured controller variable.
Tx and Rx interfaces are inferred based upon the presence or absence of the respective pins in the "pads" argument.
- When device is configured as master you can manipulate LRCK and SCLK signals using below variables.
+ When device is configured as controller you can manipulate LRCK and SCLK signals using below variables.
- lrck_ref_freq - is a reference signal that is required to achive desired LRCK and SCLK frequencies.
Have be the same as your sys_clk.
- bits_per_channel - defines SCLK frequency. Mind you, that based on sys_clk frequency,
the requested amount of bits per channel may vary from configured.
- When device is configured as slave I2S interface, sampling rate and framing is set by the
- programming of the audio CODEC chip. A slave configuration defers the
+ When device is configured as peripheral I2S interface, sampling rate and framing is set by the
+ programming of the audio CODEC chip. A peripheral configuration defers the
generation of audio clocks to the CODEC, which has PLLs specialized to generate the correct
frequencies for audio sampling rates.
]
- if master == True:
+ if controller == True:
if bits_per_channel < sample_width and frame_format == I2S_FORMAT.I2S_STANDARD:
bits_per_channel = sample_width + 1
print("I2S warning: bits per channel can't be smaller than sample_width. Setting bits per channel to {}".format(sample_width + 1))
dq_delay_taps = 31,
sclk_name = "SCLK_ODDR",
iddr_name = "SPI_IDDR",
- miso_name = "MISO_FDRE",
+ cipo_name = "CIPO_FDRE",
sim = False,
spiread = False,
prefetch_lines = 1):
self.di = Signal(16) # OPI data from SPI
self.tx = Signal() # When asserted OPI is transmitting data to SPI, otherwise, receiving
- self.mosi = Signal() # SPI data to SPI
- self.miso = Signal() # SPI data from SPI
+ self.copi = Signal() # SPI data to SPI
+ self.cipo = Signal() # SPI data from SPI
# Delay programming API
self.delay_config = CSRStorage(fields=[
self.comb += self.di.eq(Cat(di_fall, di_rise))
# OPI DDR registers
- dq = TSTriple(7) # dq[0] is special because it is also MOSI
+ dq = TSTriple(7) # dq[0] is special because it is also copi
dq_delayed = Signal(8)
self.specials += dq.get_tristate(pads.dq[1:])
for i in range(1, 8):
)
# SPI SDR register
self.specials += [
- Instance("FDRE", name="{}".format(miso_name),
+ Instance("FDRE", name="{}".format(cipo_name),
i_C = ~ClockSignal("spinor"),
i_CE = 1,
i_R = 0,
- o_Q = self.miso,
+ o_Q = self.cipo,
i_D = dq_delayed[1],
)
]
- # bit 0 (MOSI) is special-cased to handle SPI mode
- dq_mosi = TSTriple(1) # this has similar structure but an independent "oe" signal
- self.specials += dq_mosi.get_tristate(pads.dq[0])
- do_mux_rise = Signal() # mux signal for mosi/dq select of bit 0
+ # bit 0 (copi) is special-cased to handle SPI mode
+ dq_copi = TSTriple(1) # this has similar structure but an independent "oe" signal
+ self.specials += dq_copi.get_tristate(pads.dq[0])
+ do_mux_rise = Signal() # mux signal for copi/dq select of bit 0
do_mux_fall = Signal()
self.specials += [
Instance("ODDR",
i_CE = 1,
i_D1 = do_mux_rise,
i_D2 = do_mux_fall,
- o_Q = dq_mosi.o,
+ o_Q = dq_copi.o,
),
Instance("IDDR",
p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
i_CE = 0,
i_LD = self.delay_update,
i_CNTVALUEIN = self.delay_config.fields.d,
- i_IDATAIN = dq_mosi.i,
+ i_IDATAIN = dq_copi.i,
o_DATAOUT = dq_delayed[0],
),
else:
- self.comb += dq_delayed[0].eq(dq_mosi.i)
+ self.comb += dq_delayed[0].eq(dq_copi.i)
# Wire up SCLK interface
clk_en = Signal()
# Tristate mux
self.sync += [
dq.oe.eq(~spi_mode & self.tx),
- dq_mosi.oe.eq(spi_mode | self.tx),
+ dq_copi.oe.eq(spi_mode | self.tx),
]
# Data out mux (no data in mux, as we can just sample data in all the time without harm)
- self.comb += do_mux_rise.eq(~spi_mode & do_rise[0] | spi_mode & self.mosi)
- self.comb += do_mux_fall.eq(~spi_mode & do_fall[0] | spi_mode & self.mosi)
+ self.comb += do_mux_rise.eq(~spi_mode & do_rise[0] | spi_mode & self.copi)
+ self.comb += do_mux_fall.eq(~spi_mode & do_fall[0] | spi_mode & self.copi)
# Indicates if the current "req" requires dummy cycles to be appended (used for both OPI/SPI)
has_dummy = Signal()
# internal signals are:
# selection - spi_mode
# OPI - self.do(16), self.di(16), self.tx
- # SPI - self.mosi, self.miso
+ # SPI - self.copi, self.cipo
# cs_n - both
# ecs_n - OPI
# clk_en - both
spi_di_load = Signal() # spi_do load is pipelined back one cycle using this mechanism
spi_di_load2 = Signal()
spi_ack_pipe = Signal()
- # Pipelining is required the MISO path is very slow (IOB->fabric FD), and a falling-edge
+ # Pipelining is required the cipo path is very slow (IOB->fabric FD), and a falling-edge
# retiming reg is used to meet timing
self.sync += [
spi_di_load2.eq(spi_di_load),
- If(spi_di_load2, spi_di.eq(Cat(self.miso, spi_si[:-1]))).Else(spi_di.eq(spi_di)),
+ If(spi_di_load2, spi_di.eq(Cat(self.cipo, spi_si[:-1]))).Else(spi_di.eq(spi_di)),
spi_ack.eq(spi_ack_pipe),
]
- self.comb += self.mosi.eq(spi_so[7])
- self.sync += spi_si.eq(Cat(self.miso, spi_si[:-1]))
+ self.comb += self.copi.eq(spi_so[7])
+ self.sync += spi_si.eq(Cat(self.cipo, spi_si[:-1]))
self.submodules.spiphy = spiphy = FSM(reset_state="RESET")
spiphy.act("RESET",
If(spi_req,
NextValue(spi_req, 0),
If(spi_ack,
# Protect these in a spi_mode mux to prevent excess inference of logic to
- # handle otherwise implicit dual-master situation
+ # handle otherwise implicit dual-controller situation
If(spi_mode,
NextValue(bus.dat_r, Cat(d_to_wb[8:],spi_di)),
NextValue(bus.ack, 1),