Deprecate slave terminology

http://oshwa.org/a-resolution-to-redefine-spi-signal-names
This commit is contained in:
bunnie 2020-06-25 17:12:12 +08:00
parent 00d1118d41
commit 0b4c5059f2
2 changed files with 32 additions and 28 deletions

View File

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

View File

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