Deprecate slave terminology
http://oshwa.org/a-resolution-to-redefine-spi-signal-names
This commit is contained in:
parent
00d1118d41
commit
0b4c5059f2
|
@ -16,13 +16,17 @@ class I2S_FORMAT(Enum):
|
||||||
I2S_LEFT_JUSTIFIED = 2
|
I2S_LEFT_JUSTIFIED = 2
|
||||||
|
|
||||||
class S7I2S(Module, AutoCSR, AutoDoc):
|
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
|
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.
|
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.
|
- 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.
|
Have be the same as your sys_clk.
|
||||||
|
@ -31,8 +35,8 @@ class S7I2S(Module, AutoCSR, AutoDoc):
|
||||||
- bits_per_channel - defines SCLK frequency. Mind you, that based on sys_clk frequency,
|
- 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.
|
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
|
When device is configured as peripheral I2S interface, sampling rate and framing is set by the
|
||||||
programming of the audio CODEC chip. A slave configuration defers 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
|
generation of audio clocks to the CODEC, which has PLLs specialized to generate the correct
|
||||||
frequencies for audio sampling rates.
|
frequencies for audio sampling rates.
|
||||||
|
|
||||||
|
@ -163,7 +167,7 @@ class S7I2S(Module, AutoCSR, AutoDoc):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
if master == True:
|
if controller == True:
|
||||||
if bits_per_channel < sample_width and frame_format == I2S_FORMAT.I2S_STANDARD:
|
if bits_per_channel < sample_width and frame_format == I2S_FORMAT.I2S_STANDARD:
|
||||||
bits_per_channel = sample_width + 1
|
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))
|
print("I2S warning: bits per channel can't be smaller than sample_width. Setting bits per channel to {}".format(sample_width + 1))
|
||||||
|
|
|
@ -14,7 +14,7 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
dq_delay_taps = 31,
|
dq_delay_taps = 31,
|
||||||
sclk_name = "SCLK_ODDR",
|
sclk_name = "SCLK_ODDR",
|
||||||
iddr_name = "SPI_IDDR",
|
iddr_name = "SPI_IDDR",
|
||||||
miso_name = "MISO_FDRE",
|
cipo_name = "CIPO_FDRE",
|
||||||
sim = False,
|
sim = False,
|
||||||
spiread = False,
|
spiread = False,
|
||||||
prefetch_lines = 1):
|
prefetch_lines = 1):
|
||||||
|
@ -100,8 +100,8 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
self.di = Signal(16) # OPI data from SPI
|
self.di = Signal(16) # OPI data from SPI
|
||||||
self.tx = Signal() # When asserted OPI is transmitting data to SPI, otherwise, receiving
|
self.tx = Signal() # When asserted OPI is transmitting data to SPI, otherwise, receiving
|
||||||
|
|
||||||
self.mosi = Signal() # SPI data to SPI
|
self.copi = Signal() # SPI data to SPI
|
||||||
self.miso = Signal() # SPI data from SPI
|
self.cipo = Signal() # SPI data from SPI
|
||||||
|
|
||||||
# Delay programming API
|
# Delay programming API
|
||||||
self.delay_config = CSRStorage(fields=[
|
self.delay_config = CSRStorage(fields=[
|
||||||
|
@ -125,7 +125,7 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
self.comb += self.di.eq(Cat(di_fall, di_rise))
|
self.comb += self.di.eq(Cat(di_fall, di_rise))
|
||||||
|
|
||||||
# OPI DDR registers
|
# 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)
|
dq_delayed = Signal(8)
|
||||||
self.specials += dq.get_tristate(pads.dq[1:])
|
self.specials += dq.get_tristate(pads.dq[1:])
|
||||||
for i in range(1, 8):
|
for i in range(1, 8):
|
||||||
|
@ -198,19 +198,19 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
)
|
)
|
||||||
# SPI SDR register
|
# SPI SDR register
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("FDRE", name="{}".format(miso_name),
|
Instance("FDRE", name="{}".format(cipo_name),
|
||||||
i_C = ~ClockSignal("spinor"),
|
i_C = ~ClockSignal("spinor"),
|
||||||
i_CE = 1,
|
i_CE = 1,
|
||||||
i_R = 0,
|
i_R = 0,
|
||||||
o_Q = self.miso,
|
o_Q = self.cipo,
|
||||||
i_D = dq_delayed[1],
|
i_D = dq_delayed[1],
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# bit 0 (MOSI) is special-cased to handle SPI mode
|
# bit 0 (copi) is special-cased to handle SPI mode
|
||||||
dq_mosi = TSTriple(1) # this has similar structure but an independent "oe" signal
|
dq_copi = TSTriple(1) # this has similar structure but an independent "oe" signal
|
||||||
self.specials += dq_mosi.get_tristate(pads.dq[0])
|
self.specials += dq_copi.get_tristate(pads.dq[0])
|
||||||
do_mux_rise = Signal() # mux signal for mosi/dq select of bit 0
|
do_mux_rise = Signal() # mux signal for copi/dq select of bit 0
|
||||||
do_mux_fall = Signal()
|
do_mux_fall = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("ODDR",
|
Instance("ODDR",
|
||||||
|
@ -221,7 +221,7 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
i_CE = 1,
|
i_CE = 1,
|
||||||
i_D1 = do_mux_rise,
|
i_D1 = do_mux_rise,
|
||||||
i_D2 = do_mux_fall,
|
i_D2 = do_mux_fall,
|
||||||
o_Q = dq_mosi.o,
|
o_Q = dq_copi.o,
|
||||||
),
|
),
|
||||||
Instance("IDDR",
|
Instance("IDDR",
|
||||||
p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
|
p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
|
||||||
|
@ -253,11 +253,11 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
i_CE = 0,
|
i_CE = 0,
|
||||||
i_LD = self.delay_update,
|
i_LD = self.delay_update,
|
||||||
i_CNTVALUEIN = self.delay_config.fields.d,
|
i_CNTVALUEIN = self.delay_config.fields.d,
|
||||||
i_IDATAIN = dq_mosi.i,
|
i_IDATAIN = dq_copi.i,
|
||||||
o_DATAOUT = dq_delayed[0],
|
o_DATAOUT = dq_delayed[0],
|
||||||
),
|
),
|
||||||
else:
|
else:
|
||||||
self.comb += dq_delayed[0].eq(dq_mosi.i)
|
self.comb += dq_delayed[0].eq(dq_copi.i)
|
||||||
|
|
||||||
# Wire up SCLK interface
|
# Wire up SCLK interface
|
||||||
clk_en = Signal()
|
clk_en = Signal()
|
||||||
|
@ -430,11 +430,11 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
# Tristate mux
|
# Tristate mux
|
||||||
self.sync += [
|
self.sync += [
|
||||||
dq.oe.eq(~spi_mode & self.tx),
|
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)
|
# 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_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.mosi)
|
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)
|
# Indicates if the current "req" requires dummy cycles to be appended (used for both OPI/SPI)
|
||||||
has_dummy = Signal()
|
has_dummy = Signal()
|
||||||
|
@ -746,7 +746,7 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
# internal signals are:
|
# internal signals are:
|
||||||
# selection - spi_mode
|
# selection - spi_mode
|
||||||
# OPI - self.do(16), self.di(16), self.tx
|
# OPI - self.do(16), self.di(16), self.tx
|
||||||
# SPI - self.mosi, self.miso
|
# SPI - self.copi, self.cipo
|
||||||
# cs_n - both
|
# cs_n - both
|
||||||
# ecs_n - OPI
|
# ecs_n - OPI
|
||||||
# clk_en - both
|
# clk_en - both
|
||||||
|
@ -758,15 +758,15 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
spi_di_load = Signal() # spi_do load is pipelined back one cycle using this mechanism
|
spi_di_load = Signal() # spi_do load is pipelined back one cycle using this mechanism
|
||||||
spi_di_load2 = Signal()
|
spi_di_load2 = Signal()
|
||||||
spi_ack_pipe = 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
|
# retiming reg is used to meet timing
|
||||||
self.sync += [
|
self.sync += [
|
||||||
spi_di_load2.eq(spi_di_load),
|
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),
|
spi_ack.eq(spi_ack_pipe),
|
||||||
]
|
]
|
||||||
self.comb += self.mosi.eq(spi_so[7])
|
self.comb += self.copi.eq(spi_so[7])
|
||||||
self.sync += spi_si.eq(Cat(self.miso, spi_si[:-1]))
|
self.sync += spi_si.eq(Cat(self.cipo, spi_si[:-1]))
|
||||||
self.submodules.spiphy = spiphy = FSM(reset_state="RESET")
|
self.submodules.spiphy = spiphy = FSM(reset_state="RESET")
|
||||||
spiphy.act("RESET",
|
spiphy.act("RESET",
|
||||||
If(spi_req,
|
If(spi_req,
|
||||||
|
@ -1056,7 +1056,7 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc):
|
||||||
NextValue(spi_req, 0),
|
NextValue(spi_req, 0),
|
||||||
If(spi_ack,
|
If(spi_ack,
|
||||||
# Protect these in a spi_mode mux to prevent excess inference of logic to
|
# 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,
|
If(spi_mode,
|
||||||
NextValue(bus.dat_r, Cat(d_to_wb[8:],spi_di)),
|
NextValue(bus.dat_r, Cat(d_to_wb[8:],spi_di)),
|
||||||
NextValue(bus.ack, 1),
|
NextValue(bus.ack, 1),
|
||||||
|
|
Loading…
Reference in New Issue