diff --git a/litex/soc/cores/i2s.py b/litex/soc/cores/i2s.py index 96011ad3e..f0554d5f2 100644 --- a/litex/soc/cores/i2s.py +++ b/litex/soc/cores/i2s.py @@ -11,9 +11,7 @@ from litex.soc.integration.doc import AutoDoc, ModuleDoc class S7I2SSlave(Module, AutoCSR, AutoDoc): def __init__(self, pads, fifo_depth=256): - self.intro = ModuleDoc(""" - Intro - ******* + self.intro = ModuleDoc("""Intro I2S slave creates a slave audio interface instance. Tx and Rx interfaces are inferred based upon the presence or absence of the respective pins in the "pads" argument. @@ -24,7 +22,7 @@ class S7I2SSlave(Module, AutoCSR, AutoDoc): to a CODEC without a programmable bit offset! System Interface - ================= + ---------------- Audio interchange is done with the system using 16-bit stereo samples, with the right channel mapped to the least significant word of a 32-bit word. Thus each 32-bit word is a single @@ -56,12 +54,12 @@ class S7I2SSlave(Module, AutoCSR, AutoDoc): - enable the Tx FIFO to run - poll or wait for interrupt; upon interrupt, write `fifo_depth` words. Repeat. - to close stream, mute the DAC and stop the request clock. Ideally, this can be completed - before the FIFO is emptied, so there is no jarring pop or truncation of data + before the FIFO is emptied, so there is no jarring pop or truncation of data - stop FIFO running. Next initiation should reset the FIFO to ensure leftover previous data - in FIFO is cleared. + in FIFO is cleared. CODEC Interface - ================ + --------------- The interface assumes we have a sysclk domain running around 100MHz, and that our typical max audio rate is 44.1kHz * 24bits * 2channels = 2.1168MHz audio clock. Thus, the architecture @@ -87,12 +85,11 @@ class S7I2SSlave(Module, AutoCSR, AutoDoc): - Data is updated on the falling edge - Data is sampled on the rising edge - Words are MSB-to-LSB, left-justified (**NOTE: this is a deviation from strict I2S, which - offsets by 1 from the left**) + offsets by 1 from the left**) - Sync is an input (FPGA is slave, codec is master): low => left channel, high => right channel - Sync can be longer than the wordlen, extra bits are just ignored - Tx is data to the codec (SDI pin on LM49352) - Rx is data from the codec (SDO pin on LM49352) - """) # One cache line is 8 32-bit words, need to always have enough space for one line or else diff --git a/litex/soc/cores/spi_opi.py b/litex/soc/cores/spi_opi.py index 1e43882b9..45f477677 100644 --- a/litex/soc/cores/spi_opi.py +++ b/litex/soc/cores/spi_opi.py @@ -18,9 +18,7 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc): sim = False, spiread = False, prefetch_lines = 1): - self.intro = ModuleDoc(""" - Intro - ******** + self.intro = ModuleDoc("""Intro SpiOpi implements a dual-mode SPI or OPI interface. OPI is an octal (8-bit) wide variant of SPI, which is unique to Macronix parts. It is concurrently interoperable with SPI. The chip @@ -300,14 +298,13 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc): ), ] - self.architecture = ModuleDoc(""" - Architecture - ************** + self.architecture = ModuleDoc("""Architecture The machine is split into two separate pieces, one to handle SPI, and one to handle OPI. SPI - ===== + ----- + The SPI machine architecture is split into two levels: MAC and PHY. The MAC layer is responsible for: @@ -333,7 +330,8 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc): Thus holding "req" high can allow the PHY to back-to-back issue cycles without pause. OPI - ===== + ----- + The OPI machine is split into three parts: a command controller, a Tx PHY, and an Rx PHY. The Tx PHY is configured with a "dummy cycle" count register, as there is a variable length @@ -389,6 +387,7 @@ class S7SPIOPI(Module, AutoCSR, AutoDoc): - pre-fetch is aborted because bus_adr and next read address don't match and FIFO is reset RxPHY: + - while CTI==2, assemble data into 32-bit words as soon as EMPTY is deasserted, present a bus_ack, and increment the next read address pointer - when CTI==7, ack the data, and wait until the next bus cycle with CTI==2 to resume