mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
add LiteX external core and remove ethmac
This commit is contained in:
parent
9ebb8f8022
commit
0a38b8c74a
18 changed files with 22 additions and 1213 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -7,3 +7,6 @@
|
|||
[submodule "software/compiler-rt"]
|
||||
path = software/compiler-rt
|
||||
url = http://llvm.org/git/compiler-rt.git
|
||||
[submodule "extcores/litex"]
|
||||
path = extcores/litex
|
||||
url = https://github.com/enjoy-digital/litex
|
||||
|
|
4
extcores/__init__.py
Normal file
4
extcores/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
import os, sys
|
||||
sys.path.append(os.path.join("extcores", "litex", "litescope"))
|
||||
sys.path.append(os.path.join("extcores", "litex", "liteeth"))
|
||||
sys.path.append(os.path.join("extcores", "litex", "litesata"))
|
1
extcores/litex
Submodule
1
extcores/litex
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit dddb984ecd08953e38eb96aff8daff23da96efd2
|
|
@ -1,111 +0,0 @@
|
|||
# This file is Copyright (c) 2014 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# License: BSD
|
||||
|
||||
from migen.fhdl.std import *
|
||||
|
||||
from migen.bus import wishbone
|
||||
from migen.actorlib.fifo import AsyncFIFO
|
||||
from migen.actorlib.structuring import Converter, Pipeline
|
||||
from migen.bank.eventmanager import SharedIRQ
|
||||
from migen.bank.description import *
|
||||
from migen.fhdl.simplify import *
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
from misoclib.ethmac.preamble import PreambleInserter, PreambleChecker
|
||||
from migen.actorlib.crc import CRC32Inserter, CRC32Checker
|
||||
from misoclib.ethmac.last_be import TXLastBE, RXLastBE
|
||||
from misoclib.ethmac.sram import SRAMWriter, SRAMReader
|
||||
|
||||
class EthMAC(Module, AutoCSR):
|
||||
def __init__(self, phy, interface="wishbone", with_hw_preamble_crc=True, endianness="be"):
|
||||
# Preamble / CRC (optional)
|
||||
if with_hw_preamble_crc:
|
||||
self._hw_preamble_crc = CSRStatus(reset=1)
|
||||
# Preamble insert/check
|
||||
preamble_inserter = PreambleInserter(phy.dw)
|
||||
preamble_checker = PreambleChecker(phy.dw)
|
||||
self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
|
||||
self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
|
||||
|
||||
# CRC insert/check
|
||||
crc32_inserter = CRC32Inserter(eth_description(phy.dw))
|
||||
crc32_checker = CRC32Checker(eth_description(phy.dw))
|
||||
self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
|
||||
self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
|
||||
|
||||
# Delimiters
|
||||
tx_last_be = TXLastBE(phy.dw)
|
||||
rx_last_be = RXLastBE(phy.dw)
|
||||
self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
|
||||
self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
|
||||
|
||||
# Converters
|
||||
reverse = endianness == "be"
|
||||
tx_converter = Converter(eth_description(32), eth_description(phy.dw), reverse=reverse)
|
||||
rx_converter = Converter(eth_description(phy.dw), eth_description(32), reverse=reverse)
|
||||
self.submodules += RenameClockDomains(tx_converter, "eth_tx")
|
||||
self.submodules += RenameClockDomains(rx_converter, "eth_rx")
|
||||
|
||||
# Cross Domain Crossing
|
||||
tx_cdc = AsyncFIFO(eth_description(32), 4)
|
||||
rx_cdc = AsyncFIFO(eth_description(32), 4)
|
||||
self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
|
||||
self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
|
||||
|
||||
# Graph
|
||||
if with_hw_preamble_crc:
|
||||
rx_pipeline = [phy, preamble_checker, crc32_checker, rx_last_be, rx_converter, rx_cdc]
|
||||
tx_pipeline = [tx_cdc, tx_converter, tx_last_be, crc32_inserter, preamble_inserter, phy]
|
||||
else:
|
||||
rx_pipeline = [phy, rx_last_be, rx_converter, rx_cdc]
|
||||
tx_pipeline = [tx_cdc, tx_converter, tx_last_be, phy]
|
||||
self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
|
||||
self.submodules.tx_pipeline = Pipeline(*tx_pipeline)
|
||||
|
||||
if interface == "wishbone":
|
||||
nrxslots = 2
|
||||
ntxslots = 2
|
||||
|
||||
self.bus = wishbone.Interface()
|
||||
|
||||
# SRAM Memories
|
||||
sram_depth = buffer_depth//(32//8)
|
||||
self.submodules.sram_writer = SRAMWriter(sram_depth, nrxslots)
|
||||
self.submodules.sram_reader = SRAMReader(sram_depth, ntxslots)
|
||||
self.submodules.ev = SharedIRQ(self.sram_writer.ev, self.sram_reader.ev)
|
||||
|
||||
# Connect to pipelines
|
||||
self.comb += [
|
||||
self.rx_pipeline.source.connect(self.sram_writer.sink),
|
||||
self.sram_reader.source.connect(self.tx_pipeline.sink)
|
||||
]
|
||||
|
||||
# Interface
|
||||
wb_rx_sram_ifs = [wishbone.SRAM(self.sram_writer.mems[n], read_only=True)
|
||||
for n in range(nrxslots)]
|
||||
# TODO: FullMemoryWE should move to Mibuild
|
||||
wb_tx_sram_ifs = [FullMemoryWE(wishbone.SRAM(self.sram_reader.mems[n], read_only=False))
|
||||
for n in range(ntxslots)]
|
||||
wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs
|
||||
|
||||
wb_slaves = []
|
||||
decoderoffset = log2_int(sram_depth)
|
||||
decoderbits = log2_int(len(wb_sram_ifs))
|
||||
for n, wb_sram_if in enumerate(wb_sram_ifs):
|
||||
def slave_filter(a, v=n):
|
||||
return a[decoderoffset:decoderoffset+decoderbits] == v
|
||||
wb_slaves.append((slave_filter, wb_sram_if.bus))
|
||||
self.submodules += wb_sram_if
|
||||
wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True)
|
||||
self.submodules += wb_con
|
||||
|
||||
elif interface == "lasmi":
|
||||
raise NotImplementedError
|
||||
|
||||
elif interface == "expose":
|
||||
# expose pipelines endpoints
|
||||
self.sink = tx_pipeline.sink
|
||||
self.source = rx_pipeline.source
|
||||
|
||||
else:
|
||||
raise ValueError("EthMAC only supports Wishbone, LASMI or expose interfaces")
|
|
@ -1,14 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.flow.actor import EndpointDescription
|
||||
|
||||
eth_mtu = 1532
|
||||
eth_preamble = 0xD555555555555555
|
||||
buffer_depth = 2**log2_int(eth_mtu, need_pow2=False)
|
||||
|
||||
def eth_description(dw):
|
||||
layout = [
|
||||
("d", dw),
|
||||
("last_be", dw//8),
|
||||
("error", dw//8)
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
|
@ -1,39 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.record import *
|
||||
from migen.flow.actor import Sink, Source
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
|
||||
class TXLastBE(Module):
|
||||
def __init__(self, d_w):
|
||||
self.sink = sink = Sink(eth_description(d_w))
|
||||
self.source = source = Source(eth_description(d_w))
|
||||
|
||||
###
|
||||
|
||||
ongoing = Signal()
|
||||
self.sync += \
|
||||
If(self.sink.stb & self.sink.ack,
|
||||
If(sink.sop,
|
||||
ongoing.eq(1)
|
||||
).Elif(sink.last_be,
|
||||
ongoing.eq(0)
|
||||
)
|
||||
)
|
||||
self.comb += [
|
||||
Record.connect(self.sink, self.source),
|
||||
self.source.eop.eq(self.sink.last_be),
|
||||
self.source.stb.eq(self.sink.stb & (self.sink.sop | ongoing))
|
||||
]
|
||||
|
||||
class RXLastBE(Module):
|
||||
def __init__(self, d_w):
|
||||
self.sink = sink = Sink(eth_description(d_w))
|
||||
self.source = source = Source(eth_description(d_w))
|
||||
|
||||
###
|
||||
|
||||
self.comb += [
|
||||
Record.connect(self.sink, self.source),
|
||||
self.source.last_be.eq(self.sink.eop)
|
||||
]
|
|
@ -1,76 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.flow.actor import Sink, Source
|
||||
from migen.bank.description import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
|
||||
class GMIIPHYTX(Module):
|
||||
def __init__(self, pads):
|
||||
self.sink = sink = Sink(eth_description(8))
|
||||
|
||||
###
|
||||
|
||||
self.sync += [
|
||||
pads.tx_er.eq(0),
|
||||
pads.tx_en.eq(sink.stb),
|
||||
pads.tx_data.eq(sink.d)
|
||||
]
|
||||
self.comb += sink.ack.eq(1)
|
||||
|
||||
class GMIIPHYRX(Module):
|
||||
def __init__(self, pads):
|
||||
self.source = source = Source(eth_description(8))
|
||||
|
||||
###
|
||||
|
||||
dv_d = Signal()
|
||||
self.sync += dv_d.eq(pads.dv)
|
||||
|
||||
sop = Signal()
|
||||
eop = Signal()
|
||||
self.comb += [
|
||||
sop.eq(pads.dv & ~dv_d),
|
||||
eop.eq(~pads.dv & dv_d)
|
||||
]
|
||||
self.sync += [
|
||||
source.stb.eq(pads.dv),
|
||||
source.sop.eq(sop),
|
||||
source.d.eq(pads.rx_data)
|
||||
]
|
||||
self.comb += source.eop.eq(eop)
|
||||
|
||||
# CRG is the only Xilinx specific module.
|
||||
# TODO: use generic code or add support for others vendors
|
||||
class GMIIPHYCRG(Module, AutoCSR):
|
||||
def __init__(self, clock_pads, pads):
|
||||
self._reset = CSRStorage()
|
||||
|
||||
###
|
||||
|
||||
self.clock_domains.cd_eth_rx = ClockDomain()
|
||||
self.clock_domains.cd_eth_tx = ClockDomain()
|
||||
self.specials += [
|
||||
Instance("ODDR",
|
||||
p_DDR_CLK_EDGE="SAME_EDGE",
|
||||
i_C=ClockSignal("eth_tx"), i_CE=1, i_S=0, i_R=0,
|
||||
i_D1=1, i_D2=0, o_Q=clock_pads.gtx,
|
||||
),
|
||||
Instance("BUFG", i_I=clock_pads.rx, o_O=self.cd_eth_rx.clk),
|
||||
]
|
||||
self.comb += self.cd_eth_tx.clk.eq(self.cd_eth_rx.clk)
|
||||
|
||||
reset = self._reset.storage
|
||||
self.comb += pads.rst_n.eq(~reset)
|
||||
self.specials += [
|
||||
AsyncResetSynchronizer(self.cd_eth_tx, reset),
|
||||
AsyncResetSynchronizer(self.cd_eth_rx, reset),
|
||||
]
|
||||
|
||||
class GMIIPHY(Module, AutoCSR):
|
||||
def __init__(self, clock_pads, pads):
|
||||
self.dw = 8
|
||||
self.submodules.crg = GMIIPHYCRG(clock_pads, pads)
|
||||
self.submodules.tx = RenameClockDomains(GMIIPHYTX(pads), "eth_tx")
|
||||
self.submodules.rx = RenameClockDomains(GMIIPHYRX(pads), "eth_rx")
|
||||
self.sink, self.source = self.tx.sink, self.rx.source
|
|
@ -1,33 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.flow.actor import Sink, Source
|
||||
from migen.bank.description import *
|
||||
from migen.genlib.record import *
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
|
||||
class LoopbackPHYCRG(Module, AutoCSR):
|
||||
def __init__(self):
|
||||
self._reset = CSRStorage()
|
||||
|
||||
###
|
||||
|
||||
self.clock_domains.cd_eth_rx = ClockDomain()
|
||||
self.clock_domains.cd_eth_tx = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_eth_rx.clk.eq(ClockSignal()),
|
||||
self.cd_eth_tx.clk.eq(ClockSignal())
|
||||
]
|
||||
|
||||
reset = self._reset.storage
|
||||
self.comb += [
|
||||
self.cd_eth_rx.rst.eq(reset),
|
||||
self.cd_eth_tx.rst.eq(reset)
|
||||
]
|
||||
|
||||
class LoopbackPHY(Module, AutoCSR):
|
||||
def __init__(self):
|
||||
self.dw = 8
|
||||
self.submodules.crg = LoopbackPHYCRG()
|
||||
self.sink = sink = Sink(eth_description(8))
|
||||
self.source = source = Source(eth_description(8))
|
||||
self.comb += Record.connect(self.sink, self.source)
|
|
@ -1,128 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
from migen.flow.actor import Sink, Source
|
||||
from migen.bank.description import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
|
||||
class MIIPHYTX(Module):
|
||||
def __init__(self, pads):
|
||||
self.sink = sink = Sink(eth_description(8))
|
||||
|
||||
###
|
||||
|
||||
tx_en_r = Signal()
|
||||
tx_data_r = Signal(4)
|
||||
self.sync += [
|
||||
pads.tx_er.eq(0),
|
||||
pads.tx_en.eq(tx_en_r),
|
||||
pads.tx_data.eq(tx_data_r),
|
||||
]
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
fsm.act("IDLE",
|
||||
sink.ack.eq(1),
|
||||
If(sink.stb & sink.sop,
|
||||
sink.ack.eq(0),
|
||||
NextState("SEND_LO")
|
||||
)
|
||||
)
|
||||
fsm.act("SEND_LO",
|
||||
tx_data_r.eq(sink.d[0:4]),
|
||||
tx_en_r.eq(1),
|
||||
NextState("SEND_HI")
|
||||
)
|
||||
fsm.act("SEND_HI",
|
||||
tx_data_r.eq(sink.d[4:8]),
|
||||
tx_en_r.eq(1),
|
||||
sink.ack.eq(1),
|
||||
If(sink.stb & sink.eop,
|
||||
NextState("IDLE")
|
||||
).Else(
|
||||
NextState("SEND_LO")
|
||||
)
|
||||
)
|
||||
|
||||
class MIIPHYRX(Module):
|
||||
def __init__(self, pads):
|
||||
self.source = source = Source(eth_description(8))
|
||||
|
||||
###
|
||||
|
||||
sop = source.sop
|
||||
set_sop = Signal()
|
||||
clr_sop = Signal()
|
||||
self.sync += \
|
||||
If(clr_sop,
|
||||
sop.eq(0)
|
||||
).Elif(set_sop,
|
||||
sop.eq(1)
|
||||
)
|
||||
|
||||
lo = Signal(4)
|
||||
hi = Signal(4)
|
||||
load_nibble = Signal(2)
|
||||
self.sync += \
|
||||
If(load_nibble[0],
|
||||
lo.eq(pads.rx_data)
|
||||
).Elif(load_nibble[1],
|
||||
hi.eq(pads.rx_data)
|
||||
)
|
||||
self.comb += [
|
||||
source.d.eq(Cat(lo, hi))
|
||||
]
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
fsm.act("IDLE",
|
||||
set_sop.eq(1),
|
||||
If(pads.dv,
|
||||
load_nibble.eq(0b01),
|
||||
NextState("LOAD_HI")
|
||||
)
|
||||
)
|
||||
fsm.act("LOAD_LO",
|
||||
source.stb.eq(1),
|
||||
If(pads.dv,
|
||||
clr_sop.eq(1),
|
||||
load_nibble.eq(0b01),
|
||||
NextState("LOAD_HI")
|
||||
).Else(
|
||||
source.eop.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
fsm.act("LOAD_HI",
|
||||
load_nibble.eq(0b10),
|
||||
NextState("LOAD_LO")
|
||||
)
|
||||
|
||||
class MIIPHYCRG(Module, AutoCSR):
|
||||
def __init__(self, clock_pads, pads):
|
||||
self._reset = CSRStorage()
|
||||
|
||||
###
|
||||
|
||||
self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy)
|
||||
|
||||
self.clock_domains.cd_eth_rx = ClockDomain()
|
||||
self.clock_domains.cd_eth_tx = ClockDomain()
|
||||
self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
|
||||
self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx)
|
||||
|
||||
reset = self._reset.storage
|
||||
self.comb += pads.rst_n.eq(~reset)
|
||||
self.specials += [
|
||||
AsyncResetSynchronizer(self.cd_eth_tx, reset),
|
||||
AsyncResetSynchronizer(self.cd_eth_rx, reset),
|
||||
]
|
||||
|
||||
class MIIPHY(Module, AutoCSR):
|
||||
def __init__(self, clock_pads, pads):
|
||||
self.dw = 8
|
||||
self.submodules.crg = MIIPHYCRG(clock_pads, pads)
|
||||
self.submodules.tx = RenameClockDomains(MIIPHYTX(pads), "eth_tx")
|
||||
self.submodules.rx = RenameClockDomains(MIIPHYRX(pads), "eth_rx")
|
||||
self.sink, self.source = self.tx.sink, self.rx.source
|
|
@ -1,145 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
from migen.genlib.misc import chooser
|
||||
from migen.genlib.record import *
|
||||
from migen.flow.actor import Sink, Source
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
|
||||
class PreambleInserter(Module):
|
||||
def __init__(self, d_w):
|
||||
self.sink = Sink(eth_description(d_w))
|
||||
self.source = Source(eth_description(d_w))
|
||||
|
||||
###
|
||||
|
||||
preamble = Signal(64, reset=eth_preamble)
|
||||
cnt_max = (64//d_w)-1
|
||||
cnt = Signal(max=cnt_max+1)
|
||||
clr_cnt = Signal()
|
||||
inc_cnt = Signal()
|
||||
|
||||
self.sync += \
|
||||
If(clr_cnt,
|
||||
cnt.eq(0)
|
||||
).Elif(inc_cnt,
|
||||
cnt.eq(cnt+1)
|
||||
)
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
fsm.act("IDLE",
|
||||
self.sink.ack.eq(1),
|
||||
clr_cnt.eq(1),
|
||||
If(self.sink.stb & self.sink.sop,
|
||||
self.sink.ack.eq(0),
|
||||
NextState("INSERT"),
|
||||
)
|
||||
)
|
||||
fsm.act("INSERT",
|
||||
self.source.stb.eq(1),
|
||||
self.source.sop.eq(cnt==0),
|
||||
chooser(preamble, cnt, self.source.d),
|
||||
If(cnt == cnt_max,
|
||||
If(self.source.ack, NextState("COPY"))
|
||||
).Else(
|
||||
inc_cnt.eq(self.source.ack)
|
||||
)
|
||||
)
|
||||
fsm.act("COPY",
|
||||
Record.connect(self.sink, self.source),
|
||||
self.source.sop.eq(0),
|
||||
|
||||
If(self.sink.stb & self.sink.eop & self.source.ack,
|
||||
NextState("IDLE"),
|
||||
)
|
||||
)
|
||||
|
||||
class PreambleChecker(Module):
|
||||
def __init__(self, d_w):
|
||||
self.sink = Sink(eth_description(d_w))
|
||||
self.source = Source(eth_description(d_w))
|
||||
|
||||
###
|
||||
|
||||
preamble = Signal(64, reset=eth_preamble)
|
||||
cnt_max = (64//d_w) - 1
|
||||
cnt = Signal(max=cnt_max+1)
|
||||
clr_cnt = Signal()
|
||||
inc_cnt = Signal()
|
||||
|
||||
self.sync += \
|
||||
If(clr_cnt,
|
||||
cnt.eq(0)
|
||||
).Elif(inc_cnt,
|
||||
cnt.eq(cnt+1)
|
||||
)
|
||||
|
||||
discard = Signal()
|
||||
clr_discard = Signal()
|
||||
set_discard = Signal()
|
||||
|
||||
self.sync += \
|
||||
If(clr_discard,
|
||||
discard.eq(0)
|
||||
).Elif(set_discard,
|
||||
discard.eq(1)
|
||||
)
|
||||
|
||||
sop = Signal()
|
||||
clr_sop = Signal()
|
||||
set_sop = Signal()
|
||||
self.sync += \
|
||||
If(clr_sop,
|
||||
sop.eq(0)
|
||||
).Elif(set_sop,
|
||||
sop.eq(1)
|
||||
)
|
||||
|
||||
ref = Signal(d_w)
|
||||
match = Signal()
|
||||
self.comb += [
|
||||
chooser(preamble, cnt, ref),
|
||||
match.eq(self.sink.d == ref)
|
||||
]
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("IDLE",
|
||||
self.sink.ack.eq(1),
|
||||
clr_cnt.eq(1),
|
||||
clr_discard.eq(1),
|
||||
If(self.sink.stb & self.sink.sop,
|
||||
clr_cnt.eq(0),
|
||||
inc_cnt.eq(1),
|
||||
clr_discard.eq(0),
|
||||
set_discard.eq(~match),
|
||||
NextState("CHECK"),
|
||||
)
|
||||
)
|
||||
fsm.act("CHECK",
|
||||
self.sink.ack.eq(1),
|
||||
If(self.sink.stb,
|
||||
set_discard.eq(~match),
|
||||
If(cnt == cnt_max,
|
||||
If(discard | (~match),
|
||||
NextState("IDLE")
|
||||
).Else(
|
||||
set_sop.eq(1),
|
||||
NextState("COPY")
|
||||
)
|
||||
).Else(
|
||||
inc_cnt.eq(1)
|
||||
)
|
||||
)
|
||||
)
|
||||
fsm.act("COPY",
|
||||
Record.connect(self.sink, self.source),
|
||||
self.source.sop.eq(sop),
|
||||
clr_sop.eq(self.source.stb & self.source.ack),
|
||||
|
||||
If(self.source.stb & self.source.eop & self.source.ack,
|
||||
NextState("IDLE"),
|
||||
)
|
||||
)
|
|
@ -1,251 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.fifo import SyncFIFO
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
from migen.genlib.misc import chooser
|
||||
from migen.flow.actor import Sink, Source
|
||||
from migen.bank.description import *
|
||||
from migen.bank.eventmanager import *
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
|
||||
class SRAMWriter(Module, AutoCSR):
|
||||
def __init__(self, depth, nslots=2):
|
||||
self.sink = sink = Sink(eth_description(32))
|
||||
self.crc_error = Signal()
|
||||
|
||||
slotbits = max(log2_int(nslots), 1)
|
||||
lengthbits = log2_int(depth*4) # length in bytes
|
||||
|
||||
self._slot = CSRStatus(slotbits)
|
||||
self._length = CSRStatus(lengthbits)
|
||||
|
||||
self.submodules.ev = EventManager()
|
||||
self.ev.available = EventSourceLevel()
|
||||
self.ev.finalize()
|
||||
|
||||
###
|
||||
|
||||
# packet dropped if no slot available
|
||||
sink.ack.reset = 1
|
||||
|
||||
# length computation
|
||||
cnt = Signal(lengthbits)
|
||||
clr_cnt = Signal()
|
||||
inc_cnt = Signal()
|
||||
inc_val = Signal(3)
|
||||
self.comb += \
|
||||
If(sink.last_be[3],
|
||||
inc_val.eq(1)
|
||||
).Elif(sink.last_be[2],
|
||||
inc_val.eq(2)
|
||||
).Elif(sink.last_be[1],
|
||||
inc_val.eq(3)
|
||||
).Else(
|
||||
inc_val.eq(4)
|
||||
)
|
||||
self.sync += \
|
||||
If(clr_cnt,
|
||||
cnt.eq(0)
|
||||
).Elif(inc_cnt,
|
||||
cnt.eq(cnt+inc_val)
|
||||
)
|
||||
|
||||
# slot computation
|
||||
slot = Signal(slotbits)
|
||||
inc_slot = Signal()
|
||||
self.sync += \
|
||||
If(inc_slot,
|
||||
If(slot == nslots-1,
|
||||
slot.eq(0),
|
||||
).Else(
|
||||
slot.eq(slot+1)
|
||||
)
|
||||
)
|
||||
ongoing = Signal()
|
||||
discard = Signal()
|
||||
|
||||
# status fifo
|
||||
fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
|
||||
self.submodules += fifo
|
||||
|
||||
# fsm
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("IDLE",
|
||||
inc_cnt.eq(sink.stb),
|
||||
If(sink.stb & sink.sop,
|
||||
ongoing.eq(1),
|
||||
If(fifo.writable,
|
||||
NextState("WRITE")
|
||||
)
|
||||
)
|
||||
)
|
||||
fsm.act("WRITE",
|
||||
inc_cnt.eq(sink.stb),
|
||||
ongoing.eq(1),
|
||||
If(sink.stb & sink.eop,
|
||||
If((sink.error & sink.last_be) != 0,
|
||||
NextState("DISCARD")
|
||||
).Else(
|
||||
NextState("TERMINATE")
|
||||
)
|
||||
)
|
||||
)
|
||||
fsm.act("DISCARD",
|
||||
clr_cnt.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
fsm.act("TERMINATE",
|
||||
clr_cnt.eq(1),
|
||||
inc_slot.eq(1),
|
||||
fifo.we.eq(1),
|
||||
fifo.din.slot.eq(slot),
|
||||
fifo.din.length.eq(cnt),
|
||||
NextState("IDLE")
|
||||
)
|
||||
|
||||
self.comb += [
|
||||
fifo.re.eq(self.ev.available.clear),
|
||||
self.ev.available.trigger.eq(fifo.readable),
|
||||
self._slot.status.eq(fifo.dout.slot),
|
||||
self._length.status.eq(fifo.dout.length),
|
||||
]
|
||||
|
||||
# memory
|
||||
mems = [None]*nslots
|
||||
ports = [None]*nslots
|
||||
for n in range(nslots):
|
||||
mems[n] = Memory(32, depth)
|
||||
ports[n] = mems[n].get_port(write_capable=True)
|
||||
self.specials += ports[n]
|
||||
self.mems = mems
|
||||
|
||||
cases = {}
|
||||
for n, port in enumerate(ports):
|
||||
cases[n] = [
|
||||
ports[n].adr.eq(cnt[2:]),
|
||||
ports[n].dat_w.eq(sink.d),
|
||||
If(sink.stb & ongoing,
|
||||
ports[n].we.eq(0xf)
|
||||
)
|
||||
]
|
||||
self.comb += Case(slot, cases)
|
||||
|
||||
|
||||
class SRAMReader(Module, AutoCSR):
|
||||
def __init__(self, depth, nslots=2):
|
||||
self.source = source = Source(eth_description(32))
|
||||
|
||||
slotbits = max(log2_int(nslots), 1)
|
||||
lengthbits = log2_int(depth*4) # length in bytes
|
||||
self.lengthbits = lengthbits
|
||||
|
||||
self._start = CSR()
|
||||
self._ready = CSRStatus()
|
||||
self._slot = CSRStorage(slotbits)
|
||||
self._length = CSRStorage(lengthbits)
|
||||
|
||||
self.submodules.ev = EventManager()
|
||||
self.ev.done = EventSourcePulse()
|
||||
self.ev.finalize()
|
||||
|
||||
###
|
||||
|
||||
# command fifo
|
||||
fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
|
||||
self.submodules += fifo
|
||||
self.comb += [
|
||||
fifo.we.eq(self._start.re),
|
||||
fifo.din.slot.eq(self._slot.storage),
|
||||
fifo.din.length.eq(self._length.storage),
|
||||
self._ready.status.eq(fifo.writable)
|
||||
]
|
||||
|
||||
# length computation
|
||||
cnt = Signal(lengthbits)
|
||||
clr_cnt = Signal()
|
||||
inc_cnt = Signal()
|
||||
|
||||
self.sync += \
|
||||
If(clr_cnt,
|
||||
cnt.eq(0)
|
||||
).Elif(inc_cnt,
|
||||
cnt.eq(cnt+4)
|
||||
)
|
||||
|
||||
# fsm
|
||||
first = Signal()
|
||||
last = Signal()
|
||||
last_d = Signal()
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("IDLE",
|
||||
clr_cnt.eq(1),
|
||||
If(fifo.readable,
|
||||
NextState("CHECK")
|
||||
)
|
||||
)
|
||||
fsm.act("CHECK",
|
||||
If(~last_d,
|
||||
NextState("SEND"),
|
||||
).Else(
|
||||
NextState("END"),
|
||||
)
|
||||
)
|
||||
length_lsb = fifo.dout.length[0:2]
|
||||
fsm.act("SEND",
|
||||
source.stb.eq(1),
|
||||
source.sop.eq(first),
|
||||
source.eop.eq(last),
|
||||
If(last,
|
||||
If(length_lsb == 3,
|
||||
source.last_be.eq(0b0010)
|
||||
).Elif(length_lsb == 2,
|
||||
source.last_be.eq(0b0100)
|
||||
).Elif(length_lsb == 1,
|
||||
source.last_be.eq(0b1000)
|
||||
).Else(
|
||||
source.last_be.eq(0b0001)
|
||||
)
|
||||
),
|
||||
If(source.ack,
|
||||
inc_cnt.eq(~last),
|
||||
NextState("CHECK")
|
||||
)
|
||||
)
|
||||
fsm.act("END",
|
||||
fifo.re.eq(1),
|
||||
self.ev.done.trigger.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
|
||||
# first/last computation
|
||||
self.sync += [
|
||||
If(fsm.ongoing("IDLE"),
|
||||
first.eq(1)
|
||||
).Elif(source.stb & source.ack,
|
||||
first.eq(0)
|
||||
)
|
||||
]
|
||||
self.comb += last.eq(cnt + 4 >= fifo.dout.length)
|
||||
self.sync += last_d.eq(last)
|
||||
|
||||
# memory
|
||||
rd_slot = fifo.dout.slot
|
||||
|
||||
mems = [None]*nslots
|
||||
ports = [None]*nslots
|
||||
for n in range(nslots):
|
||||
mems[n] = Memory(32, depth)
|
||||
ports[n] = mems[n].get_port()
|
||||
self.specials += ports[n]
|
||||
self.mems = mems
|
||||
|
||||
cases = {}
|
||||
for n, port in enumerate(ports):
|
||||
self.comb += ports[n].adr.eq(cnt[2:])
|
||||
cases[n] = [source.d.eq(port.dat_r)]
|
||||
self.comb += Case(rd_slot, cases)
|
|
@ -1,120 +0,0 @@
|
|||
import random, copy
|
||||
|
||||
from migen.fhdl.std import *
|
||||
from migen.flow.actor import Sink, Source
|
||||
from migen.genlib.record import *
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
|
||||
def seed_to_data(seed, random=True):
|
||||
if random:
|
||||
return (seed * 0x31415979 + 1) & 0xffffffff
|
||||
else:
|
||||
return seed
|
||||
|
||||
def check(p1, p2):
|
||||
p1 = copy.deepcopy(p1)
|
||||
p2 = copy.deepcopy(p2)
|
||||
if isinstance(p1, int):
|
||||
return 0, 1, int(p1 != p2)
|
||||
else:
|
||||
if len(p1) >= len(p2):
|
||||
ref, res = p1, p2
|
||||
else:
|
||||
ref, res = p2, p1
|
||||
shift = 0
|
||||
while((ref[0] != res[0]) and (len(res)>1)):
|
||||
res.pop(0)
|
||||
shift += 1
|
||||
length = min(len(ref), len(res))
|
||||
errors = 0
|
||||
for i in range(length):
|
||||
if ref.pop(0) != res.pop(0):
|
||||
errors += 1
|
||||
return shift, length, errors
|
||||
|
||||
def randn(max_n):
|
||||
return random.randint(0, max_n-1)
|
||||
|
||||
class Packet(list):
|
||||
def __init__(self, init=[]):
|
||||
self.ongoing = False
|
||||
self.done = False
|
||||
for data in init:
|
||||
self.append(data)
|
||||
|
||||
class PacketStreamer(Module):
|
||||
def __init__(self, description):
|
||||
self.source = Source(description)
|
||||
###
|
||||
self.packets = []
|
||||
self.packet = Packet()
|
||||
self.packet.done = 1
|
||||
|
||||
def send(self, packet):
|
||||
packet = copy.deepcopy(packet)
|
||||
self.packets.append(packet)
|
||||
|
||||
def do_simulation(self, selfp):
|
||||
if len(self.packets) and self.packet.done:
|
||||
self.packet = self.packets.pop(0)
|
||||
if not self.packet.ongoing and not self.packet.done:
|
||||
selfp.source.stb = 1
|
||||
selfp.source.sop = 1
|
||||
selfp.source.d = self.packet.pop(0)
|
||||
self.packet.ongoing = True
|
||||
elif selfp.source.stb == 1 and selfp.source.ack == 1:
|
||||
selfp.source.sop = 0
|
||||
selfp.source.eop = (len(self.packet) == 1)
|
||||
if len(self.packet) > 0:
|
||||
selfp.source.stb = 1
|
||||
selfp.source.d = self.packet.pop(0)
|
||||
else:
|
||||
self.packet.done = 1
|
||||
selfp.source.stb = 0
|
||||
|
||||
class PacketLogger(Module):
|
||||
def __init__(self, description):
|
||||
self.sink = Sink(description)
|
||||
###
|
||||
self.packet = Packet()
|
||||
|
||||
def receive(self):
|
||||
self.packet.done = 0
|
||||
while self.packet.done == 0:
|
||||
yield
|
||||
|
||||
def do_simulation(self, selfp):
|
||||
selfp.sink.ack = 1
|
||||
if selfp.sink.stb == 1 and selfp.sink.sop == 1:
|
||||
self.packet = Packet()
|
||||
self.packet.append(selfp.sink.d)
|
||||
elif selfp.sink.stb:
|
||||
self.packet.append(selfp.sink.d)
|
||||
if selfp.sink.stb == 1 and selfp.sink.eop == 1:
|
||||
self.packet.done = True
|
||||
|
||||
class AckRandomizer(Module):
|
||||
def __init__(self, description, level=0):
|
||||
self.level = level
|
||||
|
||||
self.sink = Sink(description)
|
||||
self.source = Source(description)
|
||||
|
||||
self.run = Signal()
|
||||
|
||||
self.comb += \
|
||||
If(self.run,
|
||||
Record.connect(self.sink, self.source)
|
||||
).Else(
|
||||
self.source.stb.eq(0),
|
||||
self.sink.ack.eq(0),
|
||||
)
|
||||
|
||||
def do_simulation(self, selfp):
|
||||
n = randn(100)
|
||||
if n < self.level:
|
||||
selfp.run = 0
|
||||
else:
|
||||
selfp.run = 1
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.actorlib.crc import *
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
from misoclib.ethmac.test.common import *
|
||||
|
||||
payload = [
|
||||
0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12,
|
||||
0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00,
|
||||
0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11,
|
||||
0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00,
|
||||
0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C,
|
||||
0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||
0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
|
||||
]
|
||||
|
||||
crc = [
|
||||
0x7A, 0xD5, 0x6B, 0xB3
|
||||
]
|
||||
|
||||
mux = {
|
||||
"inserter": 0,
|
||||
"checker": 1,
|
||||
"both": 2
|
||||
}
|
||||
|
||||
class TB(Module):
|
||||
def __init__(self, random_level=50):
|
||||
sm = self.submodules
|
||||
sm.streamer = PacketStreamer(eth_description(8))
|
||||
sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level)
|
||||
sm.logger = PacketLogger(eth_description(8))
|
||||
sm.logger_randomizer = AckRandomizer(eth_description(8), random_level)
|
||||
|
||||
self.comb += [
|
||||
self.streamer.source.connect(self.streamer_randomizer.sink),
|
||||
self.logger_randomizer.source.connect(self.logger.sink)
|
||||
]
|
||||
|
||||
sm.crc32_inserter = CRC32Inserter(eth_description(8))
|
||||
sm.crc32_checker = CRC32Checker(eth_description(8))
|
||||
|
||||
self.mux = Signal(2)
|
||||
self.comb += [
|
||||
If(self.mux == mux["inserter"],
|
||||
self.streamer_randomizer.source.connect(self.crc32_inserter.sink),
|
||||
self.crc32_inserter.source.connect(self.logger_randomizer.sink)
|
||||
).Elif(self.mux == mux["checker"],
|
||||
self.streamer_randomizer.source.connect(self.crc32_checker.sink),
|
||||
self.crc32_checker.source.connect(self.logger_randomizer.sink)
|
||||
).Elif(self.mux == mux["both"],
|
||||
self.streamer_randomizer.source.connect(self.crc32_inserter.sink),
|
||||
self.crc32_inserter.source.connect(self.crc32_checker.sink),
|
||||
self.crc32_checker.source.connect(self.logger_randomizer.sink)
|
||||
)
|
||||
]
|
||||
|
||||
def gen_simulation(self, selfp):
|
||||
selfp.mux = mux["inserter"]
|
||||
print("streamer --> crc32_inserter --> logger:")
|
||||
self.streamer.send(Packet(payload))
|
||||
yield from self.logger.receive()
|
||||
s, l, e = check(payload+crc, self.logger.packet)
|
||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||
|
||||
selfp.mux = mux["checker"]
|
||||
print("streamer --> crc32_checker --> logger:")
|
||||
self.streamer.send(Packet(payload+crc))
|
||||
yield from self.logger.receive()
|
||||
s, l, e = check(payload, self.logger.packet)
|
||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||
|
||||
selfp.mux = mux["both"]
|
||||
print("streamer --> crc32_inserter --> crc32_checker --> logger:")
|
||||
self.streamer.send(Packet(payload))
|
||||
yield from self.logger.receive()
|
||||
s, l, e = check(payload, self.logger.packet)
|
||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
from migen.sim.generic import run_simulation
|
||||
run_simulation(TB(), ncycles=1000, vcd_name="my.vcd")
|
|
@ -1,123 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.bus import wishbone
|
||||
from migen.bus.transactions import *
|
||||
from migen.sim.generic import run_simulation
|
||||
|
||||
from misoclib.ethmac import EthMAC
|
||||
from misoclib.ethmac.phy import loopback
|
||||
|
||||
from misoclib.ethmac.test.common import *
|
||||
|
||||
class WishboneMaster:
|
||||
def __init__(self, obj):
|
||||
self.obj = obj
|
||||
self.dat = 0
|
||||
|
||||
def write(self, adr, dat):
|
||||
self.obj.cyc = 1
|
||||
self.obj.stb = 1
|
||||
self.obj.adr = adr
|
||||
self.obj.we = 1
|
||||
self.obj.sel = 0xF
|
||||
self.obj.dat_w = dat
|
||||
while self.obj.ack == 0:
|
||||
yield
|
||||
self.obj.cyc = 0
|
||||
self.obj.stb = 0
|
||||
yield
|
||||
|
||||
def read(self, adr):
|
||||
self.obj.cyc = 1
|
||||
self.obj.stb = 1
|
||||
self.obj.adr = adr
|
||||
self.obj.we = 0
|
||||
self.obj.sel = 0xF
|
||||
self.obj.dat_w = 0
|
||||
while self.obj.ack == 0:
|
||||
yield
|
||||
self.dat = self.obj.dat_r
|
||||
self.obj.cyc = 0
|
||||
self.obj.stb = 0
|
||||
yield
|
||||
|
||||
class SRAMReaderDriver:
|
||||
def __init__(self, obj):
|
||||
self.obj = obj
|
||||
|
||||
def start(self, slot, length):
|
||||
self.obj._slot.storage = slot
|
||||
self.obj._length.storage = length
|
||||
self.obj._start.re = 1
|
||||
yield
|
||||
self.obj._start.re = 0
|
||||
yield
|
||||
|
||||
def wait_done(self):
|
||||
while self.obj.ev.done.pending == 0:
|
||||
yield
|
||||
|
||||
def clear_done(self):
|
||||
self.obj.ev.done.clear = 1
|
||||
yield
|
||||
self.obj.ev.done.clear = 0
|
||||
yield
|
||||
|
||||
class TB(Module):
|
||||
def __init__(self):
|
||||
self.submodules.ethphy = loopback.LoopbackPHY()
|
||||
self.submodules.ethmac = EthMAC(phy=self.ethphy, with_hw_preamble_crc=True)
|
||||
|
||||
# use sys_clk for each clock_domain
|
||||
self.clock_domains.cd_eth_rx = ClockDomain()
|
||||
self.clock_domains.cd_eth_tx = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_eth_rx.clk.eq(ClockSignal()),
|
||||
self.cd_eth_rx.rst.eq(ResetSignal()),
|
||||
self.cd_eth_tx.clk.eq(ClockSignal()),
|
||||
self.cd_eth_tx.rst.eq(ResetSignal()),
|
||||
]
|
||||
|
||||
def gen_simulation(self, selfp):
|
||||
selfp.cd_eth_rx.rst = 1
|
||||
selfp.cd_eth_tx.rst = 1
|
||||
yield
|
||||
selfp.cd_eth_rx.rst = 0
|
||||
selfp.cd_eth_tx.rst = 0
|
||||
|
||||
wishbone_master = WishboneMaster(selfp.ethmac.bus)
|
||||
sram_reader_driver = SRAMReaderDriver(selfp.ethmac.sram_reader)
|
||||
|
||||
sram_writer_slots_offset = [0x000, 0x200]
|
||||
sram_reader_slots_offset = [0x400, 0x600]
|
||||
|
||||
length = 1500-2
|
||||
|
||||
tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0]
|
||||
|
||||
errors = 0
|
||||
|
||||
for slot in range(2):
|
||||
print("slot {}:".format(slot))
|
||||
# fill tx memory
|
||||
for i in range(length//4+1):
|
||||
dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big")
|
||||
yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat)
|
||||
|
||||
# send tx payload & wait
|
||||
yield from sram_reader_driver.start(slot, length)
|
||||
yield from sram_reader_driver.wait_done()
|
||||
yield from sram_reader_driver.clear_done()
|
||||
|
||||
# get rx payload (loopback on PHY Model)
|
||||
rx_payload = []
|
||||
for i in range(length//4+1):
|
||||
yield from wishbone_master.read(sram_writer_slots_offset[slot]+i)
|
||||
dat = wishbone_master.dat
|
||||
rx_payload += list(dat.to_bytes(4, byteorder='big'))
|
||||
|
||||
# check results
|
||||
s, l, e = check(tx_payload[:length], rx_payload[:min(length, len(rx_payload))])
|
||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_simulation(TB(), vcd_name="my.vcd")
|
|
@ -1,82 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
|
||||
from misoclib.ethmac.common import *
|
||||
from misoclib.ethmac.preamble import *
|
||||
from misoclib.ethmac.test.common import *
|
||||
|
||||
preamble = [
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5
|
||||
]
|
||||
|
||||
payload = [
|
||||
0x00, 0x0A, 0xE6, 0xF0, 0x05, 0xA3, 0x00, 0x12,
|
||||
0x34, 0x56, 0x78, 0x90, 0x08, 0x00, 0x45, 0x00,
|
||||
0x00, 0x30, 0xB3, 0xFE, 0x00, 0x00, 0x80, 0x11,
|
||||
0x72, 0xBA, 0x0A, 0x00, 0x00, 0x03, 0x0A, 0x00,
|
||||
0x00, 0x02, 0x04, 0x00, 0x04, 0x00, 0x00, 0x1C,
|
||||
0x89, 0x4D, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||
0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13
|
||||
]
|
||||
|
||||
mux = {
|
||||
"inserter": 0,
|
||||
"checker": 1,
|
||||
"both": 2
|
||||
}
|
||||
|
||||
class TB(Module):
|
||||
def __init__(self, random_level=50):
|
||||
sm = self.submodules
|
||||
sm.streamer = PacketStreamer(eth_description(8))
|
||||
sm.streamer_randomizer = AckRandomizer(eth_description(8), random_level)
|
||||
sm.logger = PacketLogger(eth_description(8))
|
||||
sm.logger_randomizer = AckRandomizer(eth_description(8), random_level)
|
||||
|
||||
self.comb += [
|
||||
self.streamer.source.connect(self.streamer_randomizer.sink),
|
||||
self.logger_randomizer.source.connect(self.logger.sink)
|
||||
]
|
||||
|
||||
sm.preamble_inserter = PreambleInserter(8)
|
||||
sm.preamble_checker = PreambleChecker(8)
|
||||
|
||||
self.mux = Signal(2)
|
||||
self.comb += [
|
||||
If(self.mux == mux["inserter"],
|
||||
self.streamer_randomizer.source.connect(self.preamble_inserter.sink),
|
||||
self.preamble_inserter.source.connect(self.logger_randomizer.sink)
|
||||
).Elif(self.mux == mux["checker"],
|
||||
self.streamer_randomizer.source.connect(self.preamble_checker.sink),
|
||||
self.preamble_checker.source.connect(self.logger_randomizer.sink)
|
||||
).Elif(self.mux == mux["both"],
|
||||
self.streamer_randomizer.source.connect(self.preamble_inserter.sink),
|
||||
self.preamble_inserter.source.connect(self.preamble_checker.sink),
|
||||
self.preamble_checker.source.connect(self.logger_randomizer.sink)
|
||||
)
|
||||
]
|
||||
def gen_simulation(self, selfp):
|
||||
selfp.mux = mux["inserter"]
|
||||
print("streamer --> preamble_inserter --> logger:")
|
||||
self.streamer.send(Packet(payload))
|
||||
yield from self.logger.receive()
|
||||
s, l, e = check(preamble+payload, self.logger.packet)
|
||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||
|
||||
selfp.mux = mux["checker"]
|
||||
print("streamer --> preamble_checker --> logger:")
|
||||
self.streamer.send(Packet(preamble+payload))
|
||||
yield from self.logger.receive()
|
||||
s, l, e = check(payload, self.logger.packet)
|
||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||
|
||||
selfp.mux = mux["both"]
|
||||
print("streamer --> preamble_inserter --> preamble_checker --> logger:")
|
||||
self.streamer.send(Packet(payload))
|
||||
yield from self.logger.receive()
|
||||
s, l, e = check(payload, self.logger.packet)
|
||||
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
|
||||
|
||||
if __name__ == "__main__":
|
||||
from migen.sim.generic import run_simulation
|
||||
run_simulation(TB(), ncycles=1000, vcd_name="my.vcd")
|
|
@ -1,10 +1,13 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
|
||||
from misoclib import sdram, spiflash, ethmac
|
||||
from misoclib import sdram, spiflash
|
||||
from misoclib.sdram.phy import k7ddrphy
|
||||
from misoclib.gensoc import SDRAMSoC
|
||||
from misoclib.ethmac.phy import gmii
|
||||
|
||||
from extcores import *
|
||||
from liteeth.phy.gmii import LiteEthPHYGMII
|
||||
from liteeth.mac import LiteEthMAC
|
||||
|
||||
class _CRG(Module):
|
||||
def __init__(self, platform):
|
||||
|
@ -121,8 +124,8 @@ class MiniSoC(BaseSoC):
|
|||
def __init__(self, platform, **kwargs):
|
||||
BaseSoC.__init__(self, platform, **kwargs)
|
||||
|
||||
self.submodules.ethphy = gmii.GMIIPHY(platform.request("eth_clocks"), platform.request("eth"))
|
||||
self.submodules.ethmac = ethmac.EthMAC(phy=self.ethphy, with_hw_preamble_crc=True)
|
||||
self.submodules.ethphy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth"))
|
||||
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone")
|
||||
self.add_wb_slave(lambda a: a[26:29] == 3, self.ethmac.bus)
|
||||
self.add_cpu_memory_region("ethmac_mem", 0xb0000000, 0x2000)
|
||||
|
||||
|
|
|
@ -4,10 +4,13 @@ from fractions import Fraction
|
|||
from migen.fhdl.std import *
|
||||
from mibuild.generic_platform import ConstraintError
|
||||
|
||||
from misoclib import sdram, mxcrg, norflash16, ethmac, framebuffer, gpio
|
||||
from misoclib import sdram, mxcrg, norflash16, framebuffer, gpio
|
||||
from misoclib.sdram.phy import s6ddrphy
|
||||
from misoclib.gensoc import SDRAMSoC
|
||||
from misoclib.ethmac.phy import mii
|
||||
|
||||
from extcores import *
|
||||
from liteeth.phy.mii import LiteEthPHYMII
|
||||
from liteeth.mac import LiteEthMAC
|
||||
|
||||
class _MXClockPads:
|
||||
def __init__(self, platform):
|
||||
|
@ -91,8 +94,8 @@ class MiniSoC(BaseSoC):
|
|||
self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2)))
|
||||
self.submodules.leds = gpio.GPIOOut(Cat(platform.request("user_led", i) for i in range(2)))
|
||||
|
||||
self.submodules.ethphy = mii.MIIPHY(platform.request("eth_clocks"), platform.request("eth"))
|
||||
self.submodules.ethmac = ethmac.EthMAC(phy=self.ethphy, with_hw_preamble_crc=False)
|
||||
self.submodules.ethphy = LiteEthPHYMII(platform.request("eth_clocks"), platform.request("eth"))
|
||||
self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone")
|
||||
self.add_wb_slave(lambda a: a[26:29] == 3, self.ethmac.bus)
|
||||
self.add_cpu_memory_region("ethmac_mem", 0xb0000000, 0x2000)
|
||||
|
||||
|
|
Loading…
Reference in a new issue