From 8d761360cbb661e8c9aa3ade570d30c31b1d79d4 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Tue, 31 Dec 2024 21:03:39 +0100 Subject: [PATCH] feat: implement spi model narrow sck check --- hdl_spi/models/spi_models.py | 28 +++++++++++++++++++++------ hdl_spi/tests/test_spi_masterslave.py | 7 ++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/hdl_spi/models/spi_models.py b/hdl_spi/models/spi_models.py index a1680d6..a1f81c1 100644 --- a/hdl_spi/models/spi_models.py +++ b/hdl_spi/models/spi_models.py @@ -4,6 +4,7 @@ from dataclasses import dataclass from cocotb.queue import Queue from cocotb.clock import Clock from cocotb.triggers import Trigger, First, Event, Timer, Edge, RisingEdge, FallingEdge +from cocotb.utils import get_sim_time import logging @@ -100,7 +101,19 @@ class SpiSlave: async def wait_all(self): await self._idle.wait() + + async def _check_sck_period(self): + await Edge(self.sck) + while True: + sim_time = get_sim_time(self.config.sck_period_unit) + await Edge(self.sck) + next_sim_time = get_sim_time(self.config.sck_period_unit) + + if next_sim_time - sim_time > 0 and (next_sim_time - sim_time) * 1.0005 < self.config.sck_period / 2: + raise Exception(f"The sck pulse is too narrow! (was: {next_sim_time - sim_time} {self.config.sck_period_unit}, expected: {self.config.sck_period / 2} {self.config.sck_period_unit})") + async def coroutine(self): + await cocotb.start(self._check_sck_period()) while True: if self.transactions.empty(): self._idle.set() @@ -176,17 +189,20 @@ class SpiSlave: break # now wait for csn rising - timeout = Timer(self.config.sck_period * 2, self.config.sck_period_unit) - # sck_edge = Edge(self.sck) - csn_rising = RisingEdge(self.csn) - res = await First(csn_rising, timeout) + sim_time = get_sim_time(self.config.sck_period_unit) + while sim_time == get_sim_time(self.config.sck_period_unit): + timeout = Timer(self.config.sck_period * 2, self.config.sck_period_unit) + sck_edge = self.config.sampling(self.sck) + csn_rising = RisingEdge(self.csn) + res = await First(csn_rising, sck_edge, timeout) if res == timeout: self._log.error("Got no rising edge on csn") raise Exception("Got no rising edge on csn") continue - # elif res == sck_edge: - # self._log.error("Got sck edge when csn rising was expected") + elif res == sck_edge: + self._log.error("Got sck edge when csn rising was expected") + raise Exception("Got sck edge when csn rising was expected") self._log.info("csn is rising") diff --git a/hdl_spi/tests/test_spi_masterslave.py b/hdl_spi/tests/test_spi_masterslave.py index 967a86d..816e959 100644 --- a/hdl_spi/tests/test_spi_masterslave.py +++ b/hdl_spi/tests/test_spi_masterslave.py @@ -455,7 +455,7 @@ async def inverted_clock(dut): async def shifted_inverted_clock(dut): clk = Clock(dut.clk_i, 5, "ns") interface = SpiInterface(dut.csn_o, dut.sck_o, dut.miso_i, dut.mosi_o) - config = SpiConfig(8, FallingEdge, RisingEdge, 20, "ns") + config = SpiConfig(8, FallingEdge, RisingEdge, 10, "ns") slave = SpiSlave(interface, config) driver = DutDriver(dut) @@ -474,6 +474,7 @@ async def shifted_inverted_clock(dut): count = 3 await perform_multiple_transmits(count, dut, slave, driver) + await Timer(100, "ns") dut.clock_phase_i.value = 1 dut.clock_polarity_i.value = 0 await FallingEdge(dut.clk_i) @@ -486,7 +487,7 @@ async def shifted_inverted_clock(dut): async def sixteen_bits(dut): clk = Clock(dut.clk_i, 5, "ns") interface = SpiInterface(dut.csn_o, dut.sck_o, dut.miso_i, dut.mosi_o) - config = SpiConfig(16, FallingEdge, RisingEdge, 20, "ns") + config = SpiConfig(16, FallingEdge, RisingEdge, 10, "ns") slave = SpiSlave(interface, config) driver = DutDriver(dut) @@ -538,7 +539,7 @@ async def rx_blocking_tx(dut): async def csn_pulse(dut): clk = Clock(dut.clk_i, 5, "ns") interface = SpiInterface(dut.csn_o, dut.sck_o, dut.miso_i, dut.mosi_o) - config = SpiConfig(16, RisingEdge, FallingEdge, 20, "ns", csn_pulse = True) + config = SpiConfig(16, RisingEdge, FallingEdge, 10, "ns", csn_pulse = True) slave = SpiSlave(interface, config) driver = DutDriver(dut) -- 2.48.1