Skip to content

Commit

Permalink
mac/core.py: add FIFO to TxDatapath
Browse files Browse the repository at this point in the history
  * to prevent stalling the PHY when using etherbone with DW=64
  • Loading branch information
michael-betz committed Apr 19, 2022
1 parent e849638 commit 09d59c0
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 14 deletions.
8 changes: 4 additions & 4 deletions liteeth/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
# IP Core ------------------------------------------------------------------------------------------

class LiteEthIPCore(Module, AutoCSR):
def __init__(self, phy, mac_address, ip_address, clk_freq, with_icmp=True, dw=8):
def __init__(self, phy, mac_address, ip_address, clk_freq, with_icmp=True, dw=8, anti_underflow=0):
ip_address = convert_ip(ip_address)
self.submodules.mac = LiteEthMAC(phy, dw, interface="crossbar", with_preamble_crc=True)
self.submodules.mac = LiteEthMAC(phy, dw, interface="crossbar", with_preamble_crc=True, anti_underflow=anti_underflow)
self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq, dw=dw)
self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table, dw=dw)
if with_icmp:
Expand All @@ -25,8 +25,8 @@ def __init__(self, phy, mac_address, ip_address, clk_freq, with_icmp=True, dw=8)
# UDP IP Core --------------------------------------------------------------------------------------

class LiteEthUDPIPCore(LiteEthIPCore):
def __init__(self, phy, mac_address, ip_address, clk_freq, with_icmp=True, dw=8):
def __init__(self, phy, mac_address, ip_address, clk_freq, with_icmp=True, dw=8, anti_underflow=0):
ip_address = convert_ip(ip_address)
LiteEthIPCore.__init__(self, phy, mac_address, ip_address, clk_freq, dw=dw,
with_icmp=with_icmp)
with_icmp=with_icmp, anti_underflow=anti_underflow)
self.submodules.udp = LiteEthUDP(self.ip, ip_address, dw=dw)
6 changes: 4 additions & 2 deletions liteeth/mac/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ def __init__(self, phy, dw,
hw_mac = None,
timestamp = None,
full_memory_we = False,
with_sys_datapath = False):
with_sys_datapath = False,
anti_underflow = 0):

assert dw%8 == 0
assert interface in ["crossbar", "wishbone", "hybrid"]
Expand All @@ -31,7 +32,8 @@ def __init__(self, phy, dw,
phy = phy,
dw = dw,
with_sys_datapath = with_sys_datapath,
with_preamble_crc = with_preamble_crc
with_preamble_crc = with_preamble_crc,
anti_underflow = anti_underflow
)
self.csrs = []
if interface == "crossbar":
Expand Down
46 changes: 46 additions & 0 deletions liteeth/mac/anti_underflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#
# This file is part of LiteEth.
#
# SPDX-License-Identifier: BSD-2-Clause

import math

from liteeth.common import *

# MAC Gap ------------------------------------------------------------------------------------------

class LiteEthAntiUnderflow(Module):
def __init__(self, dw, depth=32):
'''
buffers a whole packet and releases it at once
workaround for driving PHYs with wide datapaths which expect a
continuous stream
'''
self.sink = sink = stream.Endpoint(eth_phy_description(dw))
self.source = source = stream.Endpoint(eth_phy_description(dw))

# # #

self.submodules.fifo = fifo = stream.SyncFIFO(
eth_phy_description(dw),
depth,
buffered=True
)

self.comb += [
sink.connect(fifo.sink),
fifo.source.connect(source, omit=['valid', 'ready'])
]

self.submodules.fsm = fsm = FSM(reset_state="STORE")
fsm.act("STORE",
If(sink.valid & sink.last | (fifo.level >= fifo.depth - 1),
NextState("FLUSH")
)
)
fsm.act("FLUSH",
fifo.source.connect(source, keep=['valid', 'ready']),
If(fifo.source.valid & fifo.source.last,
NextState("STORE")
)
)
18 changes: 14 additions & 4 deletions liteeth/mac/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from liteeth.common import *
from liteeth.mac import gap, preamble, crc, padding, last_be
from liteeth.mac.anti_underflow import LiteEthAntiUnderflow
from liteeth.phy.model import LiteEthPHYModel

from migen.genlib.cdc import PulseSynchronizer
Expand All @@ -21,7 +22,8 @@ class LiteEthMACCore(Module, AutoCSR):
def __init__(self, phy, dw,
with_sys_datapath = False,
with_preamble_crc = True,
with_padding = True):
with_padding = True,
anti_underflow = 0):

# Endpoints.
self.sink = stream.Endpoint(eth_phy_description(dw))
Expand Down Expand Up @@ -100,6 +102,12 @@ def add_gap(self):
self.submodules += tx_gap
self.pipeline.append(tx_gap)

def add_anti_underflow(self, depth):
au = LiteEthAntiUnderflow(phy_dw, depth)
au = ClockDomainsRenamer("eth_tx")(au)
self.submodules += au
self.pipeline.append(au)

def do_finalize(self):
self.submodules += stream.Pipeline(*self.pipeline)

Expand Down Expand Up @@ -127,10 +135,12 @@ def do_finalize(self):
# Gap insertion has to occurr in phy tx domain to ensure gap is correctly maintained
if not getattr(phy, "integrated_ifg_inserter", False):
tx_datapath.add_gap()
if anti_underflow > 0:
tx_datapath.add_anti_underflow(anti_underflow)
tx_datapath.pipeline.append(phy)
# print("tx_datapath.pipeline:")
# for p in tx_datapath.pipeline:
# print(p)
print("tx_datapath.pipeline:")
for p in tx_datapath.pipeline:
print(p)
self.submodules.tx_datapath = tx_datapath

# RX Data-Path (PHY --> Core).
Expand Down
15 changes: 11 additions & 4 deletions test/test_etherbone.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,22 @@

class DUT(Module):
def __init__(self, dw):
assertStall = dw != 64
self.submodules.phy_model = phy.PHY(dw, assertStall=assertStall, pcap_file='dump_wishbone.pcap')
self.submodules.phy_model = phy.PHY(dw, assertStall=True, pcap_file='dump_wishbone.pcap')
self.submodules.mac_model = mac.MAC(self.phy_model)
self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address)
self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address)
self.submodules.udp_model = udp.UDP(self.ip_model, ip_address)
self.submodules.etherbone_model = etherbone.Etherbone(self.udp_model, debug=False)

self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address + 1, ip_address + 1, 100000, with_icmp=False, dw=dw)
self.submodules.core = LiteEthUDPIPCore(
self.phy_model,
mac_address + 1,
ip_address + 1,
100000,
with_icmp=False,
dw=dw,
anti_underflow=4
)
self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 0x1234, buffer_depth=8)

self.submodules.sram = wishbone.SRAM(1024)
Expand Down Expand Up @@ -117,7 +124,7 @@ def do_reads(self, dut, writes_datas):
self.assertEqual(writes_datas, reads_datas)

def main_generator(self, dut):
writes_datas = [((0xA + j) << 28) + j for j in range(6)]
writes_datas = [((0xA + j) << 24) + j for j in range(8)]

# push IP address into ARP table to speed up sim.
yield dut.core.arp.table.cached_valid.eq(1)
Expand Down

0 comments on commit 09d59c0

Please sign in to comment.