@@ 20,6 20,7 @@ async def init(dut, master: int = 1, tx_en: int = 1):
dut._log.info("Init started!")
dut.miso_io.value = 0;
dut.rst_in.value = 0;
+ dut.lsbfirst_i.value = 0;
dut.clock_polarity_i.value = 0;
dut.clock_phase_i.value = 0;
dut.size_sel_i.value = 0;
@@ 194,6 195,59 @@ async def single_transmit(dut):
await Timer(100, "ns")
@cocotb.test()
+async def lsbfirst(dut):
+ clk = Clock(dut.clk_i, 5, "ns")
+ interface = SpiInterface(dut.csn_io, dut.sck_io, dut.miso_io, dut.mosi_io)
+ config = SpiConfig(8, RisingEdge, FallingEdge, 10, "ns")
+ slave = SpiSlave(interface, config)
+ driver = DutDriver(dut)
+
+ await cocotb.start(clk.start())
+
+ await init(dut)
+ dut.lsbfirst_i.value = 1
+ await FallingEdge(dut.clk_i)
+
+ await cocotb.start(slave.coroutine())
+ await cocotb.start(driver.coroutine())
+
+ # From slave point of view
+ rx = random.randint(0, 255)
+ tx = random.randint(0, 255)
+
+
+ def reverse_bits(num, bits):
+ result = 0
+ for i in range(bits):
+ result = (result << 1) | (num & 1)
+ num >>= 1
+ return result
+
+ rx_reversed = reverse_bits(rx, 8)
+ tx_reversed = reverse_bits(tx, 8)
+
+ await slave.send_data(tx, 8)
+ await slave.expect_transaction_in(15, "ns")
+
+ await driver.send_data(rx)
+
+ await slave.wait_all()
+
+ dut_received = await driver.receive_data()
+ assert (int(dut_received) >> 8) & 0xFF == tx_reversed
+
+ # Wait a few clocks, rx data should still stay valid!
+ await FallingEdge(dut.clk_i)
+ await FallingEdge(dut.clk_i)
+ await FallingEdge(dut.clk_i)
+ await FallingEdge(dut.clk_i)
+
+ received = await slave.received_data()
+ assert received & 0xFF == rx_reversed
+
+ await Timer(100, "ns")
+
+@cocotb.test()
async def rx_tx_disabled(dut):
clk = Clock(dut.clk_i, 5, "ns")
interface = SpiInterface(dut.csn_io, dut.sck_io, dut.miso_io, dut.mosi_io)