add LiteX external core and remove ethmac

This commit is contained in:
Florent Kermarrec 2015-02-16 10:26:43 +01:00 committed by Sebastien Bourdeauducq
parent 9ebb8f8022
commit 0a38b8c74a
18 changed files with 22 additions and 1213 deletions

3
.gitmodules vendored
View file

@ -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
View 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

@ -0,0 +1 @@
Subproject commit dddb984ecd08953e38eb96aff8daff23da96efd2

View file

@ -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")

View file

@ -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)

View file

@ -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)
]

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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"),
)
)

View file

@ -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)

View file

@ -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

View file

@ -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")

View file

@ -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")

View file

@ -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")

View file

@ -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)

View file

@ -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)