ethernet: use new bridge in EthernetInterface
This commit is contained in:
parent
6563446724
commit
226d1afd9a
|
|
@ -4,8 +4,7 @@ from random import getrandbits
|
|||
from amaranth import *
|
||||
from amaranth.hdl import IOPort
|
||||
|
||||
from manta.ethernet.sink_bridge import UDPSinkBridge
|
||||
from manta.ethernet.source_bridge import UDPSourceBridge
|
||||
from manta.ethernet.bridge import EthernetBridge
|
||||
from manta.utils import *
|
||||
|
||||
|
||||
|
|
@ -517,21 +516,20 @@ class EthernetInterface(Elaboratable):
|
|||
if platform:
|
||||
platform.add_file("liteeth.v", self.generate_liteeth_core())
|
||||
|
||||
m.submodules.source_bridge = source_bridge = UDPSourceBridge()
|
||||
m.submodules.sink_bridge = sink_bridge = UDPSinkBridge()
|
||||
m.submodules.bridge = bridge = EthernetBridge()
|
||||
|
||||
m.d.comb += source_bridge.data_i.eq(self._source_data)
|
||||
m.d.comb += source_bridge.last_i.eq(self._source_last)
|
||||
m.d.comb += self._source_ready.eq(source_bridge.ready_o)
|
||||
m.d.comb += source_bridge.valid_i.eq(self._source_valid)
|
||||
m.d.comb += bridge.data_i.eq(self._source_data)
|
||||
m.d.comb += bridge.last_i.eq(self._source_last)
|
||||
m.d.comb += self._source_ready.eq(bridge.ready_o)
|
||||
m.d.comb += bridge.valid_i.eq(self._source_valid)
|
||||
|
||||
m.d.comb += self._sink_data.eq(sink_bridge.data_o)
|
||||
m.d.comb += self._sink_last.eq(sink_bridge.last_o)
|
||||
m.d.comb += sink_bridge.ready_i.eq(self._sink_ready)
|
||||
m.d.comb += self._sink_valid.eq(sink_bridge.valid_o)
|
||||
m.d.comb += self._sink_data.eq(bridge.data_o)
|
||||
m.d.comb += self._sink_last.eq(bridge.last_o)
|
||||
m.d.comb += bridge.ready_i.eq(self._sink_ready)
|
||||
m.d.comb += self._sink_valid.eq(bridge.valid_o)
|
||||
|
||||
m.d.comb += sink_bridge.bus_i.eq(self.bus_i)
|
||||
m.d.comb += self.bus_o.eq(source_bridge.bus_o)
|
||||
m.d.comb += bridge.bus_i.eq(self.bus_i)
|
||||
m.d.comb += self.bus_o.eq(bridge.bus_o)
|
||||
|
||||
return m
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,8 @@
|
|||
# Test with 32-bit data/valid/ready/last interface for input, and one for output
|
||||
|
||||
from amaranth import *
|
||||
from amaranth.lib.enum import IntEnum
|
||||
|
||||
from manta.utils import *
|
||||
|
||||
|
||||
class MessageTypes(IntEnum, shape=unsigned(3)):
|
||||
READ_REQUEST = 0
|
||||
WRITE_REQUEST = 1
|
||||
READ_RESPONSE = 2
|
||||
WRITE_RESPONSE = 3
|
||||
NACK = 4
|
||||
|
||||
|
||||
class EthernetBridge(Elaboratable):
|
||||
def __init__(self):
|
||||
self.data_i = Signal(32)
|
||||
|
|
@ -116,7 +105,7 @@ class EthernetBridge(Elaboratable):
|
|||
|
||||
with m.State("WRITE_WAIT_FOR_ADDR"):
|
||||
with m.If(self.valid_i):
|
||||
m.d.sync += self.bus_i.addr.eq(self.data_i)
|
||||
m.d.sync += self.bus_o.addr.eq(self.data_i)
|
||||
m.next = "WRITE_FIRST"
|
||||
|
||||
# Don't want to increment address on the first write,
|
||||
|
|
@ -177,104 +166,3 @@ class EthernetBridge(Elaboratable):
|
|||
m.next = "IDLE"
|
||||
|
||||
return m
|
||||
|
||||
|
||||
# Actual testing below!
|
||||
|
||||
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)
|
||||
|
||||
for i, byte in enumerate(bytes):
|
||||
ctx.set(ether_bridge.data_i, byte)
|
||||
ctx.set(ether_bridge.last_i, i == len(bytes) - 1)
|
||||
|
||||
while not ctx.get(ether_bridge.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)
|
||||
await ctx.tick()
|
||||
|
||||
|
||||
async def send_bytes_sporadic(ctx, bytes):
|
||||
ctx.set(ether_bridge.ready_i, 1)
|
||||
ctx.set(ether_bridge.valid_i, 1)
|
||||
|
||||
for i, byte in enumerate(bytes):
|
||||
if randint(0, 1):
|
||||
ctx.set(ether_bridge.valid_i, 0)
|
||||
for _ in range(0, randint(1, 4)):
|
||||
await ctx.tick()
|
||||
|
||||
ctx.set(ether_bridge.valid_i, 1)
|
||||
ctx.set(ether_bridge.data_i, byte)
|
||||
ctx.set(ether_bridge.last_i, i == len(bytes) - 1)
|
||||
|
||||
while not ctx.get(ether_bridge.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)
|
||||
await ctx.tick()
|
||||
|
||||
|
||||
# - type: 3 bits
|
||||
# - seq_num: 13 bits
|
||||
# - 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_read_request(ctx, seq_num, addr, read_length):
|
||||
await send_bytes_sporadic(
|
||||
ctx, [(read_length << 16) | (seq_num << 3) | MessageTypes.READ_REQUEST, addr]
|
||||
)
|
||||
|
||||
|
||||
@simulate(ether_bridge)
|
||||
async def test_ether_bridge(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, seq_num=0, addr=0x1234_5678, read_length=10)
|
||||
# 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()
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
from amaranth import *
|
||||
|
||||
from manta.utils import *
|
||||
|
||||
|
||||
class UDPSinkBridge(Elaboratable):
|
||||
"""
|
||||
A module for bridging Manta's internal bus to an AXI stream of UDP packet
|
||||
data. Connects to the LiteEth core's "sink" port.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.bus_i = Signal(InternalBus())
|
||||
|
||||
self.data_o = Signal(32)
|
||||
self.last_o = Signal()
|
||||
self.ready_i = Signal()
|
||||
self.valid_o = Signal()
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
||||
m.d.sync += self.data_o.eq(0)
|
||||
m.d.sync += self.last_o.eq(0)
|
||||
m.d.sync += self.valid_o.eq(0)
|
||||
|
||||
with m.If((self.bus_i.valid) & (~self.bus_i.rw)):
|
||||
m.d.sync += self.data_o.eq(self.bus_i.data)
|
||||
m.d.sync += self.last_o.eq(self.bus_i.last)
|
||||
m.d.sync += self.valid_o.eq(1)
|
||||
|
||||
return m
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
from amaranth import *
|
||||
|
||||
from manta.utils import *
|
||||
|
||||
|
||||
class UDPSourceBridge(Elaboratable):
|
||||
"""
|
||||
A module for bridging the AXI-stream of incoming UDP packet data to Manta's
|
||||
internal bus. Connects to the LiteEth core's "source" port.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.bus_o = Signal(InternalBus())
|
||||
|
||||
self.data_i = Signal(32)
|
||||
self.last_i = Signal()
|
||||
self.ready_o = Signal()
|
||||
self.valid_i = Signal()
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
||||
state = Signal() # Can either be 0, for read/write, or 1, for data
|
||||
rw_buf = Signal().like(self.bus_o.rw)
|
||||
|
||||
# Can always take more data
|
||||
m.d.sync += self.ready_o.eq(1)
|
||||
|
||||
m.d.sync += self.bus_o.eq(0)
|
||||
with m.If(self.valid_i):
|
||||
m.d.sync += state.eq(~state)
|
||||
|
||||
with m.If(state == 0):
|
||||
m.d.sync += rw_buf.eq(self.data_i)
|
||||
|
||||
with m.Else():
|
||||
m.d.sync += self.bus_o.addr.eq(self.data_i[:16])
|
||||
m.d.sync += self.bus_o.data.eq(self.data_i[16:])
|
||||
m.d.sync += self.bus_o.rw.eq(rw_buf)
|
||||
m.d.sync += self.bus_o.valid.eq(1)
|
||||
m.d.sync += self.bus_o.last.eq(self.last_i)
|
||||
|
||||
return m
|
||||
|
|
@ -3,8 +3,9 @@ from abc import ABC, abstractmethod
|
|||
from pathlib import Path
|
||||
from random import sample
|
||||
|
||||
from amaranth import Elaboratable
|
||||
from amaranth import Elaboratable, unsigned
|
||||
from amaranth.lib import data
|
||||
from amaranth.lib.enum import IntEnum
|
||||
from amaranth.sim import Simulator
|
||||
|
||||
|
||||
|
|
@ -102,6 +103,14 @@ class InternalBus(data.StructLayout):
|
|||
)
|
||||
|
||||
|
||||
class MessageTypes(IntEnum, shape=unsigned(3)):
|
||||
READ_REQUEST = 0
|
||||
WRITE_REQUEST = 1
|
||||
READ_RESPONSE = 2
|
||||
WRITE_RESPONSE = 3
|
||||
NACK = 4
|
||||
|
||||
|
||||
def warn(message):
|
||||
"""
|
||||
Prints a warning to the user's terminal. Originally the warn() method
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
# Test with 32-bit data/valid/ready/last interface for input, and one for output
|
||||
|
||||
from amaranth import *
|
||||
from amaranth.lib.enum import IntEnum
|
||||
|
||||
from manta.ethernet import EthernetBridge
|
||||
from manta.utils import *
|
||||
|
||||
# Actual testing below!
|
||||
|
||||
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)
|
||||
|
||||
for i, byte in enumerate(bytes):
|
||||
ctx.set(ether_bridge.data_i, byte)
|
||||
ctx.set(ether_bridge.last_i, i == len(bytes) - 1)
|
||||
|
||||
while not ctx.get(ether_bridge.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)
|
||||
await ctx.tick()
|
||||
|
||||
|
||||
async def send_bytes_sporadic(ctx, bytes):
|
||||
ctx.set(ether_bridge.ready_i, 1)
|
||||
ctx.set(ether_bridge.valid_i, 1)
|
||||
|
||||
for i, byte in enumerate(bytes):
|
||||
if randint(0, 1):
|
||||
ctx.set(ether_bridge.valid_i, 0)
|
||||
for _ in range(0, randint(1, 4)):
|
||||
await ctx.tick()
|
||||
|
||||
ctx.set(ether_bridge.valid_i, 1)
|
||||
ctx.set(ether_bridge.data_i, byte)
|
||||
ctx.set(ether_bridge.last_i, i == len(bytes) - 1)
|
||||
|
||||
while not ctx.get(ether_bridge.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)
|
||||
await ctx.tick()
|
||||
|
||||
|
||||
# - type: 3 bits
|
||||
# - seq_num: 13 bits
|
||||
# - 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_read_request(ctx, seq_num, addr, read_length):
|
||||
await send_bytes_sporadic(
|
||||
ctx, [(read_length << 16) | (seq_num << 3) | MessageTypes.READ_REQUEST, addr]
|
||||
)
|
||||
|
||||
|
||||
@simulate(ether_bridge)
|
||||
async def test_ether_bridge(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, seq_num=0, addr=0x1234_5678, read_length=10)
|
||||
# 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()
|
||||
Loading…
Reference in New Issue