From 23b7f53fe2ec0fec871bc6fe1bccb8002dcf4396 Mon Sep 17 00:00:00 2001 From: Fischer Moseley <42497969+fischermoseley@users.noreply.github.com> Date: Fri, 2 Jan 2026 14:10:19 -0700 Subject: [PATCH] ethernet: bugfix in read transmit logic --- src/manta/ethernet/bridge.py | 14 +++- test/test_ether_bridge_sim.py | 123 ++++++++++++++++++++++++++++------ 2 files changed, 112 insertions(+), 25 deletions(-) diff --git a/src/manta/ethernet/bridge.py b/src/manta/ethernet/bridge.py index 9e3ef7f..f0240e6 100644 --- a/src/manta/ethernet/bridge.py +++ b/src/manta/ethernet/bridge.py @@ -58,6 +58,7 @@ class EthernetBridge(Elaboratable): m.d.sync += self.data_o.eq( Cat(MessageTypes.READ_RESPONSE, seq_num_expected + 1) ) + m.d.sync += self.valid_o.eq(1) m.next = "READ_WAIT_FOR_ADDR" with m.Elif(self.data_i[:3] == MessageTypes.WRITE_REQUEST): @@ -65,6 +66,9 @@ class EthernetBridge(Elaboratable): m.next = "WRITE_WAIT_FOR_ADDR" with m.State("READ_WAIT_FOR_ADDR"): + m.d.sync += self.valid_o.eq(0) + m.d.sync += self.data_o.eq(0) + with m.If(self.valid_i): # we have the length and the address to read from, let's go! m.d.sync += self.bus_o.addr.eq(self.data_i) @@ -98,10 +102,14 @@ class EthernetBridge(Elaboratable): # Clock out any read data from the bus with m.If(self.bus_i.valid): m.d.sync += self.data_o.eq(self.bus_i.data) + m.d.sync += self.valid_o.eq(1) + m.d.sync += self.last_o.eq(self.bus_i.last) - with m.If(self.bus_i.last): - m.d.sync += self.last_o.eq(1) - m.next = "IDLE" # TODO: could save a cycle by checking valid_i to see if there's more work to do + with m.If(self.last_o): + m.d.sync += self.data_o.eq(0) + m.d.sync += self.valid_o.eq(0) + m.d.sync += self.last_o.eq(0) + m.next = "IDLE" # TODO: could save a cycle by checking valid_i to see if there's more work to do with m.State("WRITE_WAIT_FOR_ADDR"): with m.If(self.valid_i): diff --git a/test/test_ether_bridge_sim.py b/test/test_ether_bridge_sim.py index a81253b..f4747f4 100644 --- a/test/test_ether_bridge_sim.py +++ b/test/test_ether_bridge_sim.py @@ -3,6 +3,7 @@ from amaranth import * from amaranth.lib.enum import IntEnum +from manta import * from manta.ethernet import EthernetBridge from manta.utils import * @@ -13,22 +14,22 @@ ether_bridge = EthernetBridge() from random import randint -async def send_bytes(ctx, bytes): - ctx.set(ether_bridge.ready_i, 1) - ctx.set(ether_bridge.valid_i, 1) +async def send_bytes(ctx, module, bytes): + ctx.set(module.ready_i, 1) + ctx.set(module.valid_i, 1) for i, byte in enumerate(bytes): - ctx.set(ether_bridge.data_i, byte) - ctx.set(ether_bridge.last_i, i == len(bytes) - 1) + ctx.set(module.data_i, byte) + ctx.set(module.last_i, i == len(bytes) - 1) - while not ctx.get(ether_bridge.ready_o): + while not ctx.get(module.ready_o): await ctx.tick() await ctx.tick() - ctx.set(ether_bridge.data_i, 0) - ctx.set(ether_bridge.last_i, 0) - ctx.set(ether_bridge.valid_i, 0) + ctx.set(module.data_i, 0) + ctx.set(module.last_i, 0) + ctx.set(module.valid_i, 0) await ctx.tick() @@ -62,15 +63,17 @@ async def send_bytes_sporadic(ctx, bytes): # - length (only if read request): 7 bits -async def send_write_request(ctx, seq_num, addr, write_data): - await send_bytes_sporadic( - ctx, [(seq_num << 3) | MessageTypes.WRITE_REQUEST, addr] + write_data +async def send_write_request(ctx, module, seq_num, addr, write_data): + await send_bytes( + ctx, module, [(seq_num << 3) | MessageTypes.WRITE_REQUEST, addr] + write_data ) -async def send_read_request(ctx, seq_num, addr, read_length): - await send_bytes_sporadic( - ctx, [(read_length << 16) | (seq_num << 3) | MessageTypes.READ_REQUEST, addr] +async def send_read_request(ctx, module, seq_num, addr, read_length): + await send_bytes( + ctx, + module, + [(read_length << 16) | (seq_num << 3) | MessageTypes.READ_REQUEST, addr], ) @@ -89,14 +92,90 @@ async def test_ether_bridge(ctx): # await send_write_request(ctx, seq_num=0, addr=0x1234_5678, write_data=[0x0000_0000, 0x1111_1111, 0x2222_2222]) # ctx.tick() - await send_write_request( - ctx, - seq_num=0, - addr=0x1234_5678, - write_data=[0x0000_0000, 0x1111_1111, 0x2222_2222, 0x3333_3333], - ) + # await send_write_request( + # ctx, + # seq_num=0, + # addr=0x1234_5678, + # write_data=[0x0000_0000, 0x1111_1111, 0x2222_2222, 0x3333_3333], + # ) # await send_write_request(ctx, seq_num=4, addr=0x1234_5678, write_data=[0x0000_0000, 0x1111_1111, 0x2222_2222]) - # await send_read_request(ctx, seq_num=0, addr=0x1234_5678, read_length=10) + await send_read_request( + ctx, ether_bridge, seq_num=0, addr=0x1234_5678, read_length=1 + ) + # await send_bytes(ctx, [0x0123_4567]) + # await send_bytes(ctx, [0x0123_4567, 0x89AB_CDEF]) + # await send_bytes(ctx, [0x0123_4567, 0x89AB_CDEF, 0x0123_4567]) + # await send_bytes(ctx, [0x0123_4567, 0x89AB_CDEF, 0x0123_4567, 0x89AB_CDEF]) + ctx.tick() + + for _ in range(20): + await ctx.tick() + + +# Test with a memory core attached! +class EthernetBridgePlusMemoryCore(Elaboratable): + def __init__(self): + self.data_i = Signal(32) + self.valid_i = Signal() + self.last_i = Signal() + self.ready_o = Signal() + + self.data_o = Signal(32) + self.valid_o = Signal() + self.last_o = Signal() + self.ready_i = Signal() + + def elaborate(self, platform): + m = Module() + m.submodules.bridge = bridge = EthernetBridge() + m.submodules.mem_core = mem_core = MemoryCore("host_to_fpga", 32, 1024) + mem_core.base_addr = 0 + + m.d.comb += bridge.bus_i.eq(mem_core.bus_o) + m.d.comb += mem_core.bus_i.eq(bridge.bus_o) + + m.d.comb += [ + bridge.data_i.eq(self.data_i), + bridge.valid_i.eq(self.valid_i), + bridge.last_i.eq(self.last_i), + self.ready_o.eq(bridge.ready_o), + self.data_o.eq(bridge.data_o), + self.valid_o.eq(bridge.valid_o), + self.last_o.eq(bridge.last_o), + bridge.ready_i.eq(self.ready_i), + ] + + return m + + +bridge_plus_mem_core = EthernetBridgePlusMemoryCore() + + +@simulate(bridge_plus_mem_core) +async def test_ether_bridge_plus_mem_core(ctx): + await ctx.tick() + await ctx.tick() + await ctx.tick() + + # Send a read request with a bad sequence number + # await send_read_request(ctx, seq_num=1, addr=0, read_length=1) + # await ctx.tick() + # await send_read_request(ctx, seq_num=1, addr=1, read_length=1) + # await ctx.tick() + + # await send_write_request(ctx, seq_num=0, addr=0x1234_5678, write_data=[0x0000_0000, 0x1111_1111, 0x2222_2222]) + # ctx.tick() + + # await send_write_request( + # ctx, + # seq_num=0, + # addr=0x1234_5678, + # write_data=[0x0000_0000, 0x1111_1111, 0x2222_2222, 0x3333_3333], + # ) + # await send_write_request(ctx, seq_num=4, addr=0x1234_5678, write_data=[0x0000_0000, 0x1111_1111, 0x2222_2222]) + await send_read_request( + ctx, bridge_plus_mem_core, seq_num=0, addr=0x1234_5678, read_length=1 + ) # await send_bytes(ctx, [0x0123_4567]) # await send_bytes(ctx, [0x0123_4567, 0x89AB_CDEF]) # await send_bytes(ctx, [0x0123_4567, 0x89AB_CDEF, 0x0123_4567])