From 416f1b42816a90db8fb247afc9d1de24b0a271d1 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Sun, 25 Feb 2024 13:24:24 +1100 Subject: [PATCH] cores/spi_mmap: add slot post transfer cs_wait Also remove unused slot_status - maintains CSR alignment now that slot_control is 64 bit (two 32bit registers). --- litex/soc/cores/spi/spi_mmap.py | 35 +++++++++++++++++++++++++++------ test/test_spi_mmap.py | 12 +++++++++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/litex/soc/cores/spi/spi_mmap.py b/litex/soc/cores/spi/spi_mmap.py index 452c6a6b2..f9ac6b160 100644 --- a/litex/soc/cores/spi/spi_mmap.py +++ b/litex/soc/cores/spi/spi_mmap.py @@ -244,10 +244,10 @@ class SPICtrl(LiteXModule): default_slot_loopback = 0b1, default_slot_divider = 2, default_enable = 0b1, + default_slot_wait = 0, ): self.nslots = nslots self.slot_controls = [] - self.slot_status = [] version = "SPI0" self._version = CSRStatus(size=32, description="""SPI Module Version.""", @@ -354,13 +354,15 @@ class SPICtrl(LiteXModule): ("``0x0002``", "SPI-Clk = Sys-Clk/2."), ("``0x0004``", "SPI-Clk = Sys-Clk/4."), ("``0xxxxx``", "SPI-Clk = Sys-Clk/xxxxx."), - ], reset=default_slot_divider) + ], reset=default_slot_divider), + CSRField("wait", size=16, offset=32, values=[ + ("``0x0000``", "No wait time."), + ("``0x0001``", "wait = 1 / Sys-Clk."), + ("``0xxxxx``", "wait = xxxx / Sys-Clk."), + ], reset=default_slot_wait), ]) - status = CSRStatus(name=f"slot_status{slot}") # CHECKME: Useful? setattr(self, f"slot_control{slot}", control) - setattr(self, f"slot_status{slot}", status) self.slot_controls.append(control) - self.slot_status.append(status) def get_ctrl(self, name, slot=None, cs=None): assert not ((slot is None) and (cs is None)) @@ -556,8 +558,15 @@ class SPIEngine(LiteXModule): ) ] + # Wait between transfers. + ctrl_wait = ctrl.get_ctrl("wait", cs=sink.cs) + wait_ticks = Signal.like(ctrl_wait) + wait_count = Signal.like(ctrl_wait) + self.comb += wait_ticks.eq(ctrl_wait) + cs_wait = Signal() + # SPI CS. (Use Manual CS to allow back-to-back Xfers). - self.comb += If(ctrl.engine.fields.enable & sink.valid, + self.comb += If(ctrl.engine.fields.enable & sink.valid & ~cs_wait, spi.cs.eq(sink.cs) ) @@ -584,6 +593,20 @@ class SPIEngine(LiteXModule): source.be.eq(sink.be), If(source.ready, sink.ready.eq(1), + If(wait_ticks, + cs_wait.eq(1), + NextValue(wait_count, wait_ticks-1), + NextState("WAIT") + ).Else( + NextState("START") + ) + ) + ) + fsm.act("WAIT", + If(wait_count, + cs_wait.eq(1), + NextValue(wait_count, wait_count-1) + ).Else( NextState("START") ) ) diff --git a/test/test_spi_mmap.py b/test/test_spi_mmap.py index c5465bcc6..6d1924ac3 100644 --- a/test/test_spi_mmap.py +++ b/test/test_spi_mmap.py @@ -139,7 +139,7 @@ class TestSPIMMAP(unittest.TestCase): run_simulation(dut, generator(dut), vcd_name="sim.vcd") - def mmap_test(self, length, bitorder, data, vcd_name=None, sel_override=None): + def mmap_test(self, length, bitorder, data, vcd_name=None, sel_override=None, wait=0): pads = Record([("clk", 1), ("cs_n", 4), ("mosi", 1), ("miso", 1)]) dut = SPIMMAP( pads=pads, @@ -151,7 +151,7 @@ class TestSPIMMAP(unittest.TestCase): def generator(dut): # Minimal setup - spi_mmap ctrl defaults are everything enabled and: - # SPI_SLOT_MODE_3, SPI_SLOT_LENGTH_32B, SPI_SLOT_BITORDER_MSB_FIRST, loopback, divider=2, + # SPI_SLOT_MODE_3, SPI_SLOT_LENGTH_32B, SPI_SLOT_BITORDER_MSB_FIRST, loopback, divider=2, wait=0 version = yield dut.ctrl._version.status vprint(f"version: {version}") vprint(f"slot_count: {(yield dut.ctrl.slot_count.status)}") @@ -162,6 +162,7 @@ class TestSPIMMAP(unittest.TestCase): # yield dut.ctrl.slot_control0.fields.loopback.eq(1) # yield dut.ctrl.slot_control0.fields.divider.eq(2) # yield dut.ctrl.slot_control0.fields.enable.eq(1) + yield dut.ctrl.slot_control0.fields.wait.eq(wait) if length == SPI_SLOT_LENGTH_32B: spi_length = 32 sel = 0b1111 @@ -284,6 +285,13 @@ class TestSPIMMAP(unittest.TestCase): data = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0] self.mmap_test(SPI_SLOT_LENGTH_8B, SPI_SLOT_BITORDER_MSB_FIRST, data, "mmap_8_msb.vcd") + def test_spi_mmap_8_msb_wait1(self): + data = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0] + self.mmap_test(SPI_SLOT_LENGTH_8B, SPI_SLOT_BITORDER_MSB_FIRST, data, "mmap_8_msb_wait1.vcd", wait=1) + + def test_spi_mmap_8_msb_wait8(self): + data = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0] + self.mmap_test(SPI_SLOT_LENGTH_8B, SPI_SLOT_BITORDER_MSB_FIRST, data, "mmap_8_msb_wait8.vcd", wait=8) if __name__ == "__main__": unittest.main()