"target_ip": HField(16, 0, 32)
}
+icmp_header_len = 8
+icmp_header = {
+ "msgtype": HField( 0, 0, 8),
+ "code": HField( 1, 0, 8),
+ "checksum": HField( 2, 0, 16),
+ "quench": HField( 4, 0, 32)
+}
+icmp_protocol = 0x01
+
udp_header_len = 8
udp_header = {
"src_port": HField( 0, 0, 16),
udp_protocol = 0x11
-icmp_header_len = 8
-icmp_header = {
- "msgtype": HField( 0, 0, 8),
- "code": HField( 1, 0, 8),
- "checksum": HField( 2, 0, 16),
- "quench": HField( 4, 0, 32)
-}
-icmp_protocol = 0x01
+etherbone_magic = 0x4e6f
+etherbone_version = 1
+etherbone_header_len = 8
+etherbone_header = [
+ "magic": HField( 0, 0, 16),
+ "portsize": HField( 2, 0, 4),
+ "addrsize": HField( 2, 4, 4),
+ "pf": HField( 3, 0, 1),
+ "version": HField( 4, 0, 4),
+
+ "wff": HField( 5, 1, 1),
+ "wca": HField( 5, 2, 1),
+ "cyc": HField( 5, 3, 1),
+ "rff": HField( 5, 5, 1),
+ "rca": HField( 5, 6, 1),
+ "bca": HField( 5, 7, 1),
+
+ "rcount": HField( 6, 0, 8),
+
+ "wcount": HField( 7, 0, 8)
+]
def reverse_bytes(v):
n = math.ceil(flen(v)/8)
ip += int(e)
return ip
+def eth_icmp_description(dw):
+ layout = _layout_from_header(icmp_header) + [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(layout, packetized=True)
+
+def eth_icmp_user_description(dw):
+ layout = _layout_from_header(icmp_header) + [
+ ("ip_address", 32),
+ ("length", 16),
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(layout, packetized=True)
+
def eth_udp_description(dw):
layout = _layout_from_header(udp_header) + [
("data", dw),
]
return EndpointDescription(layout, packetized=True)
-def eth_icmp_description(dw):
- layout = _layout_from_header(icmp_header) + [
+def eth_etherbone_description(dw):
+ layout = _layout_from_header(etherbone_header) + [
("data", dw),
("error", dw//8)
]
return EndpointDescription(layout, packetized=True)
-def eth_icmp_user_description(dw):
- layout = _layout_from_header(icmp_header) + [
- ("ip_address", 32),
+def eth_etherbone_description(dw):
+ layout = _layout_from_header(etherbone_header) + [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(layout, packetized=True)
+
+def eth_etherbone_user_description(dw):
+ layout = [
("length", 16),
+ ("ip_address", 32),
+ ("wcount", 8),
+ ("rcount", 8),
("data", dw),
("error", dw//8)
]
return EndpointDescription(layout, packetized=True)
+
# Generic modules
@DecorateModule(InsertReset)
@DecorateModule(InsertCE)
--- /dev/null
+from liteeth.common import *
+from liteeth.generic.depacketizer import LiteEthDepacketizer
+from liteeth.generic.packetizer import LiteEthPacketizer
+
+class LiteEthEtherboneDepacketizer(LiteEthDepacketizer):
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_udp_user_description(8),
+ eth_etherbone_description(8),
+ etherbone_header,
+ etherbone_header_len)
+
+class LiteEthEtherbonePacketizer(LiteEthPacketizer):
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_etherbone_description(8),
+ eth_udp_user_description(8),
+ etherbone_header,
+ etherbone_header_len)
+
+class LiteEthEtherboneTX(Module):
+ def __init__(self, udp_port):
+ self.sink = sink = Sink(eth_etherbone_user_description(8))
+ self.source = source = Source(eth_udp_user_description(8))
+ ###
+ self.submodules.packetizer = packetizer = LiteEthUDPPacketizer()
+ self.comb += [
+ packetizer.sink.stb.eq(sink.stb),
+ packetizer.sink.sop.eq(sink.sop),
+ packetizer.sink.eop.eq(sink.eop),
+ sink.ack.eq(packetizer.sink.ack),
+
+ packetizer.sink.magic.eq(etherbone_magic),
+ packetizer.sink.portsize.eq(32), # XXX
+ packetizer.sink.addrsize.eq(32), # XXX
+ packetizer.sink.pf.eq(0), # XXX
+ packetizer.sink.version.eq(etherbone_version),
+
+ packetizer.sink.wff.eq(0), # XXX
+ packetizer.sink.wca.eq(0), # XXX
+ packetizer.sink.cyc.eq(0), # XXX
+ packetizer.sink.rff.eq(0), # XXX
+ packetizer.sink.rca.eq(0), # XXX
+ packetizer.sink.bca.eq(0), # XXX
+
+ packetizer.sink.rcount.eq(sink.rcount),
+ packetier.sink.wconut.eq(sink.wcount),
+
+ packetizer.sink.data.eq(sink.data)
+ ]
+
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ packetizer.source.ack.eq(1),
+ If(packetizer.source.stb & packetizer.source.sop,
+ packetizer.source.ack.eq(0),
+ NextState("SEND")
+ )
+ )
+ self.comb += [
+ source.src_port.eq(0x1234), # XXX,
+ source.dst_port.eq(udp_port),
+ source.ip_address.eq(sink.ip_address),
+ source.length.eq(sink.length + eth_etherbone_header_len)
+ ]
+ fsm.act("SEND",
+ Record.connect(packetizer.source, source),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
+
+class LiteEthEtherboneRX(Module):
+ def __init__(self):
+ self.sink = sink = Sink(eth_udp_user_description(8))
+ self.source = source = Source(eth_etherbone_user_description(8))
+ ###
+ self.submodules.depacketizer = depacketizer = LiteEtherboneDepacketizer()
+ self.comb += Record.connect(sink, depacketizer.sink)
+
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ depacketizer.source.ack.eq(1),
+ If(depacketizer.source.stb & depacketizer.source.sop,
+ depacketizer.source.ack.eq(0),
+ NextState("CHECK")
+ )
+ )
+ valid = Signal()
+ self.sync += valid.eq(
+ depacketizer.source.stb &
+ (depacketizer.source.magic == etherbone_magic) &
+ (depacketizer.source.version == etherbone_version)
+ )
+
+ fsm.act("CHECK",
+ If(valid,
+ NextState("PRESENT")
+ ).Else(
+ NextState("DROP")
+ )
+ )
+ self.comb += [
+ source.sop.eq(depacketizer.source.sop),
+ source.eop.eq(depacketizer.source.eop),
+ source.rcount.eq(depacketizer.source.rcount),
+ source.wcount.eq(depacketizer.source.wcount),
+ source.data.eq(depacketizer.source.data),
+ source.error.eq(depacketizer.source.error)
+ ]
+ fsm.act("PRESENT",
+ source.stb.eq(depacketizer.source.stb),
+ depacketizer.source.ack.eq(source.ack),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
+ fsm.act("DROP",
+ depacketizer.source.ack.eq(1),
+ If(depacketizer.source.stb & depacketizer.source.eop & depacketizer.source.ack,
+ NextState("IDLE")
+ )
+ )
+
+class LiteEthEtherboneWishboneMaster(Module):
+ def __init__(self):
+ self.sink = sink = Sink(eth_etherbone_user_description(8))
+ self.source = source = Source(eth_etherbone_description(8))
+ self.bus = bus = wishbone.Interface()
+ ###
+
+ self.submodules.base_addr = base_addr = FlipFlop(32)
+ self.comb += self.base_addr.d.eq(self.sink.data)
+ self.submodules.counter = counter = Counter(32)
+
+ self.submodules.fifo = fifo = SyncFIFO([("data", 32)], 256)
+
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ counter.reset.eq(1),
+ If(sink.stb & sink.sop,
+ If(sink.wcount > 0,
+ self.base_addr.ce.eq(1),
+ NextState("WRITE_DATA")
+ ).Elif(sink.rcount > 0,
+ self.base_addr.ce.eq(1),
+ NextState("READ_DATA")
+ )
+ )
+ )
+ fsm.act("WRITE_DATA",
+ bus.adr.eq(base_addr + self.counter.value),
+ bus.dat_w.eq(sink.data),
+ bus.sel.eq(0xf), # XXX?
+ bus.stb.eq(sink.stb),
+ bus.we.eq(1),
+ bus.cyc.eq(1),
+ If(bus.stb & bus.ack,
+ sink.ack.eq(1),
+ counter.ce.eq(1),
+ If(counter.value == sink.wcount-1,
+ If(sink.rcount > 0,
+ counter.reset.eq(1)
+ NextState("READ_DATA")
+ ).Else(
+ NextState("TERMINATE")
+ )
+ )
+ )
+ )
+ fsm.act("CHECK_READ",
+ If(sink.rcount > 0,
+ If(sink.stb,
+ sink.ack.eq(1),
+ base_addr.ce.eq(1),
+ NextState("READ_DATA")
+ )
+ ).Else(
+ NextState("IDLE")
+ )
+ )
+ fsm.act("READ_DATA",
+ bus.adr.eq(self.sink.data),
+ bus.sel.eq(0xf),
+ bus.stb.eq(1),
+ bus.we.eq(0),
+ bus.cyc.eq(1),
+ If(bus.stb & bus.ack,
+ sink.ack.eq(1),
+ counter.ce.eq(1),
+ fifo.sink.stb.eq(1),
+ fifo.sink.sop.eq(counter == 0),
+ fifo.sink.data.eq(bus.dat_r),
+ If(counter.value == sink.rcount-1,
+ fifo.sink.eop.eq(1),
+ NextState("PRESENT_DATA")
+ )
+ )
+ )
+ fsm.act("PRESENT_DATA",
+ source.stb.eq(fifo.stb),
+ source.sop.eq(fifo.sop),
+ source.eop.eq(fifo.eop),
+ fifo.ack.eq(source.ack),
+ source.length.eq(sink.rcount+1),
+ source.wcount.eq(sink.rcount),
+ source.rcount.eq(0),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
+
+class LiteEthEtherbone(Module):
+ def __init__(self, udp, udp_port):
+ self.submodules.tx = tx = LiteEthEtherboneTX(udp_port)
+ self.submodules.rx = rx = LiteEthEtherboneRX()
+ udp_port = udp.crossbar.get_port(udp_port)
+ self.comb += [
+ Record.connect(tx.source, udp_port.sink),
+ Record.connect(udp_port.source, rx.sink)
+ ]
+ self.master = master = LiteEthEtherboneWishboneMaster()
+ self.comb += [
+ Record.connect(rx.source.connect(master.sink)),
+ Record.connect(master.source.connect(tx.sink))
+ ]
+++ /dev/null
-# This file is Copyright (c) 2014 Robert Jordens <jordens@gmail.com>
-# License: BSD
-
-import struct
-from collections import namedtuple
-
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.record import Record
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.fifo import SyncFIFO
-from migen.genlib.misc import optree
-from migen.actorlib.structuring import Cast, Pack, Unpack, pack_layout
-from migen.actorlib.sim import SimActor
-from migen.bus.transactions import TRead, TWrite
-from migen.flow.transactions import Token
-from migen.flow.actor import Source, Sink
-from migen.flow.network import DataFlowGraph, CompositeActor
-
-
-_eb_width = 32 # addr and data
-_eb_queue_len = 32
-_eb_magic = 0x4e6f
-_eb_ver = 1
-_eb_hdr = [
- ("magic", 16),
- ("ver", 4),
- ("res1", 1),
- ("no_response", 1),
- ("probe_res", 1),
- ("probe", 1),
- ("addr_size", 4),
- ("data_size", 4),
- ][::-1] # big-endian
-
-_eb_rec_hdr = [
- ("bca_cfg", 1),
- ("rca_cfg", 1),
- ("rd_fifo", 1),
- ("res1", 1),
- ("drop_cyc", 1),
- ("wca_cfg", 1),
- ("wr_fifo", 1),
- ("res2", 1),
- ("sel", 8),
- ("wr_cnt", 8),
- ("rd_cnt", 8),
- ][::-1] # big-endian
-
-_eb_layout = [("data", _eb_width)]
-
-
-class Config(Module):
- def __init__(self, sdb_addr):
- self.errreg = Signal(8*8)
- mach = Signal(4*8, reset=0xd15e)
- macl = Signal(4*8, reset=0xa5edbeef)
- self.mac = Signal(6*8)
- self.comb += self.mac.eq(Cat(macl, mach))
- self.ip = Signal(4*8, reset=0xc0a80064)
- self.port = Signal(4*8, reset=0xebd0)
-
- self.bus = bus = wishbone.Interface()
- self.submodules.fifo = SyncFIFO(3, _eb_queue_len)
-
- read_mux = Array([self.errreg[32:], self.errreg[:32], 0,
- sdb_addr, mach, macl, self.ip, self.port])
- write_mux = Array([mach, macl, self.ip, self.port])[bus.adr - 4]
-
- self.dout = read_mux[self.fifo.dout]
- self.comb += [
- bus.ack.eq(bus.cyc & bus.stb),
- bus.dat_r.eq(read_mux[bus.adr[:3]]),
- ]
- self.sync += [
- If(bus.cyc & bus.stb & bus.we & optree("|",
- [bus.adr[:3] == i for i in (4, 5, 6, 7)]),
- write_mux.eq(bus.dat_w),
- )]
-
-class WishboneMaster(Module):
- def __init__(self, timeout):
- self.bus = bus = wishbone.Interface()
- self.submodules.fifo = SyncFIFO(_eb_width + 1, _eb_queue_len)
-
- self.active = Signal()
- inflight = Signal(max=_eb_queue_len)
- queued = Signal(max=_eb_queue_len)
- self.sync += [
- inflight.eq(inflight + self.active - self.fifo.we),
- queued.eq(queued + self.active - self.fifo.re),
- ]
-
- self.busy = Signal()
- self.full = Signal()
- self.comb += [
- self.busy.eq(inflight != 0),
- self.full.eq(queued == _eb_queue_len - 1),
- ]
-
- kill_ack = Signal()
- time = Signal(max=timeout)
- self.comb += kill_ack.eq(time == timeout - 1)
- self.sync += [
- If(self.fifo.we | ~self.busy,
- time.eq(0),
- ).Else(
- time.eq(time + 1),
- )]
-
- self.comb += [
- self.fifo.we.eq(bus.ack | bus.err | kill_ack),
- self.fifo.din.eq(Cat(bus.dat_r, ~bus.ack)),
- ]
-
- self.errreg = Signal(64)
- self.sync += [
- If(self.fifo.re,
- self.errreg.eq(Cat(self.fifo.dout[-1], self.errreg)),
- )]
-
-class Transmit(Module):
- def __init__(self, pas, cfg, wbm, tag, tags):
- self.tx = Source(_eb_layout)
-
- data = Signal(_eb_width)
- re = Signal(4)
- self.tx_cyc = Signal()
- self.tx_skip = Signal()
- last_tx_cyc = Signal()
- last_tx_skip = Signal()
- readable = Signal()
-
- self.sync += [
- last_tx_cyc.eq(self.tx_cyc),
- last_tx_skip.eq(self.tx_skip),
- ]
-
- self.comb += [
- readable.eq(Cat(tag.readable, pas.readable,
- cfg.fifo.readable, wbm.readable) & re == re),
- self.tx.stb.eq(readable & (re[1:] != 0)),
- self.tx.payload.data.eq(data),
- Case(tag.dout, {
- tags["PASS_TX"]: [re.eq(0b0011), data.eq(pas.dout)],
- tags["PASS_ON"]: [re.eq(0b0011), data.eq(pas.dout)],
- tags["CFG_REQ"]: [re.eq(0b0101), data.eq(cfg.dout)],
- tags["CFG_IGN"]: [re.eq(0b0111), data.eq(pas.dout)],
- tags["WBM_REQ"]: [re.eq(0b1001), data.eq(wbm.dout)],
- tags["WBM_IGN"]: [re.eq(0b1011), data.eq(pas.dout)],
- "default": [re.eq(0b0001)],
- }),
- If(readable & (self.tx.ack | (re[1:] == 0)),
- Cat(tag.re, pas.re, cfg.fifo.re, wbm.re).eq(re),
- ),
- If(tag.readable,
- If(tag.dout == tags["PASS_TX"],
- self.tx_cyc.eq(1),
- self.tx_skip.eq(0),
- ).Elif(tag.dout == tags["SKIP_TX"],
- self.tx_cyc.eq(0),
- self.tx_skip.eq(1),
- ).Elif(tag.dout == tags["DROP_TX"],
- self.tx_cyc.eq(0),
- self.tx_skip.eq(0),
- ).Else(
- self.tx_cyc.eq(last_tx_cyc),
- self.tx_skip.eq(last_tx_skip),
- ),
- ).Else(
- self.tx_cyc.eq(last_tx_cyc),
- self.tx_skip.eq(last_tx_skip),
- ),
- ]
-
-class Receive(Module):
- def __init__(self, pas, cfg, wbm, tag, tags):
- self.rx = Sink(_eb_layout)
-
- rx_rec_hdr = Record(_eb_rec_hdr)
- tx_rec_hdr = Record(_eb_rec_hdr)
- rx_eb_hdr = Record(_eb_hdr)
- tx_eb_hdr = Record(_eb_hdr)
- self.comb += [
- rx_eb_hdr.raw_bits().eq(self.rx.payload.data),
- tx_eb_hdr.magic.eq(rx_eb_hdr.magic),
- tx_eb_hdr.ver.eq(_eb_ver),
- tx_eb_hdr.no_response.eq(1),
- tx_eb_hdr.addr_size.eq(4),
- tx_eb_hdr.data_size.eq(4),
- tx_eb_hdr.probe_res.eq(rx_eb_hdr.probe),
-
- rx_rec_hdr.raw_bits().eq(self.rx.payload.data),
- tx_rec_hdr.wca_cfg.eq(rx_rec_hdr.bca_cfg),
- tx_rec_hdr.wr_fifo.eq(rx_rec_hdr.rd_fifo),
- tx_rec_hdr.wr_cnt.eq(rx_rec_hdr.rd_cnt),
- tx_rec_hdr.sel.eq(rx_rec_hdr.sel),
- tx_rec_hdr.drop_cyc.eq(rx_rec_hdr.drop_cyc),
- ]
-
- do_rx = Signal()
- self.rx_cyc = Signal()
- self.comb += [
- wbm.bus.sel.eq(rx_rec_hdr.sel),
- do_rx.eq(tag.writable & # tag is always written/read
- self.rx_cyc & self.rx.stb & # have data
- (wbm.fifo.we | ~wbm.bus.stb) & # stb finished or idle
- (wbm.bus.cyc | ~wbm.busy)), # in-cycle or idle
- self.rx.ack.eq(do_rx),
- cfg.fifo.din.eq(wbm.bus.adr),
- # no eb-cfg write support yet
- #cfg.dat_w.eq(wbm.bus.dat_w),
- #cfg.we.eq(wbm.bus.we),
- cfg.errreg.eq(wbm.errreg),
- ]
-
- cur_rx_rec_hdr = Record(_eb_rec_hdr)
- cur_tx_rec_hdr = Record(_eb_rec_hdr)
- do_rec = Signal()
- do_adr = Signal()
- do_write = Signal()
- do_read = Signal()
- wr_adr = Signal(flen(wbm.bus.adr))
- old_rx_cyc = Signal()
- self.sync += [
- wbm.bus.stb.eq(wbm.bus.stb & ~wbm.fifo.we),
- wbm.bus.cyc.eq(wbm.bus.cyc & (
- ~cur_rx_rec_hdr.drop_cyc |
- (cur_rx_rec_hdr.wr_cnt > 0) |
- (cur_rx_rec_hdr.rd_cnt > 0))),
- If(do_rec,
- cur_rx_rec_hdr.eq(rx_rec_hdr),
- cur_tx_rec_hdr.eq(tx_rec_hdr),
- ),
- If(do_adr,
- wr_adr.eq(self.rx.payload.data[2:]),
- ),
- If(do_write,
- If(cur_rx_rec_hdr.wca_cfg,
- cfg.fifo.we.eq(1),
- ).Else(
- wbm.bus.cyc.eq(1),
- wbm.bus.stb.eq(1),
- ),
- wbm.bus.we.eq(1),
- wbm.bus.adr.eq(wr_adr),
- wbm.bus.dat_w.eq(self.rx.payload.data),
- If(~cur_rx_rec_hdr.wr_fifo,
- wr_adr.eq(wr_adr + 1),
- ),
- cur_rx_rec_hdr.wr_cnt.eq(cur_rx_rec_hdr.wr_cnt - 1),
- ),
- If(do_read,
- If(cur_rx_rec_hdr.rca_cfg,
- cfg.fifo.we.eq(1),
- ).Else(
- wbm.bus.cyc.eq(1),
- wbm.bus.stb.eq(1),
- ),
- wbm.bus.we.eq(0),
- wbm.bus.adr.eq(self.rx.payload.data[2:]),
- cur_rx_rec_hdr.rd_cnt.eq(cur_rx_rec_hdr.rd_cnt - 1),
- ),
- If(~self.rx_cyc,
- wbm.bus.cyc.eq(0),
- ),
- old_rx_cyc.eq(self.rx_cyc),
- ]
-
- fsm = self.submodules.fsm = FSM()
- fsm.reset_state = "EB_HDR"
- fsm.act("EB_HDR",
- If(do_rx,
- tag.we.eq(1),
- If((rx_eb_hdr.magic != _eb_magic) |
- (rx_eb_hdr.ver !=_eb_ver),
- tag.din.eq(tags["SKIP_TX"]),
- NextState("DROP"),
- ).Else(
- If(rx_eb_hdr.no_response,
- tag.din.eq(tags["SKIP_TX"]),
- ).Else(
- tag.din.eq(tags["PASS_TX"]),
- pas.we.eq(1),
- pas.din.eq(tx_eb_hdr.raw_bits()),
- ),
- If(rx_eb_hdr.probe,
- If(rx_eb_hdr.addr_size[2] &
- rx_eb_hdr.data_size[2],
- NextState("PROBE_ID"),
- ).Else(
- NextState("PROBE_DROP"),
- ),
- ).Else(
- If((rx_eb_hdr.addr_size == 4) &
- (rx_eb_hdr.data_size == 4),
- NextState("CYC_HDR"),
- ).Else(
- NextState("DROP"),
- ),
- ),
- ),
- ))
- fsm.act("PROBE_DROP",
- If(do_rx,
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- pas.din.eq(self.rx.payload.data),
- NextState("DROP"),
- ))
- fsm.act("PROBE_ID",
- If(do_rx,
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- pas.din.eq(self.rx.payload.data),
- NextState("CYC_HDR"),
- ))
- fsm.act("CYC_HDR",
- If(do_rx,
- do_rec.eq(1),
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- If(rx_rec_hdr.wr_cnt != 0,
- NextState("WR_ADR"),
- ).Else(
- pas.din.eq(tx_rec_hdr.raw_bits()),
- If(rx_rec_hdr.rd_cnt != 0,
- NextState("RD_ADR"),
- ).Else(
- NextState("CYC_HDR"),
- ),
- ),
- ))
- fsm.act("WR_ADR",
- If(do_rx,
- do_adr.eq(1),
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- NextState("WRITE"),
- ))
- fsm.act("WRITE",
- If(do_rx,
- do_write.eq(1),
- tag.we.eq(1),
- If(cur_rx_rec_hdr.wca_cfg,
- tag.din.eq(tags["CFG_IGN"]),
- ).Else(
- wbm.active.eq(1),
- tag.din.eq(tags["WBM_IGN"]),
- ),
- pas.we.eq(1),
- If(cur_rx_rec_hdr.wr_cnt == 1,
- pas.din.eq(cur_tx_rec_hdr.raw_bits()),
- If(cur_rx_rec_hdr.rd_cnt != 0,
- NextState("RD_ADR"),
- ).Else(
- NextState("CYC_HDR"),
- ),
- ),
- ))
- fsm.act("RD_ADR",
- If(do_rx,
- tag.we.eq(1),
- tag.din.eq(tags["PASS_ON"]),
- pas.we.eq(1),
- pas.din.eq(self.rx.payload.data),
- NextState("READ"),
- ))
- fsm.act("READ",
- If(do_rx,
- do_read.eq(1),
- tag.we.eq(1),
- If(cur_rx_rec_hdr.rca_cfg,
- tag.din.eq(tags["CFG_REQ"]),
- ).Else(
- wbm.active.eq(1),
- tag.din.eq(tags["WBM_REQ"]),
- ),
- If(cur_rx_rec_hdr.rd_cnt == 1,
- NextState("CYC_HDR"),
- ),
- ))
- fsm.act("DROP",
- #If(do_rx,
- # tag.we.eq(1),
- # tag.din.eq(tags["PASS_ON"]),
- # pas.we.eq(1),
- #)
- )
- for state in fsm.actions:
- fsm.act(state, If(~self.rx_cyc, NextState("EB_HDR")))
- self.comb += [
- If(~self.rx_cyc,
- Cat(do_rec, do_adr, do_write, do_read).eq(0),
- Cat(wbm.active, pas.we).eq(0),
- If(old_rx_cyc,
- tag.we.eq(1),
- tag.din.eq(tags["DROP_TX"]),
- ),
- )]
-
-class Slave(Module):
- def __init__(self, sdb_addr, timeout):
- tags = dict((k, i) for i, k in enumerate(
- "DROP_TX SKIP_TX PASS_TX PASS_ON CFG_REQ "
- "CFG_IGN WBM_REQ WBM_IGN".split()))
- tag_width = flen(Signal(max=len(tags)))
-
- self.submodules.pas = SyncFIFO(_eb_width, _eb_queue_len)
- self.submodules.cfg = Config(sdb_addr)
- self.submodules.wbm = WishboneMaster(timeout)
- self.submodules.tag = SyncFIFO(tag_width, _eb_queue_len)
-
- self.submodules.rxfsm = Receive(self.pas, self.cfg,
- self.wbm, self.tag, tags)
- self.rx = self.rxfsm.rx
- self.rx_cyc = self.rxfsm.rx_cyc
- self.submodules.txmux = Transmit(self.pas, self.cfg,
- self.wbm.fifo, self.tag, tags)
- self.tx = self.txmux.tx
- self.tx_skip = self.txmux.tx_skip
- self.tx_cyc = self.txmux.tx_cyc
- self.busy = self.wbm.busy
-
-class Converter(Module):
- def __init__(self, raw_width, graph, **slave_kwargs):
- raw_layout = [("data", raw_width)]
- pack_factor = _eb_width//raw_width
-
- self.rx = Sink(raw_layout)
- rx_pack = Pack(raw_layout, pack_factor)
- rx_cast = Cast(pack_layout(raw_layout, pack_factor), _eb_layout)
- self.submodules.slave = Slave(**slave_kwargs)
- tx_cast = Cast(_eb_layout, pack_layout(raw_layout, pack_factor))
- tx_unpack = Unpack(pack_factor, raw_layout)
- self.tx = Source(raw_layout)
-
- graph.add_connection(self.rx, rx_pack)
- graph.add_connection(rx_pack, rx_cast)
- graph.add_connection(rx_cast, self.slave.rx)
- graph.add_connection(self.slave.tx, tx_cast)
- graph.add_connection(tx_cast, tx_unpack)
- graph.add_connection(tx_unpack, self.tx)
-
-class SimTx(SimActor):
- def __init__(self, data):
- self.tx = Source(_eb_layout)
- SimActor.__init__(self, self.gen(data))
-
- def gen(self, data):
- for i in data:
- yield Token("tx", {"data": i})
- print("eb tx", hex(i))
-
-class SimRx(SimActor):
- def __init__(self):
- self.rx = Sink(_eb_layout)
- self.recv = []
- SimActor.__init__(self, self.gen())
-
- def gen(self):
- while True:
- t = Token("rx")
- yield t
- print("eb rx", hex(t.value["data"]))
- self.recv.append(t.value["data"])
-
-class TB(Module):
- def __init__(self, data):
- ebm_tx = SimTx(data)
- ebm_rx = SimRx()
- self.slave = Slave(0x200, 10)
- g = DataFlowGraph()
- g.add_connection(ebm_tx, self.slave)
- g.add_connection(self.slave, ebm_rx)
- self.submodules.graph = CompositeActor(g)
- self.submodules.cfg_master = wishbone.Initiator(self.gen_cfg_reads())
- self.submodules.cfg_tap = wishbone.Tap(self.slave.cfg.bus,
- lambda l: print("cfg", l))
- self.submodules.wbm_tap = wishbone.Tap(self.slave.wbm.bus,
- lambda l: print("wbm", l))
- self.submodules.xbar = wishbone.Crossbar(
- [self.cfg_master.bus, self.slave.wbm.bus],
- [
- (lambda a: a[6:] == 0x0, wishbone.Target(
- wishbone.TargetModel()).bus),
- (lambda a: a[6:] == 0x1, self.slave.cfg.bus),
- ])
-
- def gen_cfg_reads(self):
- for a in range(0x40, 0x40+4):
- t = TRead(a)
- yield t
-
- def do_simulation(self, s):
- #s.interrupt = self.cfg_master.done
- s.wr(self.slave.rx_cyc, int(s.cycle_counter < 200))
-
-class MyStruct(object):
- _data = None
- _fmt = "!"
-
- def __init__(self, **kwargs):
- self.data = self._data(**kwargs)
-
- def __bytes__(self):
- return struct.pack(self._fmt, *self.data)
-
-class EbHeader(MyStruct):
- _data = namedtuple("eb_hdr", "magic ver size")
- _fmt = "!HBB"
-
- def __init__(self, probe_id=None, addr_size=4, data_size=4, records=[]):
- no_response = not any(r.read for r in records)
- probe = probe_id is not None
- probe_res = False
- MyStruct.__init__(self, magic=_eb_magic, ver=(_eb_ver<<4) |
- (no_response<<2) | (probe_res<<1) | (probe<<0),
- size=(addr_size<<4) | (data_size<<0))
- self.probe = struct.pack("!I", probe_id) if probe else b""
- self.records = records
-
- def __bytes__(self):
- return (MyStruct.__bytes__(self) + self.probe +
- b"".join(map(bytes, self.records)))
-
-class EbRecord(MyStruct):
- _data = namedtuple("eb_rec", "flags sel wr_cnt rd_cnt")
- _fmt = "!BBBB"
-
- def __init__(self, sel=0xf, wr_adr=0, rd_adr=0, write=[], read=[],
- bca_cfg=False, rca_cfg=False, rd_fifo=False, drop_cyc=False,
- wca_cfg=False, wr_fifo=False):
- MyStruct.__init__(self, sel=sel, wr_cnt=len(write),
- rd_cnt=len(read), flags=(bca_cfg<<7) | (rca_cfg<<6) |
- (rd_fifo<<5) | (drop_cyc<<3) | (wca_cfg<<2) |
- (wr_fifo>>1))
- self.wr_adr = wr_adr
- self.write = write
- self.rd_adr = rd_adr
- self.read = read
-
- def __bytes__(self):
- b = MyStruct.__bytes__(self)
- if self.write:
- b += struct.pack("!I" + "I"*len(self.write), self.wr_adr,
- *self.write)
- if self.read:
- b += struct.pack("!I" + "I"*len(self.read), self.rd_adr,
- *self.read)
- return b
-
-def main():
- from migen.sim.generic import Simulator, TopLevel
-
- #from migen.fhdl import verilog
- #s = Slave(0, 10)
- #print(verilog.convert(s, ios={s.rx.payload.data, s.tx.payload.data,
- # s.rx.stb, s.rx.ack, s.tx.stb, s.tx.ack}))
-
- eb_pkt = EbHeader(records=[
- EbRecord(wr_adr=0x10, write=[0x20, 0x21],
- rd_adr=0x30, read=range(0, 8, 4)),
- EbRecord(rd_adr=0x40, read=range(0x100, 0x100+32, 4),
- drop_cyc=True),
- EbRecord(rca_cfg=True, bca_cfg=True, rd_adr=0x50,
- read=range(0, 0+8, 4), drop_cyc=True),
- ])
- eb_pkt = bytes(eb_pkt)
- eb_pkt = struct.unpack("!" + "I"*(len(eb_pkt)//4), eb_pkt)
- tb = TB(eb_pkt)
- sim = Simulator(tb, TopLevel("etherbone.vcd"))
- sim.run(500)
-
-
-if __name__ == "__main__":
- main()
\ No newline at end of file