mirror of
https://github.com/enjoy-digital/liteeth.git
synced 2025-01-03 03:43:37 -05:00
Merge pull request #82 from david-sawatzke/endianconversion_sram
mac/sram: Handle endianness only in sram
This commit is contained in:
commit
f50f6d242c
4 changed files with 36 additions and 79 deletions
|
@ -23,7 +23,7 @@ class LiteEthMAC(Module, AutoCSR):
|
||||||
full_memory_we = False,
|
full_memory_we = False,
|
||||||
sys_data_path = True):
|
sys_data_path = True):
|
||||||
assert interface in ["crossbar", "wishbone", "hybrid"]
|
assert interface in ["crossbar", "wishbone", "hybrid"]
|
||||||
self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_preamble_crc, sys_data_path)
|
self.submodules.core = LiteEthMACCore(phy, dw, with_preamble_crc, sys_data_path)
|
||||||
self.csrs = []
|
self.csrs = []
|
||||||
if interface == "crossbar":
|
if interface == "crossbar":
|
||||||
self.submodules.crossbar = LiteEthMACCrossbar(dw)
|
self.submodules.crossbar = LiteEthMACCrossbar(dw)
|
||||||
|
@ -63,7 +63,7 @@ class LiteEthMAC(Module, AutoCSR):
|
||||||
assert dw == 8
|
assert dw == 8
|
||||||
# Hardware MAC
|
# Hardware MAC
|
||||||
self.submodules.crossbar = LiteEthMACCrossbar(dw)
|
self.submodules.crossbar = LiteEthMACCrossbar(dw)
|
||||||
self.submodules.mac_crossbar = LiteEthMACCoreCrossbar(self.core, self.crossbar, self.interface, dw, endianness, hw_mac)
|
self.submodules.mac_crossbar = LiteEthMACCoreCrossbar(self.core, self.crossbar, self.interface, dw, hw_mac)
|
||||||
else:
|
else:
|
||||||
assert dw == 32
|
assert dw == 32
|
||||||
self.comb += self.interface.source.connect(self.core.sink)
|
self.comb += self.interface.source.connect(self.core.sink)
|
||||||
|
@ -75,12 +75,10 @@ class LiteEthMAC(Module, AutoCSR):
|
||||||
# MAC Core Crossbar --------------------------------------------------------------------------------
|
# MAC Core Crossbar --------------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteEthMACCoreCrossbar(Module):
|
class LiteEthMACCoreCrossbar(Module):
|
||||||
def __init__(self, core, crossbar, interface, dw, endianness, hw_mac=None):
|
def __init__(self, core, crossbar, interface, dw, hw_mac=None):
|
||||||
rx_ready = Signal()
|
rx_ready = Signal()
|
||||||
rx_valid = Signal()
|
rx_valid = Signal()
|
||||||
|
|
||||||
reverse = endianness == "big"
|
|
||||||
|
|
||||||
tx_pipe = []
|
tx_pipe = []
|
||||||
rx_pipe = []
|
rx_pipe = []
|
||||||
|
|
||||||
|
@ -91,13 +89,11 @@ class LiteEthMACCoreCrossbar(Module):
|
||||||
self.submodules += tx_last_be, rx_last_be
|
self.submodules += tx_last_be, rx_last_be
|
||||||
|
|
||||||
tx_converter = stream.StrideConverter(
|
tx_converter = stream.StrideConverter(
|
||||||
description_from = eth_phy_description(32),
|
description_from=eth_phy_description(32),
|
||||||
description_to = eth_phy_description(dw),
|
description_to=eth_phy_description(dw))
|
||||||
reverse = reverse)
|
|
||||||
rx_converter = stream.StrideConverter(
|
rx_converter = stream.StrideConverter(
|
||||||
description_from = eth_phy_description(dw),
|
description_from=eth_phy_description(dw),
|
||||||
description_to = eth_phy_description(32),
|
description_to=eth_phy_description(32))
|
||||||
reverse = reverse)
|
|
||||||
rx_pipe += [rx_converter]
|
rx_pipe += [rx_converter]
|
||||||
tx_pipe += [tx_converter]
|
tx_pipe += [tx_converter]
|
||||||
self.submodules += tx_converter, rx_converter
|
self.submodules += tx_converter, rx_converter
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
from liteeth.common import *
|
from liteeth.common import *
|
||||||
from liteeth.mac import gap, preamble, crc, padding, last_be, endian_converter
|
from liteeth.mac import gap, preamble, crc, padding, last_be
|
||||||
from liteeth.phy.model import LiteEthPHYModel
|
from liteeth.phy.model import LiteEthPHYModel
|
||||||
|
|
||||||
from migen.genlib.cdc import PulseSynchronizer
|
from migen.genlib.cdc import PulseSynchronizer
|
||||||
|
@ -18,7 +18,6 @@ from litex.soc.interconnect.stream import BufferizeEndpoints, DIR_SOURCE, DIR_SI
|
||||||
|
|
||||||
class LiteEthMACCore(Module, AutoCSR):
|
class LiteEthMACCore(Module, AutoCSR):
|
||||||
def __init__(self, phy, dw,
|
def __init__(self, phy, dw,
|
||||||
endianness = "big",
|
|
||||||
with_preamble_crc = True,
|
with_preamble_crc = True,
|
||||||
sys_data_path = True,
|
sys_data_path = True,
|
||||||
with_padding = True):
|
with_padding = True):
|
||||||
|
@ -31,8 +30,7 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
tx_pipeline = [phy]
|
tx_pipeline = [phy]
|
||||||
|
|
||||||
if sys_data_path:
|
if sys_data_path:
|
||||||
# The pipeline for dw>8 only works for little endian
|
self.data_path_converter(tx_pipeline, rx_pipeline, core_dw, phy.dw)
|
||||||
self.data_path_converter(tx_pipeline, rx_pipeline, core_dw, phy.dw, "little")
|
|
||||||
cd_tx = cd_rx = "sys"
|
cd_tx = cd_rx = "sys"
|
||||||
dw = core_dw
|
dw = core_dw
|
||||||
else:
|
else:
|
||||||
|
@ -94,17 +92,8 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
tx_pipeline += [padding_inserter]
|
tx_pipeline += [padding_inserter]
|
||||||
rx_pipeline += [padding_checker]
|
rx_pipeline += [padding_checker]
|
||||||
|
|
||||||
if sys_data_path:
|
if not sys_data_path:
|
||||||
# Since the pipeline only works for little endian when dw > 8,
|
self.data_path_converter(tx_pipeline, rx_pipeline, core_dw, phy.dw)
|
||||||
# convert to big endian if necessary
|
|
||||||
if endianness == "big" and dw != 8:
|
|
||||||
tx_converter = endian_converter.LiteEthMACEndianConverter(dw)
|
|
||||||
rx_converter = endian_converter.LiteEthMACEndianConverter(dw)
|
|
||||||
self.submodules += tx_converter, rx_converter
|
|
||||||
tx_pipeline += [tx_converter]
|
|
||||||
rx_pipeline += [rx_converter]
|
|
||||||
else:
|
|
||||||
self.data_path_converter(tx_pipeline, rx_pipeline, core_dw, phy.dw, endianness)
|
|
||||||
|
|
||||||
# Graph
|
# Graph
|
||||||
self.submodules.tx_pipeline = stream.Pipeline(*reversed(tx_pipeline))
|
self.submodules.tx_pipeline = stream.Pipeline(*reversed(tx_pipeline))
|
||||||
|
@ -112,7 +101,7 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
|
|
||||||
self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
|
self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
|
||||||
|
|
||||||
def data_path_converter(self, tx_pipeline, rx_pipeline, dw, phy_dw, endianness):
|
def data_path_converter(self, tx_pipeline, rx_pipeline, dw, phy_dw):
|
||||||
# Delimiters
|
# Delimiters
|
||||||
if dw != 8:
|
if dw != 8:
|
||||||
tx_last_be = last_be.LiteEthMACTXLastBE(phy_dw)
|
tx_last_be = last_be.LiteEthMACTXLastBE(phy_dw)
|
||||||
|
@ -124,15 +113,12 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
|
|
||||||
# Converters
|
# Converters
|
||||||
if dw != phy_dw:
|
if dw != phy_dw:
|
||||||
reverse = endianness == "big"
|
|
||||||
tx_converter = stream.StrideConverter(
|
tx_converter = stream.StrideConverter(
|
||||||
description_from = eth_phy_description(dw),
|
description_from = eth_phy_description(dw),
|
||||||
description_to = eth_phy_description(phy_dw),
|
description_to = eth_phy_description(phy_dw))
|
||||||
reverse = reverse)
|
|
||||||
rx_converter = stream.StrideConverter(
|
rx_converter = stream.StrideConverter(
|
||||||
description_from = eth_phy_description(phy_dw),
|
description_from = eth_phy_description(phy_dw),
|
||||||
description_to = eth_phy_description(dw),
|
description_to = eth_phy_description(dw))
|
||||||
reverse = reverse)
|
|
||||||
self.submodules += ClockDomainsRenamer("eth_tx")(tx_converter)
|
self.submodules += ClockDomainsRenamer("eth_tx")(tx_converter)
|
||||||
self.submodules += ClockDomainsRenamer("eth_rx")(rx_converter)
|
self.submodules += ClockDomainsRenamer("eth_rx")(rx_converter)
|
||||||
tx_pipeline += [tx_converter]
|
tx_pipeline += [tx_converter]
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
#
|
|
||||||
# This file is part of LiteEth.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2021 David Sawatzke <d-git@sawatzke.dev>
|
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
|
|
||||||
from liteeth.common import *
|
|
||||||
|
|
||||||
class LiteEthMACEndianConverter(Module):
|
|
||||||
def __init__(self, dw):
|
|
||||||
self.sink = sink = stream.Endpoint(eth_phy_description(dw))
|
|
||||||
self.source = source = stream.Endpoint(eth_phy_description(dw))
|
|
||||||
self.comb += [
|
|
||||||
sink.connect(source),
|
|
||||||
source.data.eq(reverse_bytes(sink.data)),
|
|
||||||
source.last_be.eq(reverse_bits(sink.last_be)),
|
|
||||||
source.error.eq(reverse_bits(sink.error)),
|
|
||||||
]
|
|
|
@ -17,8 +17,7 @@ from litex.soc.interconnect.csr_eventmanager import *
|
||||||
# MAC SRAM Writer ----------------------------------------------------------------------------------
|
# MAC SRAM Writer ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
class LastBEDecoder(Module):
|
class LastBEDecoder(Module):
|
||||||
def __init__(self, dw, endianness, last_be):
|
def __init__(self, dw, last_be):
|
||||||
assert endianness in ["big", "little"], "endianness must be either big or litte!"
|
|
||||||
assert dw % 8 == 0, "dw must be evenly divisible by 8!"
|
assert dw % 8 == 0, "dw must be evenly divisible by 8!"
|
||||||
|
|
||||||
bytes = dw // 8
|
bytes = dw // 8
|
||||||
|
@ -29,21 +28,17 @@ class LastBEDecoder(Module):
|
||||||
# the log2. This will round up.
|
# the log2. This will round up.
|
||||||
self.decoded = Signal(log2_int(bytes + 1, need_pow2=False))
|
self.decoded = Signal(log2_int(bytes + 1, need_pow2=False))
|
||||||
|
|
||||||
if endianness == "big":
|
cases = {
|
||||||
cases = {
|
**{(1 << (b - 1)): self.decoded.eq(b) for b in range(1, bytes)},
|
||||||
**{(1 << (bytes - b)): self.decoded.eq(b) for b in range(1, bytes)},
|
"default": self.decoded.eq(bytes),
|
||||||
"default": self.decoded.eq(bytes),
|
}
|
||||||
}
|
|
||||||
elif endianness == "little":
|
|
||||||
cases = {
|
|
||||||
**{(1 << (b - 1)): self.decoded.eq(b) for b in range(1, bytes)},
|
|
||||||
"default": self.decoded.eq(bytes),
|
|
||||||
}
|
|
||||||
|
|
||||||
self.comb += Case(last_be, cases)
|
self.comb += Case(last_be, cases)
|
||||||
|
|
||||||
class LiteEthMACSRAMWriter(Module, AutoCSR):
|
class LiteEthMACSRAMWriter(Module, AutoCSR):
|
||||||
def __init__(self, dw, depth, nslots=2, endianness="big", timestamp=None):
|
def __init__(self, dw, depth, nslots=2, endianness="big", timestamp=None):
|
||||||
|
assert endianness in [
|
||||||
|
"big", "little"], "endianness must be either big or litte!"
|
||||||
self.sink = sink = stream.Endpoint(eth_phy_description(dw))
|
self.sink = sink = stream.Endpoint(eth_phy_description(dw))
|
||||||
self.crc_error = Signal()
|
self.crc_error = Signal()
|
||||||
|
|
||||||
|
@ -70,7 +65,7 @@ class LiteEthMACSRAMWriter(Module, AutoCSR):
|
||||||
sink.ready.reset = 1
|
sink.ready.reset = 1
|
||||||
|
|
||||||
# Length computation
|
# Length computation
|
||||||
last_be_dec = LastBEDecoder(dw, endianness, sink.last_be)
|
last_be_dec = LastBEDecoder(dw, sink.last_be)
|
||||||
self.submodules += last_be_dec
|
self.submodules += last_be_dec
|
||||||
inc = last_be_dec.decoded
|
inc = last_be_dec.decoded
|
||||||
|
|
||||||
|
@ -164,12 +159,13 @@ class LiteEthMACSRAMWriter(Module, AutoCSR):
|
||||||
ports[n] = mems[n].get_port(write_capable=True)
|
ports[n] = mems[n].get_port(write_capable=True)
|
||||||
self.specials += ports[n]
|
self.specials += ports[n]
|
||||||
self.mems = mems
|
self.mems = mems
|
||||||
|
data = reverse_bytes(sink.data) if endianness == "big" else sink.data
|
||||||
|
|
||||||
cases = {}
|
cases = {}
|
||||||
for n, port in enumerate(ports):
|
for n, port in enumerate(ports):
|
||||||
cases[n] = [
|
cases[n] = [
|
||||||
ports[n].adr.eq(counter[log2_int(dw // 8):]),
|
ports[n].adr.eq(counter[log2_int(dw // 8):]),
|
||||||
ports[n].dat_w.eq(sink.data),
|
ports[n].dat_w.eq(data),
|
||||||
If(sink.valid & ongoing,
|
If(sink.valid & ongoing,
|
||||||
ports[n].we.eq(0xf)
|
ports[n].we.eq(0xf)
|
||||||
)
|
)
|
||||||
|
@ -179,23 +175,15 @@ class LiteEthMACSRAMWriter(Module, AutoCSR):
|
||||||
# MAC SRAM Reader ----------------------------------------------------------------------------------
|
# MAC SRAM Reader ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
class LastBEEncoder(Module):
|
class LastBEEncoder(Module):
|
||||||
def __init__(self, dw, endianness, length_lsb):
|
def __init__(self, dw, length_lsb):
|
||||||
assert endianness in ["big", "little"], "endianness must be either big or litte!"
|
|
||||||
assert dw % 8 == 0, "dw must be evenly divisible by 8!"
|
assert dw % 8 == 0, "dw must be evenly divisible by 8!"
|
||||||
bytes = dw // 8
|
bytes = dw // 8
|
||||||
|
|
||||||
self.encoded = Signal(bytes)
|
self.encoded = Signal(bytes)
|
||||||
|
|
||||||
if endianness == "big":
|
self.comb += Case(length_lsb, {
|
||||||
cases = {
|
b: self.encoded.eq(1 << ((b - 1) % bytes)) for b in range(0, bytes)
|
||||||
b: self.encoded.eq(1 << ((bytes - b) % bytes)) for b in range(0, bytes)
|
})
|
||||||
}
|
|
||||||
elif endianness == "little":
|
|
||||||
cases = {
|
|
||||||
b: self.encoded.eq(1 << ((b - 1) % bytes)) for b in range(0, bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.comb += Case(length_lsb, cases)
|
|
||||||
|
|
||||||
class LiteEthMACSRAMReader(Module, AutoCSR):
|
class LiteEthMACSRAMReader(Module, AutoCSR):
|
||||||
def __init__(self, dw, depth, nslots=2, endianness="big", timestamp=None):
|
def __init__(self, dw, depth, nslots=2, endianness="big", timestamp=None):
|
||||||
|
@ -262,7 +250,7 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
|
||||||
|
|
||||||
# Length encoding
|
# Length encoding
|
||||||
length_lsb = cmd_fifo.source.length[0:log2_int(dw // 8)]
|
length_lsb = cmd_fifo.source.length[0:log2_int(dw // 8)]
|
||||||
last_be_enc = LastBEEncoder(dw, endianness, length_lsb)
|
last_be_enc = LastBEEncoder(dw, length_lsb)
|
||||||
self.submodules += last_be_enc
|
self.submodules += last_be_enc
|
||||||
self.comb += [
|
self.comb += [
|
||||||
If(source.last,
|
If(source.last,
|
||||||
|
@ -304,12 +292,17 @@ class LiteEthMACSRAMReader(Module, AutoCSR):
|
||||||
ports[n] = mems[n].get_port()
|
ports[n] = mems[n].get_port()
|
||||||
self.specials += ports[n]
|
self.specials += ports[n]
|
||||||
self.mems = mems
|
self.mems = mems
|
||||||
|
data = Signal().like(source.data)
|
||||||
|
|
||||||
cases = {}
|
cases = {}
|
||||||
for n, port in enumerate(ports):
|
for n, port in enumerate(ports):
|
||||||
self.comb += ports[n].adr.eq(read_address[log2_int(dw // 8):])
|
self.comb += ports[n].adr.eq(read_address[log2_int(dw // 8):])
|
||||||
cases[n] = [source.data.eq(port.dat_r)]
|
cases[n] = [data.eq(port.dat_r)]
|
||||||
self.comb += Case(rd_slot, cases)
|
|
||||||
|
self.comb += [
|
||||||
|
Case(rd_slot, cases),
|
||||||
|
source.data.eq(reverse_bytes(data) if endianness == "big" else data),
|
||||||
|
]
|
||||||
|
|
||||||
# MAC SRAM -----------------------------------------------------------------------------------------
|
# MAC SRAM -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue