buffer_depth = 2**log2_int(eth_mtu, need_pow2=False)
class HField():
- def __init__(self, byte, offset, width):
- self.byte = byte
- self.offset = offset
- self.width = width
+ def __init__(self, byte, offset, width):
+ self.byte = byte
+ self.offset = offset
+ self.width = width
ethernet_type_ip = 0x800
ethernet_type_arp = 0x806
mac_header_len = 14
mac_header = {
- "target_mac": HField(0, 0, 48),
- "sender_mac": HField(6, 0, 48),
- "ethernet_type": HField(12, 0, 16)
+ "target_mac": HField(0, 0, 48),
+ "sender_mac": HField(6, 0, 48),
+ "ethernet_type": HField(12, 0, 16)
}
arp_hwtype_ethernet = 0x0001
arp_header_len = 28
arp_header = {
- "hwtype": HField( 0, 0, 16),
- "proto": HField( 2, 0, 16),
- "hwsize": HField( 4, 0, 8),
- "protosize": HField( 5, 0, 8),
- "opcode": HField( 6, 0, 16),
- "sender_mac": HField( 8, 0, 48),
- "sender_ip": HField(14, 0, 32),
- "target_mac": HField(18, 0, 48),
- "target_ip": HField(24, 0, 32)
+ "hwtype": HField( 0, 0, 16),
+ "proto": HField( 2, 0, 16),
+ "hwsize": HField( 4, 0, 8),
+ "protosize": HField( 5, 0, 8),
+ "opcode": HField( 6, 0, 16),
+ "sender_mac": HField( 8, 0, 48),
+ "sender_ip": HField(14, 0, 32),
+ "target_mac": HField(18, 0, 48),
+ "target_ip": HField(24, 0, 32)
}
ipv4_header_len = 20
ipv4_header = {
- "ihl": HField(0, 0, 4),
- "version": HField(0, 4, 4),
- "total_length": HField(2, 0, 16),
- "identification": HField(4, 0, 16),
- "ttl": HField(8, 0, 8),
- "protocol": HField(9, 0, 8),
- "checksum": HField(10, 0, 16),
- "sender_ip": HField(12, 0, 32),
- "target_ip": HField(16, 0, 32)
+ "ihl": HField(0, 0, 4),
+ "version": HField(0, 4, 4),
+ "total_length": HField(2, 0, 16),
+ "identification": HField(4, 0, 16),
+ "ttl": HField(8, 0, 8),
+ "protocol": HField(9, 0, 8),
+ "checksum": HField(10, 0, 16),
+ "sender_ip": HField(12, 0, 32),
+ "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)
+ "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),
- "dst_port": HField( 2, 0, 16),
- "length": HField( 4, 0, 16),
- "checksum": HField( 6, 0, 16)
+ "src_port": HField( 0, 0, 16),
+ "dst_port": HField( 2, 0, 16),
+ "length": HField( 4, 0, 16),
+ "checksum": HField( 6, 0, 16)
}
udp_protocol = 0x11
etherbone_version = 1
etherbone_packet_header_len = 8
etherbone_packet_header = {
- "magic": HField( 0, 0, 16),
+ "magic": HField( 0, 0, 16),
- "version": HField( 2, 4, 4),
- "nr": HField( 2, 2, 1),
- "pr": HField( 2, 1, 1),
- "pf": HField( 2, 0, 1),
+ "version": HField( 2, 4, 4),
+ "nr": HField( 2, 2, 1),
+ "pr": HField( 2, 1, 1),
+ "pf": HField( 2, 0, 1),
- "addr_size": HField( 3, 4, 4),
- "port_size": HField( 3, 0, 4)
+ "addr_size": HField( 3, 4, 4),
+ "port_size": HField( 3, 0, 4)
}
etherbone_record_header_len = 4
etherbone_record_header = {
- "bca": HField( 0, 0, 1),
- "rca": HField( 0, 1, 1),
- "rff": HField( 0, 2, 1),
- "cyc": HField( 0, 4, 1),
- "wca": HField( 0, 5, 1),
- "wff": HField( 0, 6, 1),
+ "bca": HField( 0, 0, 1),
+ "rca": HField( 0, 1, 1),
+ "rff": HField( 0, 2, 1),
+ "cyc": HField( 0, 4, 1),
+ "wca": HField( 0, 5, 1),
+ "wff": HField( 0, 6, 1),
- "byte_enable": HField( 1, 0, 8),
+ "byte_enable": HField( 1, 0, 8),
- "wcount": HField( 2, 0, 8),
+ "wcount": HField( 2, 0, 8),
- "rcount": HField( 3, 0, 8)
+ "rcount": HField( 3, 0, 8)
}
def reverse_bytes(v):
- n = math.ceil(flen(v)/8)
- r = []
- for i in reversed(range(n)):
- r.append(v[i*8:min((i+1)*8, flen(v))])
- return Cat(iter(r))
+ n = math.ceil(flen(v)/8)
+ r = []
+ for i in reversed(range(n)):
+ r.append(v[i*8:min((i+1)*8, flen(v))])
+ return Cat(iter(r))
# layouts
def _layout_from_header(header):
- _layout = []
- for k, v in sorted(header.items()):
- _layout.append((k, v.width))
- return _layout
+ _layout = []
+ for k, v in sorted(header.items()):
+ _layout.append((k, v.width))
+ return _layout
def _remove_from_layout(layout, *args):
- r = []
- for f in layout:
- remove = False
- for arg in args:
- if f[0] == arg:
- remove = True
- if not remove:
- r.append(f)
- return r
+ r = []
+ for f in layout:
+ remove = False
+ for arg in args:
+ if f[0] == arg:
+ remove = True
+ if not remove:
+ r.append(f)
+ return r
def eth_phy_description(dw):
- payload_layout = [
- ("data", dw),
- ("last_be", dw//8),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, packetized=True)
+ payload_layout = [
+ ("data", dw),
+ ("last_be", dw//8),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, packetized=True)
def eth_mac_description(dw):
- payload_layout = _layout_from_header(mac_header) + [
- ("data", dw),
- ("last_be", dw//8),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, packetized=True)
+ payload_layout = _layout_from_header(mac_header) + [
+ ("data", dw),
+ ("last_be", dw//8),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, packetized=True)
def eth_arp_description(dw):
- param_layout = _layout_from_header(arp_header)
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(arp_header)
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
arp_table_request_layout = [
- ("ip_address", 32)
+ ("ip_address", 32)
]
arp_table_response_layout = [
- ("failed", 1),
- ("mac_address", 48)
+ ("failed", 1),
+ ("mac_address", 48)
]
def eth_ipv4_description(dw):
- param_layout = _layout_from_header(ipv4_header)
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(ipv4_header)
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_ipv4_user_description(dw):
- param_layout = [
- ("length", 16),
- ("protocol", 8),
- ("ip_address", 32)
- ]
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = [
+ ("length", 16),
+ ("protocol", 8),
+ ("ip_address", 32)
+ ]
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def convert_ip(s):
- ip = 0
- for e in s.split("."):
- ip = ip << 8
- ip += int(e)
- return ip
+ ip = 0
+ for e in s.split("."):
+ ip = ip << 8
+ ip += int(e)
+ return ip
def eth_icmp_description(dw):
- param_layout = _layout_from_header(icmp_header)
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(icmp_header)
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_icmp_user_description(dw):
- param_layout = _layout_from_header(icmp_header) + [
- ("ip_address", 32),
- ("length", 16)
- ]
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(icmp_header) + [
+ ("ip_address", 32),
+ ("length", 16)
+ ]
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_udp_description(dw):
- param_layout = _layout_from_header(udp_header)
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(udp_header)
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_udp_user_description(dw):
- param_layout = [
- ("src_port", 16),
- ("dst_port", 16),
- ("ip_address", 32),
- ("length", 16)
- ]
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = [
+ ("src_port", 16),
+ ("dst_port", 16),
+ ("ip_address", 32),
+ ("length", 16)
+ ]
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_etherbone_packet_description(dw):
- param_layout = _layout_from_header(etherbone_packet_header)
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(etherbone_packet_header)
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_etherbone_packet_user_description(dw):
- param_layout = _layout_from_header(etherbone_packet_header)
- param_layout = _remove_from_layout(param_layout, "magic", "portsize", "addrsize", "version")
- param_layout += eth_udp_user_description(dw).param_layout
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(etherbone_packet_header)
+ param_layout = _remove_from_layout(param_layout, "magic", "portsize", "addrsize", "version")
+ param_layout += eth_udp_user_description(dw).param_layout
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_etherbone_record_description(dw):
- param_layout = _layout_from_header(etherbone_record_header)
- payload_layout = [
- ("data", dw),
- ("error", dw//8)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = _layout_from_header(etherbone_record_header)
+ payload_layout = [
+ ("data", dw),
+ ("error", dw//8)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_etherbone_mmap_description(dw):
- param_layout = [
- ("we", 1),
- ("count", 8),
- ("base_addr", 32),
- ("be", dw//8)
- ]
- payload_layout = [
- ("addr", 32),
- ("data", dw)
- ]
- return EndpointDescription(payload_layout, param_layout, packetized=True)
+ param_layout = [
+ ("we", 1),
+ ("count", 8),
+ ("base_addr", 32),
+ ("be", dw//8)
+ ]
+ payload_layout = [
+ ("addr", 32),
+ ("data", dw)
+ ]
+ return EndpointDescription(payload_layout, param_layout, packetized=True)
def eth_tty_description(dw):
- payload_layout = [("data", dw)]
- return EndpointDescription(payload_layout, packetized=False)
+ payload_layout = [("data", dw)]
+ return EndpointDescription(payload_layout, packetized=False)
from misoclib.com.liteeth.core.icmp import LiteEthICMP
class LiteEthIPCore(Module, AutoCSR):
- def __init__(self, phy, mac_address, ip_address, clk_freq):
- self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
- self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq)
- self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table)
- self.submodules.icmp = LiteEthICMP(self.ip, ip_address)
+ def __init__(self, phy, mac_address, ip_address, clk_freq):
+ self.submodules.mac = LiteEthMAC(phy, 8, interface="crossbar", with_hw_preamble_crc=True)
+ self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, clk_freq)
+ self.submodules.ip = LiteEthIP(self.mac, mac_address, ip_address, self.arp.table)
+ self.submodules.icmp = LiteEthICMP(self.ip, ip_address)
class LiteEthUDPIPCore(LiteEthIPCore):
- def __init__(self, phy, mac_address, ip_address, clk_freq):
- LiteEthIPCore.__init__(self, phy, mac_address, ip_address, clk_freq)
- self.submodules.udp = LiteEthUDP(self.ip, ip_address)
+ def __init__(self, phy, mac_address, ip_address, clk_freq):
+ LiteEthIPCore.__init__(self, phy, mac_address, ip_address, clk_freq)
+ self.submodules.udp = LiteEthUDP(self.ip, ip_address)
from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer
_arp_table_layout = [
- ("reply", 1),
- ("request", 1),
- ("ip_address", 32),
- ("mac_address", 48)
- ]
+ ("reply", 1),
+ ("request", 1),
+ ("ip_address", 32),
+ ("mac_address", 48)
+ ]
class LiteEthARPPacketizer(LiteEthPacketizer):
- def __init__(self):
- LiteEthPacketizer.__init__(self,
- eth_arp_description(8),
- eth_mac_description(8),
- arp_header,
- arp_header_len)
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_arp_description(8),
+ eth_mac_description(8),
+ arp_header,
+ arp_header_len)
class LiteEthARPTX(Module):
- def __init__(self, mac_address, ip_address):
- self.sink = sink = Sink(_arp_table_layout)
- self.source = source = Source(eth_mac_description(8))
- ###
- self.submodules.packetizer = packetizer = LiteEthARPPacketizer()
+ def __init__(self, mac_address, ip_address):
+ self.sink = sink = Sink(_arp_table_layout)
+ self.source = source = Source(eth_mac_description(8))
+ ###
+ self.submodules.packetizer = packetizer = LiteEthARPPacketizer()
- counter = Counter(max=max(arp_header_len, eth_min_len))
- self.submodules += counter
+ counter = Counter(max=max(arp_header_len, eth_min_len))
+ self.submodules += counter
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- sink.ack.eq(1),
- counter.reset.eq(1),
- If(sink.stb,
- sink.ack.eq(0),
- NextState("SEND")
- )
- )
- self.comb += [
- packetizer.sink.sop.eq(counter.value == 0),
- packetizer.sink.eop.eq(counter.value == max(arp_header_len, eth_min_len)-1),
- packetizer.sink.hwtype.eq(arp_hwtype_ethernet),
- packetizer.sink.proto.eq(arp_proto_ip),
- packetizer.sink.hwsize.eq(6),
- packetizer.sink.protosize.eq(4),
- packetizer.sink.sender_mac.eq(mac_address),
- packetizer.sink.sender_ip.eq(ip_address),
- If(sink.reply,
- packetizer.sink.opcode.eq(arp_opcode_reply),
- packetizer.sink.target_mac.eq(sink.mac_address),
- packetizer.sink.target_ip.eq(sink.ip_address)
- ).Elif(sink.request,
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ counter.reset.eq(1),
+ If(sink.stb,
+ sink.ack.eq(0),
+ NextState("SEND")
+ )
+ )
+ self.comb += [
+ packetizer.sink.sop.eq(counter.value == 0),
+ packetizer.sink.eop.eq(counter.value == max(arp_header_len, eth_min_len)-1),
+ packetizer.sink.hwtype.eq(arp_hwtype_ethernet),
+ packetizer.sink.proto.eq(arp_proto_ip),
+ packetizer.sink.hwsize.eq(6),
+ packetizer.sink.protosize.eq(4),
+ packetizer.sink.sender_mac.eq(mac_address),
+ packetizer.sink.sender_ip.eq(ip_address),
+ If(sink.reply,
+ packetizer.sink.opcode.eq(arp_opcode_reply),
+ packetizer.sink.target_mac.eq(sink.mac_address),
+ packetizer.sink.target_ip.eq(sink.ip_address)
+ ).Elif(sink.request,
- packetizer.sink.opcode.eq(arp_opcode_request),
- packetizer.sink.target_mac.eq(0xffffffffffff),
- packetizer.sink.target_ip.eq(sink.ip_address)
- )
- ]
- fsm.act("SEND",
- packetizer.sink.stb.eq(1),
- Record.connect(packetizer.source, source),
- source.target_mac.eq(packetizer.sink.target_mac),
- source.sender_mac.eq(mac_address),
- source.ethernet_type.eq(ethernet_type_arp),
- If(source.stb & source.ack,
- counter.ce.eq(1),
- If(source.eop,
- sink.ack.eq(1),
- NextState("IDLE")
- )
- )
- )
+ packetizer.sink.opcode.eq(arp_opcode_request),
+ packetizer.sink.target_mac.eq(0xffffffffffff),
+ packetizer.sink.target_ip.eq(sink.ip_address)
+ )
+ ]
+ fsm.act("SEND",
+ packetizer.sink.stb.eq(1),
+ Record.connect(packetizer.source, source),
+ source.target_mac.eq(packetizer.sink.target_mac),
+ source.sender_mac.eq(mac_address),
+ source.ethernet_type.eq(ethernet_type_arp),
+ If(source.stb & source.ack,
+ counter.ce.eq(1),
+ If(source.eop,
+ sink.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+ )
class LiteEthARPDepacketizer(LiteEthDepacketizer):
- def __init__(self):
- LiteEthDepacketizer.__init__(self,
- eth_mac_description(8),
- eth_arp_description(8),
- arp_header,
- arp_header_len)
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_mac_description(8),
+ eth_arp_description(8),
+ arp_header,
+ arp_header_len)
class LiteEthARPRX(Module):
- def __init__(self, mac_address, ip_address):
- self.sink = sink = Sink(eth_mac_description(8))
- self.source = source = Source(_arp_table_layout)
- ###
- self.submodules.depacketizer = depacketizer = LiteEthARPDepacketizer()
- self.comb += Record.connect(sink, depacketizer.sink)
+ def __init__(self, mac_address, ip_address):
+ self.sink = sink = Sink(eth_mac_description(8))
+ self.source = source = Source(_arp_table_layout)
+ ###
+ self.submodules.depacketizer = depacketizer = LiteEthARPDepacketizer()
+ 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.hwtype == arp_hwtype_ethernet) &
- (depacketizer.source.proto == arp_proto_ip) &
- (depacketizer.source.hwsize == 6) &
- (depacketizer.source.protosize == 4) &
- (depacketizer.source.target_ip == ip_address)
- )
- reply = Signal()
- request = Signal()
- self.comb += Case(depacketizer.source.opcode, {
- arp_opcode_request : [request.eq(1)],
- arp_opcode_reply : [reply.eq(1)],
- "default" : []
- })
- self.comb += [
- source.ip_address.eq(depacketizer.source.sender_ip),
- source.mac_address.eq(depacketizer.source.sender_mac)
- ]
- fsm.act("CHECK",
- If(valid,
- source.stb.eq(1),
- source.reply.eq(reply),
- source.request.eq(request)
- ),
- NextState("TERMINATE")
- ),
- fsm.act("TERMINATE",
- depacketizer.source.ack.eq(1),
- If(depacketizer.source.stb & depacketizer.source.eop,
- NextState("IDLE")
- )
- )
+ 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.hwtype == arp_hwtype_ethernet) &
+ (depacketizer.source.proto == arp_proto_ip) &
+ (depacketizer.source.hwsize == 6) &
+ (depacketizer.source.protosize == 4) &
+ (depacketizer.source.target_ip == ip_address)
+ )
+ reply = Signal()
+ request = Signal()
+ self.comb += Case(depacketizer.source.opcode, {
+ arp_opcode_request : [request.eq(1)],
+ arp_opcode_reply : [reply.eq(1)],
+ "default" : []
+ })
+ self.comb += [
+ source.ip_address.eq(depacketizer.source.sender_ip),
+ source.mac_address.eq(depacketizer.source.sender_mac)
+ ]
+ fsm.act("CHECK",
+ If(valid,
+ source.stb.eq(1),
+ source.reply.eq(reply),
+ source.request.eq(request)
+ ),
+ NextState("TERMINATE")
+ ),
+ fsm.act("TERMINATE",
+ depacketizer.source.ack.eq(1),
+ If(depacketizer.source.stb & depacketizer.source.eop,
+ NextState("IDLE")
+ )
+ )
class LiteEthARPTable(Module):
- def __init__(self, clk_freq, max_requests=8):
- self.sink = sink = Sink(_arp_table_layout) # from arp_rx
- self.source = source = Source(_arp_table_layout) # to arp_tx
+ def __init__(self, clk_freq, max_requests=8):
+ self.sink = sink = Sink(_arp_table_layout) # from arp_rx
+ self.source = source = Source(_arp_table_layout) # to arp_tx
- # Request/Response interface
- self.request = request = Sink(arp_table_request_layout)
- self.response = response = Source(arp_table_response_layout)
- ###
- request_timeout = Timeout(clk_freq//10)
- request_counter = Counter(max=max_requests)
- request_pending = FlipFlop()
- request_ip_address = FlipFlop(32)
- self.submodules += request_timeout, request_counter, request_pending, request_ip_address
- self.comb += [
- request_timeout.ce.eq(request_pending.q),
- request_pending.d.eq(1),
- request_ip_address.d.eq(request.ip_address)
- ]
+ # Request/Response interface
+ self.request = request = Sink(arp_table_request_layout)
+ self.response = response = Source(arp_table_response_layout)
+ ###
+ request_timeout = Timeout(clk_freq//10)
+ request_counter = Counter(max=max_requests)
+ request_pending = FlipFlop()
+ request_ip_address = FlipFlop(32)
+ self.submodules += request_timeout, request_counter, request_pending, request_ip_address
+ self.comb += [
+ request_timeout.ce.eq(request_pending.q),
+ request_pending.d.eq(1),
+ request_ip_address.d.eq(request.ip_address)
+ ]
- # Note: Store only 1 IP/MAC couple, can be improved with a real
- # table in the future to improve performance when packets are
- # targeting multiple destinations.
- update = Signal()
- cached_valid = Signal()
- cached_ip_address = Signal(32)
- cached_mac_address = Signal(48)
- cached_timeout = Timeout(clk_freq*10)
- self.submodules += cached_timeout
+ # Note: Store only 1 IP/MAC couple, can be improved with a real
+ # table in the future to improve performance when packets are
+ # targeting multiple destinations.
+ update = Signal()
+ cached_valid = Signal()
+ cached_ip_address = Signal(32)
+ cached_mac_address = Signal(48)
+ cached_timeout = Timeout(clk_freq*10)
+ self.submodules += cached_timeout
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- # Note: for simplicicy, if APR table is busy response from arp_rx
- # is lost. This is compensated by the protocol (retries)
- If(sink.stb & sink.request,
- NextState("SEND_REPLY")
- ).Elif(sink.stb & sink.reply & request_pending.q,
- NextState("UPDATE_TABLE"),
- ).Elif(request_counter.value == max_requests-1,
- NextState("PRESENT_RESPONSE")
- ).Elif(request.stb | (request_pending.q & request_timeout.reached),
- NextState("CHECK_TABLE")
- )
- )
- fsm.act("SEND_REPLY",
- source.stb.eq(1),
- source.reply.eq(1),
- source.ip_address.eq(sink.ip_address),
- If(source.ack,
- NextState("IDLE")
- )
- )
- fsm.act("UPDATE_TABLE",
- request_pending.reset.eq(1),
- update.eq(1),
- NextState("CHECK_TABLE")
- )
- self.sync += [
- If(update,
- cached_valid.eq(1),
- cached_ip_address.eq(sink.ip_address),
- cached_mac_address.eq(sink.mac_address),
- cached_timeout.reset.eq(1)
- ).Else(
- cached_timeout.ce.eq(1),
- If(cached_timeout.reached,
- cached_valid.eq(0)
- )
- )
- ]
- found = Signal()
- fsm.act("CHECK_TABLE",
- If(cached_valid,
- If(request_ip_address.q == cached_ip_address,
- request_ip_address.reset.eq(1),
- NextState("PRESENT_RESPONSE"),
- ).Elif(request.ip_address == cached_ip_address,
- request.ack.eq(request.stb),
- NextState("PRESENT_RESPONSE"),
- ).Else(
- request_ip_address.ce.eq(request.stb),
- NextState("SEND_REQUEST")
- )
- ).Else(
- request_ip_address.ce.eq(request.stb),
- NextState("SEND_REQUEST")
- )
- )
- fsm.act("SEND_REQUEST",
- source.stb.eq(1),
- source.request.eq(1),
- source.ip_address.eq(request_ip_address.q),
- If(source.ack,
- request_timeout.reset.eq(1),
- request_counter.reset.eq(request.stb),
- request_counter.ce.eq(1),
- request_pending.ce.eq(1),
- request.ack.eq(1),
- NextState("IDLE")
- )
- )
- self.comb += [
- If(request_counter == max_requests-1,
- response.failed.eq(1),
- request_counter.reset.eq(1),
- request_pending.reset.eq(1)
- ),
- response.mac_address.eq(cached_mac_address)
- ]
- fsm.act("PRESENT_RESPONSE",
- response.stb.eq(1),
- If(response.ack,
- NextState("IDLE")
- )
- )
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ # Note: for simplicicy, if APR table is busy response from arp_rx
+ # is lost. This is compensated by the protocol (retries)
+ If(sink.stb & sink.request,
+ NextState("SEND_REPLY")
+ ).Elif(sink.stb & sink.reply & request_pending.q,
+ NextState("UPDATE_TABLE"),
+ ).Elif(request_counter.value == max_requests-1,
+ NextState("PRESENT_RESPONSE")
+ ).Elif(request.stb | (request_pending.q & request_timeout.reached),
+ NextState("CHECK_TABLE")
+ )
+ )
+ fsm.act("SEND_REPLY",
+ source.stb.eq(1),
+ source.reply.eq(1),
+ source.ip_address.eq(sink.ip_address),
+ If(source.ack,
+ NextState("IDLE")
+ )
+ )
+ fsm.act("UPDATE_TABLE",
+ request_pending.reset.eq(1),
+ update.eq(1),
+ NextState("CHECK_TABLE")
+ )
+ self.sync += [
+ If(update,
+ cached_valid.eq(1),
+ cached_ip_address.eq(sink.ip_address),
+ cached_mac_address.eq(sink.mac_address),
+ cached_timeout.reset.eq(1)
+ ).Else(
+ cached_timeout.ce.eq(1),
+ If(cached_timeout.reached,
+ cached_valid.eq(0)
+ )
+ )
+ ]
+ found = Signal()
+ fsm.act("CHECK_TABLE",
+ If(cached_valid,
+ If(request_ip_address.q == cached_ip_address,
+ request_ip_address.reset.eq(1),
+ NextState("PRESENT_RESPONSE"),
+ ).Elif(request.ip_address == cached_ip_address,
+ request.ack.eq(request.stb),
+ NextState("PRESENT_RESPONSE"),
+ ).Else(
+ request_ip_address.ce.eq(request.stb),
+ NextState("SEND_REQUEST")
+ )
+ ).Else(
+ request_ip_address.ce.eq(request.stb),
+ NextState("SEND_REQUEST")
+ )
+ )
+ fsm.act("SEND_REQUEST",
+ source.stb.eq(1),
+ source.request.eq(1),
+ source.ip_address.eq(request_ip_address.q),
+ If(source.ack,
+ request_timeout.reset.eq(1),
+ request_counter.reset.eq(request.stb),
+ request_counter.ce.eq(1),
+ request_pending.ce.eq(1),
+ request.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+ self.comb += [
+ If(request_counter == max_requests-1,
+ response.failed.eq(1),
+ request_counter.reset.eq(1),
+ request_pending.reset.eq(1)
+ ),
+ response.mac_address.eq(cached_mac_address)
+ ]
+ fsm.act("PRESENT_RESPONSE",
+ response.stb.eq(1),
+ If(response.ack,
+ NextState("IDLE")
+ )
+ )
class LiteEthARP(Module):
- def __init__(self, mac, mac_address, ip_address, clk_freq):
- self.submodules.tx = tx = LiteEthARPTX(mac_address, ip_address)
- self.submodules.rx = rx = LiteEthARPRX(mac_address, ip_address)
- self.submodules.table = table = LiteEthARPTable(clk_freq)
- self.comb += [
- Record.connect(rx.source, table.sink),
- Record.connect(table.source, tx.sink)
- ]
- mac_port = mac.crossbar.get_port(ethernet_type_arp)
- self.comb += [
- Record.connect(tx.source, mac_port.sink),
- Record.connect(mac_port.source, rx.sink)
- ]
+ def __init__(self, mac, mac_address, ip_address, clk_freq):
+ self.submodules.tx = tx = LiteEthARPTX(mac_address, ip_address)
+ self.submodules.rx = rx = LiteEthARPRX(mac_address, ip_address)
+ self.submodules.table = table = LiteEthARPTable(clk_freq)
+ self.comb += [
+ Record.connect(rx.source, table.sink),
+ Record.connect(table.source, tx.sink)
+ ]
+ mac_port = mac.crossbar.get_port(ethernet_type_arp)
+ self.comb += [
+ Record.connect(tx.source, mac_port.sink),
+ Record.connect(mac_port.source, rx.sink)
+ ]
from misoclib.com.liteeth.core.etherbone.wishbone import *
class LiteEthEtherbone(Module):
- def __init__(self, udp, udp_port):
- # decode/encode etherbone packets
- self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port)
+ def __init__(self, udp, udp_port):
+ # decode/encode etherbone packets
+ self.submodules.packet = packet = LiteEthEtherbonePacket(udp, udp_port)
- # packets can be probe (etherbone discovering) or records with
- # writes and reads
- self.submodules.probe = probe = LiteEthEtherboneProbe()
- self.submodules.record = record = LiteEthEtherboneRecord()
+ # packets can be probe (etherbone discovering) or records with
+ # writes and reads
+ self.submodules.probe = probe = LiteEthEtherboneProbe()
+ self.submodules.record = record = LiteEthEtherboneRecord()
- # arbitrate/dispatch probe/records packets
- dispatcher = Dispatcher(packet.source, [probe.sink, record.sink])
- self.comb += dispatcher.sel.eq(~packet.source.pf)
- arbiter = Arbiter([probe.source, record.source], packet.sink)
- self.submodules += dispatcher, arbiter
+ # arbitrate/dispatch probe/records packets
+ dispatcher = Dispatcher(packet.source, [probe.sink, record.sink])
+ self.comb += dispatcher.sel.eq(~packet.source.pf)
+ arbiter = Arbiter([probe.source, record.source], packet.sink)
+ self.submodules += dispatcher, arbiter
- # create mmap ŵishbone master
- self.submodules.master = master = LiteEthEtherboneWishboneMaster()
- self.comb += [
- Record.connect(record.receiver.source, master.sink),
- Record.connect(master.source, record.sender.sink)
- ]
+ # create mmap ŵishbone master
+ self.submodules.master = master = LiteEthEtherboneWishboneMaster()
+ self.comb += [
+ Record.connect(record.receiver.source, master.sink),
+ Record.connect(master.source, record.sender.sink)
+ ]
from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer
class LiteEthEtherbonePacketPacketizer(LiteEthPacketizer):
- def __init__(self):
- LiteEthPacketizer.__init__(self,
- eth_etherbone_packet_description(32),
- eth_udp_user_description(32),
- etherbone_packet_header,
- etherbone_packet_header_len)
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_etherbone_packet_description(32),
+ eth_udp_user_description(32),
+ etherbone_packet_header,
+ etherbone_packet_header_len)
class LiteEthEtherbonePacketTX(Module):
- def __init__(self, udp_port):
- self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
- self.source = source = Source(eth_udp_user_description(32))
- ###
- self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer()
- 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),
+ def __init__(self, udp_port):
+ self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
+ self.source = source = Source(eth_udp_user_description(32))
+ ###
+ self.submodules.packetizer = packetizer = LiteEthEtherbonePacketPacketizer()
+ 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.port_size.eq(32//8),
- packetizer.sink.addr_size.eq(32//8),
- packetizer.sink.pf.eq(sink.pf),
- packetizer.sink.pr.eq(sink.pr),
- packetizer.sink.nr.eq(sink.nr),
- packetizer.sink.version.eq(etherbone_version),
+ packetizer.sink.magic.eq(etherbone_magic),
+ packetizer.sink.port_size.eq(32//8),
+ packetizer.sink.addr_size.eq(32//8),
+ packetizer.sink.pf.eq(sink.pf),
+ packetizer.sink.pr.eq(sink.pr),
+ packetizer.sink.nr.eq(sink.nr),
+ packetizer.sink.version.eq(etherbone_version),
- 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")
- )
- )
- fsm.act("SEND",
- Record.connect(packetizer.source, source),
- source.src_port.eq(udp_port),
- source.dst_port.eq(udp_port),
- source.ip_address.eq(sink.ip_address),
- source.length.eq(sink.length + etherbone_packet_header_len),
- If(source.stb & source.eop & source.ack,
- NextState("IDLE")
- )
- )
+ 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")
+ )
+ )
+ fsm.act("SEND",
+ Record.connect(packetizer.source, source),
+ source.src_port.eq(udp_port),
+ source.dst_port.eq(udp_port),
+ source.ip_address.eq(sink.ip_address),
+ source.length.eq(sink.length + etherbone_packet_header_len),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
class LiteEthEtherbonePacketDepacketizer(LiteEthDepacketizer):
- def __init__(self):
- LiteEthDepacketizer.__init__(self,
- eth_udp_user_description(32),
- eth_etherbone_packet_description(32),
- etherbone_packet_header,
- etherbone_packet_header_len)
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_udp_user_description(32),
+ eth_etherbone_packet_description(32),
+ etherbone_packet_header,
+ etherbone_packet_header_len)
class LiteEthEtherbonePacketRX(Module):
- def __init__(self):
- self.sink = sink = Sink(eth_udp_user_description(32))
- self.source = source = Source(eth_etherbone_packet_user_description(32))
- ###
- self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer()
- self.comb += Record.connect(sink, depacketizer.sink)
+ def __init__(self):
+ self.sink = sink = Sink(eth_udp_user_description(32))
+ self.source = source = Source(eth_etherbone_packet_user_description(32))
+ ###
+ self.submodules.depacketizer = depacketizer = LiteEthEtherbonePacketDepacketizer()
+ 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)
- )
- fsm.act("CHECK",
- If(valid,
- NextState("PRESENT")
- ).Else(
- NextState("DROP")
- )
- )
- self.comb += [
- source.sop.eq(depacketizer.source.sop),
- source.eop.eq(depacketizer.source.eop),
+ 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)
+ )
+ 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.pf.eq(depacketizer.source.pf),
- source.pr.eq(depacketizer.source.pr),
- source.nr.eq(depacketizer.source.nr),
+ source.pf.eq(depacketizer.source.pf),
+ source.pr.eq(depacketizer.source.pr),
+ source.nr.eq(depacketizer.source.nr),
- source.data.eq(depacketizer.source.data),
+ source.data.eq(depacketizer.source.data),
- source.src_port.eq(sink.src_port),
- source.dst_port.eq(sink.dst_port),
- source.ip_address.eq(sink.ip_address),
- source.length.eq(sink.length - etherbone_packet_header_len)
- ]
- 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")
- )
- )
+ source.src_port.eq(sink.src_port),
+ source.dst_port.eq(sink.dst_port),
+ source.ip_address.eq(sink.ip_address),
+ source.length.eq(sink.length - etherbone_packet_header_len)
+ ]
+ 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 LiteEthEtherbonePacket(Module):
- def __init__(self, udp, udp_port):
- self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port)
- self.submodules.rx = rx = LiteEthEtherbonePacketRX()
- udp_port = udp.crossbar.get_port(udp_port, dw=32)
- self.comb += [
- Record.connect(tx.source, udp_port.sink),
- Record.connect(udp_port.source, rx.sink)
- ]
- self.sink, self.source = self.tx.sink, self.rx.source
+ def __init__(self, udp, udp_port):
+ self.submodules.tx = tx = LiteEthEtherbonePacketTX(udp_port)
+ self.submodules.rx = rx = LiteEthEtherbonePacketRX()
+ udp_port = udp.crossbar.get_port(udp_port, dw=32)
+ self.comb += [
+ Record.connect(tx.source, udp_port.sink),
+ Record.connect(udp_port.source, rx.sink)
+ ]
+ self.sink, self.source = self.tx.sink, self.rx.source
from misoclib.com.liteeth.generic import *
class LiteEthEtherboneProbe(Module):
- def __init__(self):
- self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
- self.source = source = Source(eth_etherbone_packet_user_description(32))
- ###
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- sink.ack.eq(1),
- If(sink.stb & sink.sop,
- sink.ack.eq(0),
- NextState("PROBE_RESPONSE")
- )
- )
- fsm.act("PROBE_RESPONSE",
- Record.connect(sink, source),
- source.pf.eq(0),
- source.pr.eq(1),
- If(source.stb & source.eop & source.ack,
- NextState("IDLE")
- )
- )
+ def __init__(self):
+ self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
+ self.source = source = Source(eth_etherbone_packet_user_description(32))
+ ###
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ If(sink.stb & sink.sop,
+ sink.ack.eq(0),
+ NextState("PROBE_RESPONSE")
+ )
+ )
+ fsm.act("PROBE_RESPONSE",
+ Record.connect(sink, source),
+ source.pf.eq(0),
+ source.pr.eq(1),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer
class LiteEthEtherboneRecordPacketizer(LiteEthPacketizer):
- def __init__(self):
- LiteEthPacketizer.__init__(self,
- eth_etherbone_record_description(32),
- eth_etherbone_packet_user_description(32),
- etherbone_record_header,
- etherbone_record_header_len)
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_etherbone_record_description(32),
+ eth_etherbone_packet_user_description(32),
+ etherbone_record_header,
+ etherbone_record_header_len)
class LiteEthEtherboneRecordDepacketizer(LiteEthDepacketizer):
- def __init__(self):
- LiteEthDepacketizer.__init__(self,
- eth_etherbone_packet_user_description(32),
- eth_etherbone_record_description(32),
- etherbone_record_header,
- etherbone_record_header_len)
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_etherbone_packet_user_description(32),
+ eth_etherbone_record_description(32),
+ etherbone_record_header,
+ etherbone_record_header_len)
class LiteEthEtherboneRecordReceiver(Module):
- def __init__(self, buffer_depth=256):
- self.sink = sink = Sink(eth_etherbone_record_description(32))
- self.source = source = Source(eth_etherbone_mmap_description(32))
- ###
- fifo = SyncFIFO(eth_etherbone_record_description(32), buffer_depth, buffered=True)
- self.submodules += fifo
- self.comb += Record.connect(sink, fifo.sink)
+ def __init__(self, buffer_depth=256):
+ self.sink = sink = Sink(eth_etherbone_record_description(32))
+ self.source = source = Source(eth_etherbone_mmap_description(32))
+ ###
+ fifo = SyncFIFO(eth_etherbone_record_description(32), buffer_depth, buffered=True)
+ self.submodules += fifo
+ self.comb += Record.connect(sink, fifo.sink)
- self.submodules.base_addr = base_addr = FlipFlop(32)
- self.comb += base_addr.d.eq(fifo.source.data)
+ self.submodules.base_addr = base_addr = FlipFlop(32)
+ self.comb += base_addr.d.eq(fifo.source.data)
- self.submodules.counter = counter = Counter(max=512)
+ self.submodules.counter = counter = Counter(max=512)
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- fifo.source.ack.eq(1),
- counter.reset.eq(1),
- If(fifo.source.stb & fifo.source.sop,
- base_addr.ce.eq(1),
- If(fifo.source.wcount,
- NextState("RECEIVE_WRITES")
- ).Elif(fifo.source.rcount,
- NextState("RECEIVE_READS")
- )
- )
- )
- fsm.act("RECEIVE_WRITES",
- source.stb.eq(fifo.source.stb),
- source.sop.eq(counter.value == 0),
- source.eop.eq(counter.value == fifo.source.wcount-1),
- source.count.eq(fifo.source.wcount),
- source.be.eq(fifo.source.byte_enable),
- source.addr.eq(base_addr.q[2:] + counter.value),
- source.we.eq(1),
- source.data.eq(fifo.source.data),
- fifo.source.ack.eq(source.ack),
- If(source.stb & source.ack,
- counter.ce.eq(1),
- If(source.eop,
- If(fifo.source.rcount,
- NextState("RECEIVE_BASE_RET_ADDR")
- ).Else(
- NextState("IDLE")
- )
- )
- )
- )
- fsm.act("RECEIVE_BASE_RET_ADDR",
- counter.reset.eq(1),
- If(fifo.source.stb & fifo.source.sop,
- base_addr.ce.eq(1),
- NextState("RECEIVE_READS")
- )
- )
- fsm.act("RECEIVE_READS",
- source.stb.eq(fifo.source.stb),
- source.sop.eq(counter.value == 0),
- source.eop.eq(counter.value == fifo.source.rcount-1),
- source.count.eq(fifo.source.rcount),
- source.base_addr.eq(base_addr.q),
- source.addr.eq(fifo.source.data[2:]),
- fifo.source.ack.eq(source.ack),
- If(source.stb & source.ack,
- counter.ce.eq(1),
- If(source.eop,
- NextState("IDLE")
- )
- )
- )
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ fifo.source.ack.eq(1),
+ counter.reset.eq(1),
+ If(fifo.source.stb & fifo.source.sop,
+ base_addr.ce.eq(1),
+ If(fifo.source.wcount,
+ NextState("RECEIVE_WRITES")
+ ).Elif(fifo.source.rcount,
+ NextState("RECEIVE_READS")
+ )
+ )
+ )
+ fsm.act("RECEIVE_WRITES",
+ source.stb.eq(fifo.source.stb),
+ source.sop.eq(counter.value == 0),
+ source.eop.eq(counter.value == fifo.source.wcount-1),
+ source.count.eq(fifo.source.wcount),
+ source.be.eq(fifo.source.byte_enable),
+ source.addr.eq(base_addr.q[2:] + counter.value),
+ source.we.eq(1),
+ source.data.eq(fifo.source.data),
+ fifo.source.ack.eq(source.ack),
+ If(source.stb & source.ack,
+ counter.ce.eq(1),
+ If(source.eop,
+ If(fifo.source.rcount,
+ NextState("RECEIVE_BASE_RET_ADDR")
+ ).Else(
+ NextState("IDLE")
+ )
+ )
+ )
+ )
+ fsm.act("RECEIVE_BASE_RET_ADDR",
+ counter.reset.eq(1),
+ If(fifo.source.stb & fifo.source.sop,
+ base_addr.ce.eq(1),
+ NextState("RECEIVE_READS")
+ )
+ )
+ fsm.act("RECEIVE_READS",
+ source.stb.eq(fifo.source.stb),
+ source.sop.eq(counter.value == 0),
+ source.eop.eq(counter.value == fifo.source.rcount-1),
+ source.count.eq(fifo.source.rcount),
+ source.base_addr.eq(base_addr.q),
+ source.addr.eq(fifo.source.data[2:]),
+ fifo.source.ack.eq(source.ack),
+ If(source.stb & source.ack,
+ counter.ce.eq(1),
+ If(source.eop,
+ NextState("IDLE")
+ )
+ )
+ )
class LiteEthEtherboneRecordSender(Module):
- def __init__(self, buffer_depth=256):
- self.sink = sink = Sink(eth_etherbone_mmap_description(32))
- self.source = source = Source(eth_etherbone_record_description(32))
- ###
- pbuffer = PacketBuffer(eth_etherbone_mmap_description(32), buffer_depth)
- self.submodules += pbuffer
- self.comb += Record.connect(sink, pbuffer.sink)
+ def __init__(self, buffer_depth=256):
+ self.sink = sink = Sink(eth_etherbone_mmap_description(32))
+ self.source = source = Source(eth_etherbone_record_description(32))
+ ###
+ pbuffer = PacketBuffer(eth_etherbone_mmap_description(32), buffer_depth)
+ self.submodules += pbuffer
+ self.comb += Record.connect(sink, pbuffer.sink)
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- pbuffer.source.ack.eq(1),
- If(pbuffer.source.stb & pbuffer.source.sop,
- pbuffer.source.ack.eq(0),
- NextState("SEND_BASE_ADDRESS")
- )
- )
- self.comb += [
- source.byte_enable.eq(pbuffer.source.be),
- If(pbuffer.source.we,
- source.wcount.eq(pbuffer.source.count)
- ).Else(
- source.rcount.eq(pbuffer.source.count)
- )
- ]
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ pbuffer.source.ack.eq(1),
+ If(pbuffer.source.stb & pbuffer.source.sop,
+ pbuffer.source.ack.eq(0),
+ NextState("SEND_BASE_ADDRESS")
+ )
+ )
+ self.comb += [
+ source.byte_enable.eq(pbuffer.source.be),
+ If(pbuffer.source.we,
+ source.wcount.eq(pbuffer.source.count)
+ ).Else(
+ source.rcount.eq(pbuffer.source.count)
+ )
+ ]
- fsm.act("SEND_BASE_ADDRESS",
- source.stb.eq(pbuffer.source.stb),
- source.sop.eq(1),
- source.eop.eq(0),
- source.data.eq(pbuffer.source.base_addr),
- If(source.ack,
- NextState("SEND_DATA")
- )
- )
- fsm.act("SEND_DATA",
- source.stb.eq(pbuffer.source.stb),
- source.sop.eq(0),
- source.eop.eq(pbuffer.source.eop),
- source.data.eq(pbuffer.source.data),
- If(source.stb & source.ack,
- pbuffer.source.ack.eq(1),
- If(source.eop,
- NextState("IDLE")
- )
- )
- )
+ fsm.act("SEND_BASE_ADDRESS",
+ source.stb.eq(pbuffer.source.stb),
+ source.sop.eq(1),
+ source.eop.eq(0),
+ source.data.eq(pbuffer.source.base_addr),
+ If(source.ack,
+ NextState("SEND_DATA")
+ )
+ )
+ fsm.act("SEND_DATA",
+ source.stb.eq(pbuffer.source.stb),
+ source.sop.eq(0),
+ source.eop.eq(pbuffer.source.eop),
+ source.data.eq(pbuffer.source.data),
+ If(source.stb & source.ack,
+ pbuffer.source.ack.eq(1),
+ If(source.eop,
+ NextState("IDLE")
+ )
+ )
+ )
# Limitation: For simplicity we only support 1 record per packet
class LiteEthEtherboneRecord(Module):
- def __init__(self, endianness="big"):
- self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
- self.source = source = Sink(eth_etherbone_packet_user_description(32))
- ###
+ def __init__(self, endianness="big"):
+ self.sink = sink = Sink(eth_etherbone_packet_user_description(32))
+ self.source = source = Sink(eth_etherbone_packet_user_description(32))
+ ###
- # receive record, decode it and generate mmap stream
- self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer()
- self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver()
- self.comb += [
- Record.connect(sink, depacketizer.sink),
- Record.connect(depacketizer.source, receiver.sink)
- ]
- if endianness is "big":
- self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data))
+ # receive record, decode it and generate mmap stream
+ self.submodules.depacketizer = depacketizer = LiteEthEtherboneRecordDepacketizer()
+ self.submodules.receiver = receiver = LiteEthEtherboneRecordReceiver()
+ self.comb += [
+ Record.connect(sink, depacketizer.sink),
+ Record.connect(depacketizer.source, receiver.sink)
+ ]
+ if endianness is "big":
+ self.comb += receiver.sink.data.eq(reverse_bytes(depacketizer.source.data))
- # save last ip address
- last_ip_address = Signal(32)
- self.sync += [
- If(sink.stb & sink.sop & sink.ack,
- last_ip_address.eq(sink.ip_address)
- )
- ]
+ # save last ip address
+ last_ip_address = Signal(32)
+ self.sync += [
+ If(sink.stb & sink.sop & sink.ack,
+ last_ip_address.eq(sink.ip_address)
+ )
+ ]
- # receive mmap stream, encode it and send records
- self.submodules.sender = sender = LiteEthEtherboneRecordSender()
- self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer()
- self.comb += [
- Record.connect(sender.source, packetizer.sink),
- Record.connect(packetizer.source, source),
- source.length.eq(sender.source.wcount*4 + 4 +etherbone_record_header_len), # XXX improve this
- source.ip_address.eq(last_ip_address)
- ]
- if endianness is "big":
- self.comb += packetizer.sink.data.eq(reverse_bytes(sender.source.data))
+ # receive mmap stream, encode it and send records
+ self.submodules.sender = sender = LiteEthEtherboneRecordSender()
+ self.submodules.packetizer = packetizer = LiteEthEtherboneRecordPacketizer()
+ self.comb += [
+ Record.connect(sender.source, packetizer.sink),
+ Record.connect(packetizer.source, source),
+ source.length.eq(sender.source.wcount*4 + 4 +etherbone_record_header_len), # XXX improve this
+ source.ip_address.eq(last_ip_address)
+ ]
+ if endianness is "big":
+ self.comb += packetizer.sink.data.eq(reverse_bytes(sender.source.data))
from migen.bus import wishbone
class LiteEthEtherboneWishboneMaster(Module):
- def __init__(self):
- self.sink = sink = Sink(eth_etherbone_mmap_description(32))
- self.source = source = Source(eth_etherbone_mmap_description(32))
- self.bus = bus = wishbone.Interface()
- ###s
+ def __init__(self):
+ self.sink = sink = Sink(eth_etherbone_mmap_description(32))
+ self.source = source = Source(eth_etherbone_mmap_description(32))
+ self.bus = bus = wishbone.Interface()
+ ###s
- self.submodules.data = data = FlipFlop(32)
- self.comb += data.d.eq(bus.dat_r)
+ self.submodules.data = data = FlipFlop(32)
+ self.comb += data.d.eq(bus.dat_r)
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- sink.ack.eq(1),
- If(sink.stb & sink.sop,
- sink.ack.eq(0),
- If(sink.we,
- NextState("WRITE_DATA")
- ).Else(
- NextState("READ_DATA")
- )
- )
- )
- fsm.act("WRITE_DATA",
- bus.adr.eq(sink.addr),
- bus.dat_w.eq(sink.data),
- bus.sel.eq(sink.be),
- bus.stb.eq(sink.stb),
- bus.we.eq(1),
- bus.cyc.eq(1),
- If(bus.stb & bus.ack,
- sink.ack.eq(1),
- If(sink.eop,
- NextState("IDLE")
- )
- )
- )
- fsm.act("READ_DATA",
- bus.adr.eq(sink.addr),
- bus.sel.eq(sink.be),
- bus.stb.eq(sink.stb),
- bus.cyc.eq(1),
- If(bus.stb & bus.ack,
- data.ce.eq(1),
- NextState("SEND_DATA")
- )
- )
- fsm.act("SEND_DATA",
- source.stb.eq(sink.stb),
- source.sop.eq(sink.sop),
- source.eop.eq(sink.eop),
- source.base_addr.eq(sink.base_addr),
- source.addr.eq(sink.addr),
- source.count.eq(sink.count),
- source.be.eq(sink.be),
- source.we.eq(1),
- source.data.eq(data.q),
- If(source.stb & source.ack,
- sink.ack.eq(1),
- If(source.eop,
- NextState("IDLE")
- ).Else(
- NextState("READ_DATA")
- )
- )
- )
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ If(sink.stb & sink.sop,
+ sink.ack.eq(0),
+ If(sink.we,
+ NextState("WRITE_DATA")
+ ).Else(
+ NextState("READ_DATA")
+ )
+ )
+ )
+ fsm.act("WRITE_DATA",
+ bus.adr.eq(sink.addr),
+ bus.dat_w.eq(sink.data),
+ bus.sel.eq(sink.be),
+ bus.stb.eq(sink.stb),
+ bus.we.eq(1),
+ bus.cyc.eq(1),
+ If(bus.stb & bus.ack,
+ sink.ack.eq(1),
+ If(sink.eop,
+ NextState("IDLE")
+ )
+ )
+ )
+ fsm.act("READ_DATA",
+ bus.adr.eq(sink.addr),
+ bus.sel.eq(sink.be),
+ bus.stb.eq(sink.stb),
+ bus.cyc.eq(1),
+ If(bus.stb & bus.ack,
+ data.ce.eq(1),
+ NextState("SEND_DATA")
+ )
+ )
+ fsm.act("SEND_DATA",
+ source.stb.eq(sink.stb),
+ source.sop.eq(sink.sop),
+ source.eop.eq(sink.eop),
+ source.base_addr.eq(sink.base_addr),
+ source.addr.eq(sink.addr),
+ source.count.eq(sink.count),
+ source.be.eq(sink.be),
+ source.we.eq(1),
+ source.data.eq(data.q),
+ If(source.stb & source.ack,
+ sink.ack.eq(1),
+ If(source.eop,
+ NextState("IDLE")
+ ).Else(
+ NextState("READ_DATA")
+ )
+ )
+ )
from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer
class LiteEthICMPPacketizer(LiteEthPacketizer):
- def __init__(self):
- LiteEthPacketizer.__init__(self,
- eth_icmp_description(8),
- eth_ipv4_user_description(8),
- icmp_header,
- icmp_header_len)
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_icmp_description(8),
+ eth_ipv4_user_description(8),
+ icmp_header,
+ icmp_header_len)
class LiteEthICMPTX(Module):
- def __init__(self, ip_address):
- self.sink = sink = Sink(eth_icmp_user_description(8))
- self.source = source = Source(eth_ipv4_user_description(8))
- ###
- self.submodules.packetizer = packetizer = LiteEthICMPPacketizer()
- 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.msgtype.eq(sink.msgtype),
- packetizer.sink.code.eq(sink.code),
- packetizer.sink.checksum.eq(sink.checksum),
- packetizer.sink.quench.eq(sink.quench),
- packetizer.sink.data.eq(sink.data)
- ]
+ def __init__(self, ip_address):
+ self.sink = sink = Sink(eth_icmp_user_description(8))
+ self.source = source = Source(eth_ipv4_user_description(8))
+ ###
+ self.submodules.packetizer = packetizer = LiteEthICMPPacketizer()
+ 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.msgtype.eq(sink.msgtype),
+ packetizer.sink.code.eq(sink.code),
+ packetizer.sink.checksum.eq(sink.checksum),
+ packetizer.sink.quench.eq(sink.quench),
+ 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")
- )
- )
- fsm.act("SEND",
- Record.connect(packetizer.source, source),
- source.length.eq(sink.length + icmp_header_len),
- source.protocol.eq(icmp_protocol),
- source.ip_address.eq(sink.ip_address),
- If(source.stb & source.eop & source.ack,
- NextState("IDLE")
- )
- )
+ 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")
+ )
+ )
+ fsm.act("SEND",
+ Record.connect(packetizer.source, source),
+ source.length.eq(sink.length + icmp_header_len),
+ source.protocol.eq(icmp_protocol),
+ source.ip_address.eq(sink.ip_address),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
class LiteEthICMPDepacketizer(LiteEthDepacketizer):
- def __init__(self):
- LiteEthDepacketizer.__init__(self,
- eth_ipv4_user_description(8),
- eth_icmp_description(8),
- icmp_header,
- icmp_header_len)
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_ipv4_user_description(8),
+ eth_icmp_description(8),
+ icmp_header,
+ icmp_header_len)
class LiteEthICMPRX(Module):
- def __init__(self, ip_address):
- self.sink = sink = Sink(eth_ipv4_user_description(8))
- self.source = source = Source(eth_icmp_user_description(8))
- ###
- self.submodules.depacketizer = depacketizer = LiteEthICMPDepacketizer()
- self.comb += Record.connect(sink, depacketizer.sink)
+ def __init__(self, ip_address):
+ self.sink = sink = Sink(eth_ipv4_user_description(8))
+ self.source = source = Source(eth_icmp_user_description(8))
+ ###
+ self.submodules.depacketizer = depacketizer = LiteEthICMPDepacketizer()
+ 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 &
- (sink.protocol == icmp_protocol)
- )
- 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.msgtype.eq(depacketizer.source.msgtype),
- source.code.eq(depacketizer.source.code),
- source.checksum.eq(depacketizer.source.checksum),
- source.quench.eq(depacketizer.source.quench),
- source.ip_address.eq(sink.ip_address),
- source.length.eq(sink.length - icmp_header_len),
- 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")
- )
- )
+ 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 &
+ (sink.protocol == icmp_protocol)
+ )
+ 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.msgtype.eq(depacketizer.source.msgtype),
+ source.code.eq(depacketizer.source.code),
+ source.checksum.eq(depacketizer.source.checksum),
+ source.quench.eq(depacketizer.source.quench),
+ source.ip_address.eq(sink.ip_address),
+ source.length.eq(sink.length - icmp_header_len),
+ 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 LiteEthICMPEcho(Module):
- def __init__(self):
- self.sink = sink = Sink(eth_icmp_user_description(8))
- self.source = source = Source(eth_icmp_user_description(8))
- ###
- self.submodules.buffer = PacketBuffer(eth_icmp_user_description(8), 128, 2)
- self.comb += [
- Record.connect(sink, self.buffer.sink),
- Record.connect(self.buffer.source, source),
- self.source.msgtype.eq(0x0),
- self.source.checksum.eq(~((~self.buffer.source.checksum)-0x0800))
- ]
+ def __init__(self):
+ self.sink = sink = Sink(eth_icmp_user_description(8))
+ self.source = source = Source(eth_icmp_user_description(8))
+ ###
+ self.submodules.buffer = PacketBuffer(eth_icmp_user_description(8), 128, 2)
+ self.comb += [
+ Record.connect(sink, self.buffer.sink),
+ Record.connect(self.buffer.source, source),
+ self.source.msgtype.eq(0x0),
+ self.source.checksum.eq(~((~self.buffer.source.checksum)-0x0800))
+ ]
class LiteEthICMP(Module):
- def __init__(self, ip, ip_address):
- self.submodules.tx = tx = LiteEthICMPTX(ip_address)
- self.submodules.rx = rx = LiteEthICMPRX(ip_address)
- self.submodules.echo = echo = LiteEthICMPEcho()
- self.comb += [
- Record.connect(rx.source, echo.sink),
- Record.connect(echo.source, tx.sink)
- ]
- ip_port = ip.crossbar.get_port(icmp_protocol)
- self.comb += [
- Record.connect(tx.source, ip_port.sink),
- Record.connect(ip_port.source, rx.sink)
- ]
+ def __init__(self, ip, ip_address):
+ self.submodules.tx = tx = LiteEthICMPTX(ip_address)
+ self.submodules.rx = rx = LiteEthICMPRX(ip_address)
+ self.submodules.echo = echo = LiteEthICMPEcho()
+ self.comb += [
+ Record.connect(rx.source, echo.sink),
+ Record.connect(echo.source, tx.sink)
+ ]
+ ip_port = ip.crossbar.get_port(icmp_protocol)
+ self.comb += [
+ Record.connect(tx.source, ip_port.sink),
+ Record.connect(ip_port.source, rx.sink)
+ ]
from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer
class LiteEthIPV4Packetizer(LiteEthPacketizer):
- def __init__(self):
- LiteEthPacketizer.__init__(self,
- eth_ipv4_description(8),
- eth_mac_description(8),
- ipv4_header,
- ipv4_header_len)
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_ipv4_description(8),
+ eth_mac_description(8),
+ ipv4_header,
+ ipv4_header_len)
class LiteEthIPTX(Module):
- def __init__(self, mac_address, ip_address, arp_table):
- self.sink = sink = Sink(eth_ipv4_user_description(8))
- self.source = source = Source(eth_mac_description(8))
- self.target_unreachable = Signal()
- ###
- self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=True)
- self.comb += [
- checksum.ce.eq(sink.stb & sink.sop),
- checksum.reset.eq(source.stb & source.eop & source.ack)
- ]
+ def __init__(self, mac_address, ip_address, arp_table):
+ self.sink = sink = Sink(eth_ipv4_user_description(8))
+ self.source = source = Source(eth_mac_description(8))
+ self.target_unreachable = Signal()
+ ###
+ self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=True)
+ self.comb += [
+ checksum.ce.eq(sink.stb & sink.sop),
+ checksum.reset.eq(source.stb & source.eop & source.ack)
+ ]
- self.submodules.packetizer = packetizer = LiteEthIPV4Packetizer()
- self.comb += [
- packetizer.sink.stb.eq(sink.stb & checksum.done),
- packetizer.sink.sop.eq(sink.sop),
- packetizer.sink.eop.eq(sink.eop),
- sink.ack.eq(packetizer.sink.ack & checksum.done),
- packetizer.sink.target_ip.eq(sink.ip_address),
- packetizer.sink.protocol.eq(sink.protocol),
- packetizer.sink.total_length.eq(sink.length + (0x5*4)),
- packetizer.sink.version.eq(0x4), # ipv4
- packetizer.sink.ihl.eq(0x5), # 20 bytes
- packetizer.sink.identification.eq(0),
- packetizer.sink.ttl.eq(0x80),
- packetizer.sink.sender_ip.eq(ip_address),
- packetizer.sink.data.eq(sink.data),
- checksum.header.eq(packetizer.header),
- packetizer.sink.checksum.eq(checksum.value)
- ]
+ self.submodules.packetizer = packetizer = LiteEthIPV4Packetizer()
+ self.comb += [
+ packetizer.sink.stb.eq(sink.stb & checksum.done),
+ packetizer.sink.sop.eq(sink.sop),
+ packetizer.sink.eop.eq(sink.eop),
+ sink.ack.eq(packetizer.sink.ack & checksum.done),
+ packetizer.sink.target_ip.eq(sink.ip_address),
+ packetizer.sink.protocol.eq(sink.protocol),
+ packetizer.sink.total_length.eq(sink.length + (0x5*4)),
+ packetizer.sink.version.eq(0x4), # ipv4
+ packetizer.sink.ihl.eq(0x5), # 20 bytes
+ packetizer.sink.identification.eq(0),
+ packetizer.sink.ttl.eq(0x80),
+ packetizer.sink.sender_ip.eq(ip_address),
+ packetizer.sink.data.eq(sink.data),
+ checksum.header.eq(packetizer.header),
+ packetizer.sink.checksum.eq(checksum.value)
+ ]
- target_mac = Signal(48)
+ target_mac = Signal(48)
- 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_MAC_ADDRESS_REQUEST")
- )
- )
- self.comb += arp_table.request.ip_address.eq(sink.ip_address)
- fsm.act("SEND_MAC_ADDRESS_REQUEST",
- arp_table.request.stb.eq(1),
- If(arp_table.request.stb & arp_table.request.ack,
- NextState("WAIT_MAC_ADDRESS_RESPONSE")
- )
- )
- fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
- If(arp_table.response.stb,
- arp_table.response.ack.eq(1),
- If(arp_table.response.failed,
- self.target_unreachable.eq(1),
- NextState("DROP"),
- ).Else(
- NextState("SEND")
- )
- )
- )
- self.sync += \
- If(arp_table.response.stb,
- target_mac.eq(arp_table.response.mac_address)
- )
- fsm.act("SEND",
- Record.connect(packetizer.source, source),
- source.ethernet_type.eq(ethernet_type_ip),
- source.target_mac.eq(target_mac),
- source.sender_mac.eq(mac_address),
- If(source.stb & source.eop & source.ack,
- NextState("IDLE")
- )
- )
- fsm.act("DROP",
- packetizer.source.ack.eq(1),
- If(packetizer.source.stb & packetizer.source.eop & packetizer.source.ack,
- NextState("IDLE")
- )
- )
+ 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_MAC_ADDRESS_REQUEST")
+ )
+ )
+ self.comb += arp_table.request.ip_address.eq(sink.ip_address)
+ fsm.act("SEND_MAC_ADDRESS_REQUEST",
+ arp_table.request.stb.eq(1),
+ If(arp_table.request.stb & arp_table.request.ack,
+ NextState("WAIT_MAC_ADDRESS_RESPONSE")
+ )
+ )
+ fsm.act("WAIT_MAC_ADDRESS_RESPONSE",
+ If(arp_table.response.stb,
+ arp_table.response.ack.eq(1),
+ If(arp_table.response.failed,
+ self.target_unreachable.eq(1),
+ NextState("DROP"),
+ ).Else(
+ NextState("SEND")
+ )
+ )
+ )
+ self.sync += \
+ If(arp_table.response.stb,
+ target_mac.eq(arp_table.response.mac_address)
+ )
+ fsm.act("SEND",
+ Record.connect(packetizer.source, source),
+ source.ethernet_type.eq(ethernet_type_ip),
+ source.target_mac.eq(target_mac),
+ source.sender_mac.eq(mac_address),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
+ fsm.act("DROP",
+ packetizer.source.ack.eq(1),
+ If(packetizer.source.stb & packetizer.source.eop & packetizer.source.ack,
+ NextState("IDLE")
+ )
+ )
class LiteEthIPV4Depacketizer(LiteEthDepacketizer):
- def __init__(self):
- LiteEthDepacketizer.__init__(self,
- eth_mac_description(8),
- eth_ipv4_description(8),
- ipv4_header,
- ipv4_header_len)
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_mac_description(8),
+ eth_ipv4_description(8),
+ ipv4_header,
+ ipv4_header_len)
class LiteEthIPRX(Module):
- def __init__(self, mac_address, ip_address):
- self.sink = sink = Sink(eth_mac_description(8))
- self.source = source = Source(eth_ipv4_user_description(8))
- ###
- self.submodules.depacketizer = depacketizer = LiteEthIPV4Depacketizer()
- self.comb += Record.connect(sink, depacketizer.sink)
+ def __init__(self, mac_address, ip_address):
+ self.sink = sink = Sink(eth_mac_description(8))
+ self.source = source = Source(eth_ipv4_user_description(8))
+ ###
+ self.submodules.depacketizer = depacketizer = LiteEthIPV4Depacketizer()
+ self.comb += Record.connect(sink, depacketizer.sink)
- self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=False)
- self.comb += [
- checksum.header.eq(depacketizer.header),
- checksum.reset.eq(depacketizer.source.stb & depacketizer.source.eop),
- checksum.ce.eq(depacketizer.source.stb & depacketizer.source.sop)
- ]
+ self.submodules.checksum = checksum = LiteEthIPV4Checksum(skip_checksum=False)
+ self.comb += [
+ checksum.header.eq(depacketizer.header),
+ checksum.reset.eq(depacketizer.source.stb & depacketizer.source.eop),
+ checksum.ce.eq(depacketizer.source.stb & depacketizer.source.sop)
+ ]
- 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.target_ip == ip_address) &
- (depacketizer.source.version == 0x4) &
- (depacketizer.source.ihl == 0x5) &
- (checksum.value == 0)
- )
+ 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.target_ip == ip_address) &
+ (depacketizer.source.version == 0x4) &
+ (depacketizer.source.ihl == 0x5) &
+ (checksum.value == 0)
+ )
- fsm.act("CHECK",
- If(checksum.done,
- If(valid,
- NextState("PRESENT")
- ).Else(
- NextState("DROP")
- )
- )
- )
- self.comb += [
- source.sop.eq(depacketizer.source.sop),
- source.eop.eq(depacketizer.source.eop),
- source.length.eq(depacketizer.source.total_length - (0x5*4)),
- source.protocol.eq(depacketizer.source.protocol),
- source.ip_address.eq(depacketizer.source.sender_ip),
- 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")
- )
- )
+ fsm.act("CHECK",
+ If(checksum.done,
+ If(valid,
+ NextState("PRESENT")
+ ).Else(
+ NextState("DROP")
+ )
+ )
+ )
+ self.comb += [
+ source.sop.eq(depacketizer.source.sop),
+ source.eop.eq(depacketizer.source.eop),
+ source.length.eq(depacketizer.source.total_length - (0x5*4)),
+ source.protocol.eq(depacketizer.source.protocol),
+ source.ip_address.eq(depacketizer.source.sender_ip),
+ 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 LiteEthIP(Module):
- def __init__(self, mac, mac_address, ip_address, arp_table):
- self.submodules.tx = tx = LiteEthIPTX(mac_address, ip_address, arp_table)
- self.submodules.rx = rx = LiteEthIPRX(mac_address, ip_address)
- mac_port = mac.crossbar.get_port(ethernet_type_ip)
- self.comb += [
- Record.connect(tx.source, mac_port.sink),
- Record.connect(mac_port.source, rx.sink)
- ]
- self.submodules.crossbar = crossbar = LiteEthIPV4Crossbar()
- self.comb += [
- Record.connect(crossbar.master.source, tx.sink),
- Record.connect(rx.source, crossbar.master.sink)
- ]
+ def __init__(self, mac, mac_address, ip_address, arp_table):
+ self.submodules.tx = tx = LiteEthIPTX(mac_address, ip_address, arp_table)
+ self.submodules.rx = rx = LiteEthIPRX(mac_address, ip_address)
+ mac_port = mac.crossbar.get_port(ethernet_type_ip)
+ self.comb += [
+ Record.connect(tx.source, mac_port.sink),
+ Record.connect(mac_port.source, rx.sink)
+ ]
+ self.submodules.crossbar = crossbar = LiteEthIPV4Crossbar()
+ self.comb += [
+ Record.connect(crossbar.master.source, tx.sink),
+ Record.connect(rx.source, crossbar.master.sink)
+ ]
from misoclib.com.liteeth.generic import *
class LiteEthIPV4Checksum(Module):
- def __init__(self, words_per_clock_cycle=1, skip_checksum=False):
- self.reset = Signal() # XXX FIXME InsertReset generates incorrect verilog
- self.ce = Signal() # XXX FIXME InsertCE generates incorrect verilog
- self.header = Signal(ipv4_header_len*8)
- self.value = Signal(16)
- self.done = Signal()
- ###
- s = Signal(17)
- r = Signal(17)
- n_cycles = 0
- for i in range(ipv4_header_len//2):
- if skip_checksum and (i == ipv4_header["checksum"].byte//2):
- pass
- else:
- s_next = Signal(17)
- r_next = Signal(17)
- self.comb += s_next.eq(r + self.header[i*16:(i+1)*16])
- r_next_eq = r_next.eq(Cat(s_next[:16]+s_next[16], Signal()))
- if (i%words_per_clock_cycle) != 0:
- self.comb += r_next_eq
- else:
- self.sync += \
- If(self.reset,
- r_next.eq(0)
- ).Elif(self.ce & ~self.done,
- r_next_eq
- )
- n_cycles += 1
- s, r = s_next, r_next
- self.comb += self.value.eq(~Cat(r[8:16], r[:8]))
+ def __init__(self, words_per_clock_cycle=1, skip_checksum=False):
+ self.reset = Signal() # XXX FIXME InsertReset generates incorrect verilog
+ self.ce = Signal() # XXX FIXME InsertCE generates incorrect verilog
+ self.header = Signal(ipv4_header_len*8)
+ self.value = Signal(16)
+ self.done = Signal()
+ ###
+ s = Signal(17)
+ r = Signal(17)
+ n_cycles = 0
+ for i in range(ipv4_header_len//2):
+ if skip_checksum and (i == ipv4_header["checksum"].byte//2):
+ pass
+ else:
+ s_next = Signal(17)
+ r_next = Signal(17)
+ self.comb += s_next.eq(r + self.header[i*16:(i+1)*16])
+ r_next_eq = r_next.eq(Cat(s_next[:16]+s_next[16], Signal()))
+ if (i%words_per_clock_cycle) != 0:
+ self.comb += r_next_eq
+ else:
+ self.sync += \
+ If(self.reset,
+ r_next.eq(0)
+ ).Elif(self.ce & ~self.done,
+ r_next_eq
+ )
+ n_cycles += 1
+ s, r = s_next, r_next
+ self.comb += self.value.eq(~Cat(r[8:16], r[:8]))
- if not skip_checksum:
- n_cycles += 1
- self.submodules.counter = counter = Counter(max=n_cycles+1)
- self.comb += [
- counter.reset.eq(self.reset),
- counter.ce.eq(self.ce & ~self.done),
- self.done.eq(counter.value == n_cycles)
- ]
+ if not skip_checksum:
+ n_cycles += 1
+ self.submodules.counter = counter = Counter(max=n_cycles+1)
+ self.comb += [
+ counter.reset.eq(self.reset),
+ counter.ce.eq(self.ce & ~self.done),
+ self.done.eq(counter.value == n_cycles)
+ ]
from misoclib.com.liteeth.generic.crossbar import LiteEthCrossbar
class LiteEthIPV4MasterPort:
- def __init__(self, dw):
- self.dw = dw
- self.source = Source(eth_ipv4_user_description(dw))
- self.sink = Sink(eth_ipv4_user_description(dw))
+ def __init__(self, dw):
+ self.dw = dw
+ self.source = Source(eth_ipv4_user_description(dw))
+ self.sink = Sink(eth_ipv4_user_description(dw))
class LiteEthIPV4SlavePort:
- def __init__(self, dw):
- self.dw = dw
- self.sink = Sink(eth_ipv4_user_description(dw))
- self.source = Source(eth_ipv4_user_description(dw))
+ def __init__(self, dw):
+ self.dw = dw
+ self.sink = Sink(eth_ipv4_user_description(dw))
+ self.source = Source(eth_ipv4_user_description(dw))
class LiteEthIPV4UserPort(LiteEthIPV4SlavePort):
- def __init__(self, dw):
- LiteEthIPV4SlavePort.__init__(self, dw)
+ def __init__(self, dw):
+ LiteEthIPV4SlavePort.__init__(self, dw)
class LiteEthIPV4Crossbar(LiteEthCrossbar):
- def __init__(self):
- LiteEthCrossbar.__init__(self, LiteEthIPV4MasterPort, "protocol")
+ def __init__(self):
+ LiteEthCrossbar.__init__(self, LiteEthIPV4MasterPort, "protocol")
- def get_port(self, protocol):
- if protocol in self.users.keys():
- raise ValueError("Protocol {0:#x} already assigned".format(protocol))
- port = LiteEthIPV4UserPort(8)
- self.users[protocol] = port
- return port
+ def get_port(self, protocol):
+ if protocol in self.users.keys():
+ raise ValueError("Protocol {0:#x} already assigned".format(protocol))
+ port = LiteEthIPV4UserPort(8)
+ self.users[protocol] = port
+ return port
from misoclib.com.liteeth.generic import *
class LiteEthTTYTX(Module):
- def __init__(self, ip_address, udp_port, fifo_depth=None):
- self.sink = sink = Sink(eth_tty_description(8))
- self.source = source = Source(eth_udp_user_description(8))
- ###
- if fifo_depth is None:
- self.comb += [
- source.stb.eq(sink.stb),
- source.sop.eq(1),
- source.eop.eq(1),
- source.length.eq(1),
- source.data.eq(sink.data),
- sink.ack.eq(source.ack)
- ]
- else:
- self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth)
- self.comb += Record.connect(sink, fifo.sink)
+ def __init__(self, ip_address, udp_port, fifo_depth=None):
+ self.sink = sink = Sink(eth_tty_description(8))
+ self.source = source = Source(eth_udp_user_description(8))
+ ###
+ if fifo_depth is None:
+ self.comb += [
+ source.stb.eq(sink.stb),
+ source.sop.eq(1),
+ source.eop.eq(1),
+ source.length.eq(1),
+ source.data.eq(sink.data),
+ sink.ack.eq(source.ack)
+ ]
+ else:
+ self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth)
+ self.comb += Record.connect(sink, fifo.sink)
- self.submodules.level = level = FlipFlop(max=fifo_depth)
- self.comb += level.d.eq(fifo.fifo.level)
+ self.submodules.level = level = FlipFlop(max=fifo_depth)
+ self.comb += level.d.eq(fifo.fifo.level)
- self.submodules.counter = counter = Counter(max=fifo_depth)
+ self.submodules.counter = counter = Counter(max=fifo_depth)
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- If(fifo.source.stb,
- level.ce.eq(1),
- counter.reset.eq(1),
- NextState("SEND")
- )
- )
- fsm.act("SEND",
- source.stb.eq(fifo.source.stb),
- source.sop.eq(counter.value == 0),
- If(level.q == 0,
- source.eop.eq(1),
- ).Else(
- source.eop.eq(counter.value == (level.q-1)),
- ),
- source.src_port.eq(udp_port),
- source.dst_port.eq(udp_port),
- source.ip_address.eq(ip_address),
- If(level.q == 0,
- source.length.eq(1),
- ).Else(
- source.length.eq(level.q),
- ),
- source.data.eq(fifo.source.data),
- fifo.source.ack.eq(source.ack),
- If(source.stb & source.ack,
- counter.ce.eq(1),
- If(source.eop,
- NextState("IDLE")
- )
- )
- )
+ self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+ fsm.act("IDLE",
+ If(fifo.source.stb,
+ level.ce.eq(1),
+ counter.reset.eq(1),
+ NextState("SEND")
+ )
+ )
+ fsm.act("SEND",
+ source.stb.eq(fifo.source.stb),
+ source.sop.eq(counter.value == 0),
+ If(level.q == 0,
+ source.eop.eq(1),
+ ).Else(
+ source.eop.eq(counter.value == (level.q-1)),
+ ),
+ source.src_port.eq(udp_port),
+ source.dst_port.eq(udp_port),
+ source.ip_address.eq(ip_address),
+ If(level.q == 0,
+ source.length.eq(1),
+ ).Else(
+ source.length.eq(level.q),
+ ),
+ source.data.eq(fifo.source.data),
+ fifo.source.ack.eq(source.ack),
+ If(source.stb & source.ack,
+ counter.ce.eq(1),
+ If(source.eop,
+ NextState("IDLE")
+ )
+ )
+ )
class LiteEthTTYRX(Module):
- def __init__(self, ip_address, udp_port, fifo_depth=None):
- self.sink = sink = Sink(eth_udp_user_description(8))
- self.source = source = Source(eth_tty_description(8))
- ###
- valid = Signal()
- self.comb += valid.eq(
- (sink.ip_address == ip_address) &
- (sink.dst_port == udp_port)
- )
- if fifo_depth is None:
- self.comb += [
- source.stb.eq(sink.stb & valid),
- source.data.eq(sink.data),
- sink.ack.eq(source.ack)
- ]
- else:
- self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth)
- self.comb += [
- fifo.sink.stb.eq(sink.stb & valid),
- fifo.sink.data.eq(sink.data),
- sink.ack.eq(fifo.sink.ack),
- Record.connect(fifo.source, source)
- ]
+ def __init__(self, ip_address, udp_port, fifo_depth=None):
+ self.sink = sink = Sink(eth_udp_user_description(8))
+ self.source = source = Source(eth_tty_description(8))
+ ###
+ valid = Signal()
+ self.comb += valid.eq(
+ (sink.ip_address == ip_address) &
+ (sink.dst_port == udp_port)
+ )
+ if fifo_depth is None:
+ self.comb += [
+ source.stb.eq(sink.stb & valid),
+ source.data.eq(sink.data),
+ sink.ack.eq(source.ack)
+ ]
+ else:
+ self.submodules.fifo = fifo = SyncFIFO([("data", 8)], fifo_depth)
+ self.comb += [
+ fifo.sink.stb.eq(sink.stb & valid),
+ fifo.sink.data.eq(sink.data),
+ sink.ack.eq(fifo.sink.ack),
+ Record.connect(fifo.source, source)
+ ]
class LiteEthTTY(Module):
- def __init__(self, udp, ip_address, udp_port,
- rx_fifo_depth=64,
- tx_fifo_depth=64):
- self.submodules.tx = tx = LiteEthTTYTX(ip_address, udp_port, tx_fifo_depth)
- self.submodules.rx = rx = LiteEthTTYRX(ip_address, udp_port, rx_fifo_depth)
- udp_port = udp.crossbar.get_port(udp_port, dw=8)
- self.comb += [
- Record.connect(tx.source, udp_port.sink),
- Record.connect(udp_port.source, rx.sink)
- ]
- self.sink, self.source = self.tx.sink, self.rx.source
+ def __init__(self, udp, ip_address, udp_port,
+ rx_fifo_depth=64,
+ tx_fifo_depth=64):
+ self.submodules.tx = tx = LiteEthTTYTX(ip_address, udp_port, tx_fifo_depth)
+ self.submodules.rx = rx = LiteEthTTYRX(ip_address, udp_port, rx_fifo_depth)
+ udp_port = udp.crossbar.get_port(udp_port, dw=8)
+ self.comb += [
+ Record.connect(tx.source, udp_port.sink),
+ Record.connect(udp_port.source, rx.sink)
+ ]
+ self.sink, self.source = self.tx.sink, self.rx.source
from misoclib.com.liteeth.generic.packetizer import LiteEthPacketizer
class LiteEthUDPPacketizer(LiteEthPacketizer):
- def __init__(self):
- LiteEthPacketizer.__init__(self,
- eth_udp_description(8),
- eth_ipv4_user_description(8),
- udp_header,
- udp_header_len)
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_udp_description(8),
+ eth_ipv4_user_description(8),
+ udp_header,
+ udp_header_len)
class LiteEthUDPTX(Module):
- def __init__(self, ip_address):
- self.sink = sink = Sink(eth_udp_user_description(8))
- self.source = source = Source(eth_ipv4_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.src_port.eq(sink.src_port),
- packetizer.sink.dst_port.eq(sink.dst_port),
- packetizer.sink.length.eq(sink.length + udp_header_len),
- packetizer.sink.checksum.eq(0), # Disabled (MAC CRC is enough)
- packetizer.sink.data.eq(sink.data)
- ]
+ def __init__(self, ip_address):
+ self.sink = sink = Sink(eth_udp_user_description(8))
+ self.source = source = Source(eth_ipv4_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.src_port.eq(sink.src_port),
+ packetizer.sink.dst_port.eq(sink.dst_port),
+ packetizer.sink.length.eq(sink.length + udp_header_len),
+ packetizer.sink.checksum.eq(0), # Disabled (MAC CRC is enough)
+ 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")
- )
- )
- fsm.act("SEND",
- Record.connect(packetizer.source, source),
- source.length.eq(packetizer.sink.length),
- source.protocol.eq(udp_protocol),
- source.ip_address.eq(sink.ip_address),
- If(source.stb & source.eop & source.ack,
- NextState("IDLE")
- )
- )
+ 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")
+ )
+ )
+ fsm.act("SEND",
+ Record.connect(packetizer.source, source),
+ source.length.eq(packetizer.sink.length),
+ source.protocol.eq(udp_protocol),
+ source.ip_address.eq(sink.ip_address),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
class LiteEthUDPDepacketizer(LiteEthDepacketizer):
- def __init__(self):
- LiteEthDepacketizer.__init__(self,
- eth_ipv4_user_description(8),
- eth_udp_description(8),
- udp_header,
- udp_header_len)
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_ipv4_user_description(8),
+ eth_udp_description(8),
+ udp_header,
+ udp_header_len)
class LiteEthUDPRX(Module):
- def __init__(self, ip_address):
- self.sink = sink = Sink(eth_ipv4_user_description(8))
- self.source = source = Source(eth_udp_user_description(8))
- ###
- self.submodules.depacketizer = depacketizer = LiteEthUDPDepacketizer()
- self.comb += Record.connect(sink, depacketizer.sink)
+ def __init__(self, ip_address):
+ self.sink = sink = Sink(eth_ipv4_user_description(8))
+ self.source = source = Source(eth_udp_user_description(8))
+ ###
+ self.submodules.depacketizer = depacketizer = LiteEthUDPDepacketizer()
+ 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 &
- (sink.protocol == udp_protocol)
- )
+ 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 &
+ (sink.protocol == udp_protocol)
+ )
- 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.src_port.eq(depacketizer.source.src_port),
- source.dst_port.eq(depacketizer.source.dst_port),
- source.ip_address.eq(sink.ip_address),
- source.length.eq(depacketizer.source.length - udp_header_len),
- 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")
- )
- )
+ 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.src_port.eq(depacketizer.source.src_port),
+ source.dst_port.eq(depacketizer.source.dst_port),
+ source.ip_address.eq(sink.ip_address),
+ source.length.eq(depacketizer.source.length - udp_header_len),
+ 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 LiteEthUDP(Module):
- def __init__(self, ip, ip_address):
- self.submodules.tx = tx = LiteEthUDPTX(ip_address)
- self.submodules.rx = rx = LiteEthUDPRX(ip_address)
- ip_port = ip.crossbar.get_port(udp_protocol)
- self.comb += [
- Record.connect(tx.source, ip_port.sink),
- Record.connect(ip_port.source, rx.sink)
- ]
- self.submodules.crossbar = crossbar = LiteEthUDPCrossbar()
- self.comb += [
- Record.connect(crossbar.master.source, tx.sink),
- Record.connect(rx.source, crossbar.master.sink)
- ]
+ def __init__(self, ip, ip_address):
+ self.submodules.tx = tx = LiteEthUDPTX(ip_address)
+ self.submodules.rx = rx = LiteEthUDPRX(ip_address)
+ ip_port = ip.crossbar.get_port(udp_protocol)
+ self.comb += [
+ Record.connect(tx.source, ip_port.sink),
+ Record.connect(ip_port.source, rx.sink)
+ ]
+ self.submodules.crossbar = crossbar = LiteEthUDPCrossbar()
+ self.comb += [
+ Record.connect(crossbar.master.source, tx.sink),
+ Record.connect(rx.source, crossbar.master.sink)
+ ]
from misoclib.com.liteeth.generic.crossbar import LiteEthCrossbar
class LiteEthUDPMasterPort:
- def __init__(self, dw):
- self.dw = dw
- self.source = Source(eth_udp_user_description(dw))
- self.sink = Sink(eth_udp_user_description(dw))
+ def __init__(self, dw):
+ self.dw = dw
+ self.source = Source(eth_udp_user_description(dw))
+ self.sink = Sink(eth_udp_user_description(dw))
class LiteEthUDPSlavePort:
- def __init__(self, dw):
- self.dw =dw
- self.sink = Sink(eth_udp_user_description(dw))
- self.source = Source(eth_udp_user_description(dw))
+ def __init__(self, dw):
+ self.dw =dw
+ self.sink = Sink(eth_udp_user_description(dw))
+ self.source = Source(eth_udp_user_description(dw))
class LiteEthUDPUserPort(LiteEthUDPSlavePort):
- def __init__(self, dw):
- LiteEthUDPSlavePort.__init__(self, dw)
+ def __init__(self, dw):
+ LiteEthUDPSlavePort.__init__(self, dw)
class LiteEthUDPCrossbar(LiteEthCrossbar):
- def __init__(self):
- LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port")
+ def __init__(self):
+ LiteEthCrossbar.__init__(self, LiteEthUDPMasterPort, "dst_port")
- def get_port(self, udp_port, dw=8):
- if udp_port in self.users.keys():
- raise ValueError("Port {0:#x} already assigned".format(udp_port))
- user_port = LiteEthUDPUserPort(dw)
- internal_port = LiteEthUDPUserPort(8)
- if dw != 8:
- converter = Converter(eth_udp_user_description(user_port.dw), eth_udp_user_description(8))
- self.submodules += converter
- self.comb += [
- Record.connect(user_port.sink, converter.sink),
- Record.connect(converter.source, internal_port.sink)
- ]
- converter = Converter(eth_udp_user_description(8), eth_udp_user_description(user_port.dw))
- self.submodules += converter
- self.comb += [
- Record.connect(internal_port.source, converter.sink),
- Record.connect(converter.source, user_port.source)
- ]
- self.users[udp_port] = internal_port
- else:
- self.users[udp_port] = user_port
- return user_port
+ def get_port(self, udp_port, dw=8):
+ if udp_port in self.users.keys():
+ raise ValueError("Port {0:#x} already assigned".format(udp_port))
+ user_port = LiteEthUDPUserPort(dw)
+ internal_port = LiteEthUDPUserPort(8)
+ if dw != 8:
+ converter = Converter(eth_udp_user_description(user_port.dw), eth_udp_user_description(8))
+ self.submodules += converter
+ self.comb += [
+ Record.connect(user_port.sink, converter.sink),
+ Record.connect(converter.source, internal_port.sink)
+ ]
+ converter = Converter(eth_udp_user_description(8), eth_udp_user_description(user_port.dw))
+ self.submodules += converter
+ self.comb += [
+ Record.connect(internal_port.source, converter.sink),
+ Record.connect(converter.source, user_port.source)
+ ]
+ self.users[udp_port] = internal_port
+ else:
+ self.users[udp_port] = user_port
+ return user_port
from misoclib.com.liteeth.common import *
def _import(default, name):
- return importlib.import_module(default + "." + name)
+ return importlib.import_module(default + "." + name)
def _get_args():
- parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
- description="""\
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""\
LiteEth - based on Migen.
This program builds and/or loads LiteEth components.
all clean, build-csr-csv, build-bitstream, load-bitstream.
""")
- parser.add_argument("-t", "--target", default="base", help="Core type to build")
- parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build")
- parser.add_argument("-p", "--platform", default=None, help="platform to build for")
- parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option")
- parser.add_argument("-Op", "--platform-option", default=[], nargs=2, action="append", help="set platform-specific option")
- parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into")
+ parser.add_argument("-t", "--target", default="base", help="Core type to build")
+ parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build")
+ parser.add_argument("-p", "--platform", default=None, help="platform to build for")
+ parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option")
+ parser.add_argument("-Op", "--platform-option", default=[], nargs=2, action="append", help="set platform-specific option")
+ parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into")
- parser.add_argument("action", nargs="+", help="specify an action")
+ parser.add_argument("action", nargs="+", help="specify an action")
- return parser.parse_args()
+ return parser.parse_args()
# Note: misoclib need to be installed as a python library
if __name__ == "__main__":
- args = _get_args()
-
- # create top-level Core object
- target_module = _import("targets", args.target)
- if args.sub_target:
- top_class = getattr(target_module, args.sub_target)
- else:
- top_class = target_module.default_subtarget
-
- if args.platform is None:
- if hasattr(top_class, "default_platform"):
- platform_name = top_class.default_platform
- else:
- raise ValueError("Target has no default platform, specify a platform with -p your_platform")
- else:
- platform_name = args.platform
- platform_module = _import("mibuild.platforms", platform_name)
- platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option)
- platform = platform_module.Platform(**platform_kwargs)
-
- build_name = top_class.__name__.lower() + "-" + platform_name
- top_kwargs = dict((k, autotype(v)) for k, v in args.target_option)
- soc = top_class(platform, **top_kwargs)
- soc.finalize()
- memory_regions = soc.get_memory_regions()
- csr_regions = soc.get_csr_regions()
-
- # decode actions
- action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"]
- actions = {k: False for k in action_list}
- for action in args.action:
- if action in actions:
- actions[action] = True
- else:
- print("Unknown action: "+action+". Valid actions are:")
- for a in action_list:
- print(" "+a)
- sys.exit(1)
-
- print("""
+ args = _get_args()
+
+ # create top-level Core object
+ target_module = _import("targets", args.target)
+ if args.sub_target:
+ top_class = getattr(target_module, args.sub_target)
+ else:
+ top_class = target_module.default_subtarget
+
+ if args.platform is None:
+ if hasattr(top_class, "default_platform"):
+ platform_name = top_class.default_platform
+ else:
+ raise ValueError("Target has no default platform, specify a platform with -p your_platform")
+ else:
+ platform_name = args.platform
+ platform_module = _import("mibuild.platforms", platform_name)
+ platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option)
+ platform = platform_module.Platform(**platform_kwargs)
+
+ build_name = top_class.__name__.lower() + "-" + platform_name
+ top_kwargs = dict((k, autotype(v)) for k, v in args.target_option)
+ soc = top_class(platform, **top_kwargs)
+ soc.finalize()
+ memory_regions = soc.get_memory_regions()
+ csr_regions = soc.get_csr_regions()
+
+ # decode actions
+ action_list = ["clean", "build-csr-csv", "build-bitstream", "load-bitstream", "all"]
+ actions = {k: False for k in action_list}
+ for action in args.action:
+ if action in actions:
+ actions[action] = True
+ else:
+ print("Unknown action: "+action+". Valid actions are:")
+ for a in action_list:
+ print(" "+a)
+ sys.exit(1)
+
+ print("""
__ _ __ ______ __
/ / (_) /____ / __/ /_/ /
/ /__/ / __/ -_) _// __/ _ \\
Subtarget: {}
System Clk: {} MHz
===============================""".format(
- platform_name,
- args.target,
- top_class.__name__,
- soc.clk_freq/1000000
- )
+ platform_name,
+ args.target,
+ top_class.__name__,
+ soc.clk_freq/1000000
+ )
)
- # dependencies
- if actions["all"]:
- actions["build-csr-csv"] = True
- actions["build-bitstream"] = True
- actions["load-bitstream"] = True
-
- if actions["build-bitstream"]:
- actions["build-csr-csv"] = True
- actions["build-bitstream"] = True
- actions["load-bitstream"] = True
-
- if actions["clean"]:
- subprocess.call(["rm", "-rf", "build/*"])
-
- if actions["build-csr-csv"]:
- csr_csv = cpuif.get_csr_csv(csr_regions)
- write_to_file(args.csr_csv, csr_csv)
-
- if actions["build-bitstream"]:
- vns = platform.build(soc, build_name=build_name)
- if hasattr(soc, "do_exit") and vns is not None:
- if hasattr(soc.do_exit, '__call__'):
- soc.do_exit(vns)
-
- if actions["load-bitstream"]:
- prog = platform.create_programmer()
- prog.load_bitstream("build/" + build_name + platform.bitstream_ext)
+ # dependencies
+ if actions["all"]:
+ actions["build-csr-csv"] = True
+ actions["build-bitstream"] = True
+ actions["load-bitstream"] = True
+
+ if actions["build-bitstream"]:
+ actions["build-csr-csv"] = True
+ actions["build-bitstream"] = True
+ actions["load-bitstream"] = True
+
+ if actions["clean"]:
+ subprocess.call(["rm", "-rf", "build/*"])
+
+ if actions["build-csr-csv"]:
+ csr_csv = cpuif.get_csr_csv(csr_regions)
+ write_to_file(args.csr_csv, csr_csv)
+
+ if actions["build-bitstream"]:
+ vns = platform.build(soc, build_name=build_name)
+ if hasattr(soc, "do_exit") and vns is not None:
+ if hasattr(soc.do_exit, '__call__'):
+ soc.do_exit(vns)
+
+ if actions["load-bitstream"]:
+ prog = platform.create_programmer()
+ prog.load_bitstream("build/" + build_name + platform.bitstream_ext)
from misoclib.com.liteeth.core import LiteEthUDPIPCore
class BaseSoC(SoC, AutoCSR):
- csr_map = {
- "phy": 11,
- "core": 12
- }
- csr_map.update(SoC.csr_map)
- def __init__(self, platform, clk_freq=166*1000000,
- mac_address=0x10e2d5000000,
- ip_address="192.168.0.42"):
- clk_freq = int((1/(platform.default_clk_period))*1000000000)
- SoC.__init__(self, platform, clk_freq,
- cpu_type="none",
- with_csr=True, csr_data_width=32,
- with_uart=False,
- with_identifier=True,
- with_timer=False
- )
- self.add_cpu_or_bridge(LiteScopeUART2WB(platform.request("serial"), clk_freq, baudrate=115200))
- self.add_wb_master(self.cpu_or_bridge.wishbone)
- self.submodules.crg = CRG(platform.request(platform.default_clk_name))
-
- # wishbone SRAM (to test Wishbone over UART and Etherbone)
- self.submodules.sram = wishbone.SRAM(1024)
- self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus)
-
- # ethernet PHY and UDP/IP stack
- self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth"))
- self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq)
+ csr_map = {
+ "phy": 11,
+ "core": 12
+ }
+ csr_map.update(SoC.csr_map)
+ def __init__(self, platform, clk_freq=166*1000000,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.0.42"):
+ clk_freq = int((1/(platform.default_clk_period))*1000000000)
+ SoC.__init__(self, platform, clk_freq,
+ cpu_type="none",
+ with_csr=True, csr_data_width=32,
+ with_uart=False,
+ with_identifier=True,
+ with_timer=False
+ )
+ self.add_cpu_or_bridge(LiteScopeUART2WB(platform.request("serial"), clk_freq, baudrate=115200))
+ self.add_wb_master(self.cpu_or_bridge.wishbone)
+ self.submodules.crg = CRG(platform.request(platform.default_clk_name))
+
+ # wishbone SRAM (to test Wishbone over UART and Etherbone)
+ self.submodules.sram = wishbone.SRAM(1024)
+ self.add_wb_slave(lambda a: a[23:25] == 1, self.sram.bus)
+
+ # ethernet PHY and UDP/IP stack
+ self.submodules.phy = LiteEthPHYGMII(platform.request("eth_clocks"), platform.request("eth"))
+ self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address, convert_ip(ip_address), clk_freq)
class BaseSoCDevel(BaseSoC, AutoCSR):
- csr_map = {
- "la": 20
- }
- csr_map.update(BaseSoC.csr_map)
- def __init__(self, platform):
- BaseSoC.__init__(self, platform)
-
- self.core_icmp_rx_fsm_state = Signal(4)
- self.core_icmp_tx_fsm_state = Signal(4)
- self.core_udp_rx_fsm_state = Signal(4)
- self.core_udp_tx_fsm_state = Signal(4)
- self.core_ip_rx_fsm_state = Signal(4)
- self.core_ip_tx_fsm_state = Signal(4)
- self.core_arp_rx_fsm_state = Signal(4)
- self.core_arp_tx_fsm_state = Signal(4)
- self.core_arp_table_fsm_state = Signal(4)
-
- debug = (
- # MAC interface
- self.core.mac.core.sink.stb,
- self.core.mac.core.sink.sop,
- self.core.mac.core.sink.eop,
- self.core.mac.core.sink.ack,
- self.core.mac.core.sink.data,
-
- self.core.mac.core.source.stb,
- self.core.mac.core.source.sop,
- self.core.mac.core.source.eop,
- self.core.mac.core.source.ack,
- self.core.mac.core.source.data,
-
- # ICMP interface
- self.core.icmp.echo.sink.stb,
- self.core.icmp.echo.sink.sop,
- self.core.icmp.echo.sink.eop,
- self.core.icmp.echo.sink.ack,
- self.core.icmp.echo.sink.data,
-
- self.core.icmp.echo.source.stb,
- self.core.icmp.echo.source.sop,
- self.core.icmp.echo.source.eop,
- self.core.icmp.echo.source.ack,
- self.core.icmp.echo.source.data,
-
- # IP interface
- self.core.ip.crossbar.master.sink.stb,
- self.core.ip.crossbar.master.sink.sop,
- self.core.ip.crossbar.master.sink.eop,
- self.core.ip.crossbar.master.sink.ack,
- self.core.ip.crossbar.master.sink.data,
- self.core.ip.crossbar.master.sink.ip_address,
- self.core.ip.crossbar.master.sink.protocol,
-
- # State machines
- self.core_icmp_rx_fsm_state,
- self.core_icmp_tx_fsm_state,
-
- self.core_arp_rx_fsm_state,
- self.core_arp_tx_fsm_state,
- self.core_arp_table_fsm_state,
-
- self.core_ip_rx_fsm_state,
- self.core_ip_tx_fsm_state,
-
- self.core_udp_rx_fsm_state,
- self.core_udp_tx_fsm_state
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
-
- def do_finalize(self):
- BaseSoC.do_finalize(self)
- self.comb += [
- self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state),
- self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state),
-
- self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state),
- self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state),
- self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state),
-
- self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state),
- self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state),
-
- self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state),
- self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state)
- ]
-
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(BaseSoC.csr_map)
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform)
+
+ self.core_icmp_rx_fsm_state = Signal(4)
+ self.core_icmp_tx_fsm_state = Signal(4)
+ self.core_udp_rx_fsm_state = Signal(4)
+ self.core_udp_tx_fsm_state = Signal(4)
+ self.core_ip_rx_fsm_state = Signal(4)
+ self.core_ip_tx_fsm_state = Signal(4)
+ self.core_arp_rx_fsm_state = Signal(4)
+ self.core_arp_tx_fsm_state = Signal(4)
+ self.core_arp_table_fsm_state = Signal(4)
+
+ debug = (
+ # MAC interface
+ self.core.mac.core.sink.stb,
+ self.core.mac.core.sink.sop,
+ self.core.mac.core.sink.eop,
+ self.core.mac.core.sink.ack,
+ self.core.mac.core.sink.data,
+
+ self.core.mac.core.source.stb,
+ self.core.mac.core.source.sop,
+ self.core.mac.core.source.eop,
+ self.core.mac.core.source.ack,
+ self.core.mac.core.source.data,
+
+ # ICMP interface
+ self.core.icmp.echo.sink.stb,
+ self.core.icmp.echo.sink.sop,
+ self.core.icmp.echo.sink.eop,
+ self.core.icmp.echo.sink.ack,
+ self.core.icmp.echo.sink.data,
+
+ self.core.icmp.echo.source.stb,
+ self.core.icmp.echo.source.sop,
+ self.core.icmp.echo.source.eop,
+ self.core.icmp.echo.source.ack,
+ self.core.icmp.echo.source.data,
+
+ # IP interface
+ self.core.ip.crossbar.master.sink.stb,
+ self.core.ip.crossbar.master.sink.sop,
+ self.core.ip.crossbar.master.sink.eop,
+ self.core.ip.crossbar.master.sink.ack,
+ self.core.ip.crossbar.master.sink.data,
+ self.core.ip.crossbar.master.sink.ip_address,
+ self.core.ip.crossbar.master.sink.protocol,
+
+ # State machines
+ self.core_icmp_rx_fsm_state,
+ self.core_icmp_tx_fsm_state,
+
+ self.core_arp_rx_fsm_state,
+ self.core_arp_tx_fsm_state,
+ self.core_arp_table_fsm_state,
+
+ self.core_ip_rx_fsm_state,
+ self.core_ip_tx_fsm_state,
+
+ self.core_udp_rx_fsm_state,
+ self.core_udp_tx_fsm_state
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+
+ def do_finalize(self):
+ BaseSoC.do_finalize(self)
+ self.comb += [
+ self.core_icmp_rx_fsm_state.eq(self.core.icmp.rx.fsm.state),
+ self.core_icmp_tx_fsm_state.eq(self.core.icmp.tx.fsm.state),
+
+ self.core_arp_rx_fsm_state.eq(self.core.arp.rx.fsm.state),
+ self.core_arp_tx_fsm_state.eq(self.core.arp.tx.fsm.state),
+ self.core_arp_table_fsm_state.eq(self.core.arp.table.fsm.state),
+
+ self.core_ip_rx_fsm_state.eq(self.core.ip.rx.fsm.state),
+ self.core_ip_tx_fsm_state.eq(self.core.ip.tx.fsm.state),
+
+ self.core_udp_rx_fsm_state.eq(self.core.udp.rx.fsm.state),
+ self.core_udp_tx_fsm_state.eq(self.core.udp.tx.fsm.state)
+ ]
+
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
default_subtarget = BaseSoC
from misoclib.com.liteeth.core.etherbone import LiteEthEtherbone
class EtherboneSoC(BaseSoC):
- default_platform = "kc705"
- def __init__(self, platform):
- BaseSoC.__init__(self, platform,
- mac_address=0x10e2d5000000,
- ip_address="192.168.0.42")
- self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000)
- self.add_wb_master(self.etherbone.master.bus)
+ default_platform = "kc705"
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.0.42")
+ self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000)
+ self.add_wb_master(self.etherbone.master.bus)
class EtherboneSoCDevel(EtherboneSoC):
- csr_map = {
- "la": 20
- }
- csr_map.update(EtherboneSoC.csr_map)
- def __init__(self, platform):
- EtherboneSoC.__init__(self, platform)
- debug = (
- # mmap stream from HOST
- self.etherbone.master.sink.stb,
- self.etherbone.master.sink.sop,
- self.etherbone.master.sink.eop,
- self.etherbone.master.sink.ack,
- self.etherbone.master.sink.we,
- self.etherbone.master.sink.count,
- self.etherbone.master.sink.base_addr,
- self.etherbone.master.sink.be,
- self.etherbone.master.sink.addr,
- self.etherbone.master.sink.data,
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(EtherboneSoC.csr_map)
+ def __init__(self, platform):
+ EtherboneSoC.__init__(self, platform)
+ debug = (
+ # mmap stream from HOST
+ self.etherbone.master.sink.stb,
+ self.etherbone.master.sink.sop,
+ self.etherbone.master.sink.eop,
+ self.etherbone.master.sink.ack,
+ self.etherbone.master.sink.we,
+ self.etherbone.master.sink.count,
+ self.etherbone.master.sink.base_addr,
+ self.etherbone.master.sink.be,
+ self.etherbone.master.sink.addr,
+ self.etherbone.master.sink.data,
- # mmap stream to HOST
- self.etherbone.master.source.stb,
- self.etherbone.master.source.sop,
- self.etherbone.master.source.eop,
- self.etherbone.master.source.ack,
- self.etherbone.master.source.we,
- self.etherbone.master.source.count,
- self.etherbone.master.source.base_addr,
- self.etherbone.master.source.be,
- self.etherbone.master.source.addr,
- self.etherbone.master.source.data,
+ # mmap stream to HOST
+ self.etherbone.master.source.stb,
+ self.etherbone.master.source.sop,
+ self.etherbone.master.source.eop,
+ self.etherbone.master.source.ack,
+ self.etherbone.master.source.we,
+ self.etherbone.master.source.count,
+ self.etherbone.master.source.base_addr,
+ self.etherbone.master.source.be,
+ self.etherbone.master.source.addr,
+ self.etherbone.master.source.data,
- # etherbone wishbone master
- self.etherbone.master.bus.dat_w,
- self.etherbone.master.bus.dat_r,
- self.etherbone.master.bus.adr,
- self.etherbone.master.bus.sel,
- self.etherbone.master.bus.cyc,
- self.etherbone.master.bus.stb,
- self.etherbone.master.bus.ack,
- self.etherbone.master.bus.we,
- self.etherbone.master.bus.cti,
- self.etherbone.master.bus.bte,
- self.etherbone.master.bus.err
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+ # etherbone wishbone master
+ self.etherbone.master.bus.dat_w,
+ self.etherbone.master.bus.dat_r,
+ self.etherbone.master.bus.adr,
+ self.etherbone.master.bus.sel,
+ self.etherbone.master.bus.cyc,
+ self.etherbone.master.bus.stb,
+ self.etherbone.master.bus.ack,
+ self.etherbone.master.bus.we,
+ self.etherbone.master.bus.cti,
+ self.etherbone.master.bus.bte,
+ self.etherbone.master.bus.err
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
default_subtarget = EtherboneSoC
from misoclib.com.liteeth.core.tty import LiteEthTTY
class TTYSoC(BaseSoC):
- default_platform = "kc705"
- def __init__(self, platform):
- BaseSoC.__init__(self, platform,
- mac_address=0x10e2d5000000,
- ip_address="192.168.0.42")
- self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.0.14"), 10000)
- self.comb += Record.connect(self.tty.source, self.tty.sink)
+ default_platform = "kc705"
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.0.42")
+ self.submodules.tty = LiteEthTTY(self.core.udp, convert_ip("192.168.0.14"), 10000)
+ self.comb += Record.connect(self.tty.source, self.tty.sink)
class TTYSoCDevel(TTYSoC):
- csr_map = {
- "la": 20
- }
- csr_map.update(TTYSoC.csr_map)
- def __init__(self, platform):
- TTYSoC.__init__(self, platform)
- debug = (
- self.tty.sink.stb,
- self.tty.sink.ack,
- self.tty.sink.data,
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(TTYSoC.csr_map)
+ def __init__(self, platform):
+ TTYSoC.__init__(self, platform)
+ debug = (
+ self.tty.sink.stb,
+ self.tty.sink.ack,
+ self.tty.sink.data,
- self.tty.source.stb,
- self.tty.source.ack,
- self.tty.source.data
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+ self.tty.source.stb,
+ self.tty.source.ack,
+ self.tty.source.data
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
default_subtarget = TTYSoC
from targets.base import BaseSoC
class UDPSoC(BaseSoC):
- default_platform = "kc705"
- def __init__(self, platform):
- BaseSoC.__init__(self, platform,
- mac_address=0x10e2d5000000,
- ip_address="192.168.0.42")
+ default_platform = "kc705"
+ def __init__(self, platform):
+ BaseSoC.__init__(self, platform,
+ mac_address=0x10e2d5000000,
+ ip_address="192.168.0.42")
- # add udp loopback on port 6000 with dw=8
- self.add_udp_loopback(6000, 8, 8192, "loopback_8")
- # add udp loopback on port 8000 with dw=32
- self.add_udp_loopback(8000, 32, 8192, "loopback_32")
+ # add udp loopback on port 6000 with dw=8
+ self.add_udp_loopback(6000, 8, 8192, "loopback_8")
+ # add udp loopback on port 8000 with dw=32
+ self.add_udp_loopback(8000, 32, 8192, "loopback_32")
- def add_udp_loopback(self, port, dw, depth, name=None):
- port = self.core.udp.crossbar.get_port(port, dw)
- buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8)
- if name is None:
- self.submodules += buf
- else:
- setattr(self.submodules, name, buf)
- self.comb += Port.connect(port, buf)
+ def add_udp_loopback(self, port, dw, depth, name=None):
+ port = self.core.udp.crossbar.get_port(port, dw)
+ buf = PacketBuffer(eth_udp_user_description(dw), depth//(dw//8), 8)
+ if name is None:
+ self.submodules += buf
+ else:
+ setattr(self.submodules, name, buf)
+ self.comb += Port.connect(port, buf)
class UDPSoCDevel(UDPSoC):
- csr_map = {
- "la": 20
- }
- csr_map.update(UDPSoC.csr_map)
- def __init__(self, platform):
- UDPSoC.__init__(self, platform)
- debug = (
- self.loopback_8.sink.stb,
- self.loopback_8.sink.sop,
- self.loopback_8.sink.eop,
- self.loopback_8.sink.ack,
- self.loopback_8.sink.data,
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(UDPSoC.csr_map)
+ def __init__(self, platform):
+ UDPSoC.__init__(self, platform)
+ debug = (
+ self.loopback_8.sink.stb,
+ self.loopback_8.sink.sop,
+ self.loopback_8.sink.eop,
+ self.loopback_8.sink.ack,
+ self.loopback_8.sink.data,
- self.loopback_8.source.stb,
- self.loopback_8.source.sop,
- self.loopback_8.source.eop,
- self.loopback_8.source.ack,
- self.loopback_8.source.data,
+ self.loopback_8.source.stb,
+ self.loopback_8.source.sop,
+ self.loopback_8.source.eop,
+ self.loopback_8.source.ack,
+ self.loopback_8.source.data,
- self.loopback_32.sink.stb,
- self.loopback_32.sink.sop,
- self.loopback_32.sink.eop,
- self.loopback_32.sink.ack,
- self.loopback_32.sink.data,
+ self.loopback_32.sink.stb,
+ self.loopback_32.sink.sop,
+ self.loopback_32.sink.eop,
+ self.loopback_32.sink.ack,
+ self.loopback_32.sink.data,
- self.loopback_32.source.stb,
- self.loopback_32.source.sop,
- self.loopback_32.source.eop,
- self.loopback_32.source.ack,
- self.loopback_32.source.data
- )
- self.submodules.la = LiteScopeLA(debug, 4096)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+ self.loopback_32.source.stb,
+ self.loopback_32.source.sop,
+ self.loopback_32.source.eop,
+ self.loopback_32.source.ack,
+ self.loopback_32.source.data
+ )
+ self.submodules.la = LiteScopeLA(debug, 4096)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
default_subtarget = UDPSoC
import argparse, importlib
def _get_args():
- parser = argparse.ArgumentParser()
- parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use")
- parser.add_argument("--port", default="2", help="UART port")
- parser.add_argument("--baudrate", default=115200, help="UART baudrate")
- parser.add_argument("--ip_address", default="192.168.0.42", help="Etherbone IP address")
- parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port")
- parser.add_argument("--busword", default=32, help="CSR busword")
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use")
+ parser.add_argument("--port", default="2", help="UART port")
+ parser.add_argument("--baudrate", default=115200, help="UART baudrate")
+ parser.add_argument("--ip_address", default="192.168.0.42", help="Etherbone IP address")
+ parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port")
+ parser.add_argument("--busword", default=32, help="CSR busword")
- parser.add_argument("test", nargs="+", help="specify a test")
+ parser.add_argument("test", nargs="+", help="specify a test")
- return parser.parse_args()
+ return parser.parse_args()
if __name__ == "__main__":
- args = _get_args()
- if args.bridge == "uart":
- from misoclib.tools.litescope.host.driver.uart import LiteScopeUARTDriver
- port = args.port if not args.port.isdigit() else int(args.port)
- wb = LiteScopeUARTDriver(port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
- elif args.bridge == "etherbone":
- from misoclib.tools.litescope.host.driver.etherbone import LiteScopeEtherboneDriver
- wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False)
- else:
- ValueError("Invalid bridge {}".format(args.bridge))
+ args = _get_args()
+ if args.bridge == "uart":
+ from misoclib.tools.litescope.host.driver.uart import LiteScopeUARTDriver
+ port = args.port if not args.port.isdigit() else int(args.port)
+ wb = LiteScopeUARTDriver(port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
+ elif args.bridge == "etherbone":
+ from misoclib.tools.litescope.host.driver.etherbone import LiteScopeEtherboneDriver
+ wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False)
+ else:
+ ValueError("Invalid bridge {}".format(args.bridge))
- def _import(name):
- return importlib.import_module(name)
+ def _import(name):
+ return importlib.import_module(name)
- for test in args.test:
- t = _import(test)
- t.main(wb)
+ for test in args.test:
+ t = _import(test)
+ t.main(wb)
import socket
def main(wb):
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
- # test probe
- packet = EtherbonePacket()
- packet.pf = 1
- packet.encode()
- sock.sendto(bytes(packet), ("192.168.0.42", 20000))
- time.sleep(0.01)
-
- # test writes
- writes_datas = [j for j in range(16)]
- writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas)
- record = EtherboneRecord()
- record.writes = writes
- record.reads = None
- record.bca = 0
- record.rca = 0
- record.rff = 0
- record.cyc = 0
- record.wca = 0
- record.wff = 0
- record.byte_enable = 0xf
- record.wcount = len(writes_datas)
- record.rcount = 0
-
- packet = EtherbonePacket()
- packet.records = [record]
- packet.encode()
- sock.sendto(bytes(packet), ("192.168.0.42", 20000))
- time.sleep(0.01)
-
- # test reads
- reads_addrs = [SRAM_BASE+4*j for j in range(16)]
- reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
- record = EtherboneRecord()
- record.writes = None
- record.reads = reads
- record.bca = 0
- record.rca = 0
- record.rff = 0
- record.cyc = 0
- record.wca = 0
- record.wff = 0
- record.byte_enable = 0xf
- record.wcount = 0
- record.rcount = len(reads_addrs)
-
- packet = EtherbonePacket()
- packet.records = [record]
- packet.encode()
- sock.sendto(bytes(packet), ("192.168.0.42", 20000))
- time.sleep(0.01)
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+ # test probe
+ packet = EtherbonePacket()
+ packet.pf = 1
+ packet.encode()
+ sock.sendto(bytes(packet), ("192.168.0.42", 20000))
+ time.sleep(0.01)
+
+ # test writes
+ writes_datas = [j for j in range(16)]
+ writes = EtherboneWrites(base_addr=SRAM_BASE, datas=writes_datas)
+ record = EtherboneRecord()
+ record.writes = writes
+ record.reads = None
+ record.bca = 0
+ record.rca = 0
+ record.rff = 0
+ record.cyc = 0
+ record.wca = 0
+ record.wff = 0
+ record.byte_enable = 0xf
+ record.wcount = len(writes_datas)
+ record.rcount = 0
+
+ packet = EtherbonePacket()
+ packet.records = [record]
+ packet.encode()
+ sock.sendto(bytes(packet), ("192.168.0.42", 20000))
+ time.sleep(0.01)
+
+ # test reads
+ reads_addrs = [SRAM_BASE+4*j for j in range(16)]
+ reads = EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
+ record = EtherboneRecord()
+ record.writes = None
+ record.reads = reads
+ record.bca = 0
+ record.rca = 0
+ record.rff = 0
+ record.cyc = 0
+ record.wca = 0
+ record.wff = 0
+ record.byte_enable = 0xf
+ record.wcount = 0
+ record.rcount = len(reads_addrs)
+
+ packet = EtherbonePacket()
+ packet.records = [record]
+ packet.encode()
+ sock.sendto(bytes(packet), ("192.168.0.42", 20000))
+ time.sleep(0.01)
from misoclib.tools.litescope.host.driver.la import LiteScopeLADriver
def main(wb):
- la = LiteScopeLADriver(wb.regs, "la", debug=True)
+ la = LiteScopeLADriver(wb.regs, "la", debug=True)
- wb.open()
- regs = wb.regs
- ###
+ wb.open()
+ regs = wb.regs
+ ###
- conditions = {}
- la.configure_term(port=0, cond=conditions)
- la.configure_sum("term")
- # Run Logic Analyzer
- la.run(offset=2048, length=4000)
+ conditions = {}
+ la.configure_term(port=0, cond=conditions)
+ la.configure_sum("term")
+ # Run Logic Analyzer
+ la.run(offset=2048, length=4000)
- while not la.done():
- pass
+ while not la.done():
+ pass
- la.upload()
- la.save("dump.vcd")
+ la.upload()
+ la.save("dump.vcd")
- ###
- wb.close()
+ ###
+ wb.close()
def main(wb):
- wb.open()
- regs = wb.regs
- ###
- print("sysid : 0x{:04x}".format(regs.identifier_sysid.read()))
- print("revision : 0x{:04x}".format(regs.identifier_revision.read()))
- print("frequency : {}MHz".format(int(regs.identifier_frequency.read()/1000000)))
- SRAM_BASE = 0x02000000
- wb.write(SRAM_BASE, [i for i in range(64)])
- print(wb.read(SRAM_BASE, 64))
- ###
- wb.close()
+ wb.open()
+ regs = wb.regs
+ ###
+ print("sysid : 0x{:04x}".format(regs.identifier_sysid.read()))
+ print("revision : 0x{:04x}".format(regs.identifier_revision.read()))
+ print("frequency : {}MHz".format(int(regs.identifier_frequency.read()/1000000)))
+ SRAM_BASE = 0x02000000
+ wb.write(SRAM_BASE, [i for i in range(64)])
+ print(wb.read(SRAM_BASE, 64))
+ ###
+ wb.close()
import threading
def test(fpga_ip, udp_port, test_message):
- tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock.bind(("", udp_port))
- rx_sock.settimeout(0.5)
+ tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock.bind(("", udp_port))
+ rx_sock.settimeout(0.5)
- def receive():
- while True:
- try:
- msg = rx_sock.recv(8192)
- for byte in msg:
- print(chr(byte), end="")
- except:
- break
+ def receive():
+ while True:
+ try:
+ msg = rx_sock.recv(8192)
+ for byte in msg:
+ print(chr(byte), end="")
+ except:
+ break
- def send():
- tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port))
+ def send():
+ tx_sock.sendto(bytes(test_message, "utf-8"), (fpga_ip, udp_port))
- receive_thread = threading.Thread(target=receive)
- receive_thread.start()
+ receive_thread = threading.Thread(target=receive)
+ receive_thread.start()
- send_thread = threading.Thread(target=send)
- send_thread.start()
+ send_thread = threading.Thread(target=send)
+ send_thread.start()
- try:
- send_thread.join(5)
- send_thread.join(5)
- except KeyboardInterrupt:
- pass
+ try:
+ send_thread.join(5)
+ send_thread.join(5)
+ except KeyboardInterrupt:
+ pass
def main(wb):
- test_message = "LiteEth virtual TTY Hello world\n"
- test("192.168.0.42", 10000, test_message)
+ test_message = "LiteEth virtual TTY Hello world\n"
+ test("192.168.0.42", 10000, test_message)
GB = 1024*MB
def seed_to_data(seed, random=True):
- if random:
- return (seed * 0x31415979 + 1) & 0xffffffff
- else:
- return seed
+ 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
+ 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 generate_packet(seed, length):
- r = []
- for i in range(length):
- r.append(seed_to_data(seed, True)%0xff) # XXX FIXME
- seed += 1
- return r, seed
+ r = []
+ for i in range(length):
+ r.append(seed_to_data(seed, True)%0xff) # XXX FIXME
+ seed += 1
+ return r, seed
def test(fpga_ip, udp_port, test_size):
- tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- rx_sock.bind(("", udp_port))
+ tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ rx_sock.bind(("", udp_port))
- def receive():
- rx_seed = 0
- while rx_seed < test_size:
- data, addr = rx_sock.recvfrom(8192)
- rx_packet = []
- for byte in data:
- rx_packet.append(int(byte))
- rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024)
- s, l, e = check(rx_reference_packet, rx_packet)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ def receive():
+ rx_seed = 0
+ while rx_seed < test_size:
+ data, addr = rx_sock.recvfrom(8192)
+ rx_packet = []
+ for byte in data:
+ rx_packet.append(int(byte))
+ rx_reference_packet, rx_seed = generate_packet(rx_seed, 1024)
+ s, l, e = check(rx_reference_packet, rx_packet)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
- def send():
- tx_seed = 0
- while tx_seed < test_size:
- tx_packet, tx_seed = generate_packet(tx_seed, 1024)
- tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port))
- time.sleep(0.001) # XXX: FIXME, Python limitation?
+ def send():
+ tx_seed = 0
+ while tx_seed < test_size:
+ tx_packet, tx_seed = generate_packet(tx_seed, 1024)
+ tx_sock.sendto(bytes(tx_packet), (fpga_ip, udp_port))
+ time.sleep(0.001) # XXX: FIXME, Python limitation?
- receive_thread = threading.Thread(target=receive)
- receive_thread.start()
+ receive_thread = threading.Thread(target=receive)
+ receive_thread.start()
- send_thread = threading.Thread(target=send)
- send_thread.start()
+ send_thread = threading.Thread(target=send)
+ send_thread.start()
- try:
- send_thread.join(10)
- receive_thread.join(0.1)
- except KeyboardInterrupt:
- pass
+ try:
+ send_thread.join(10)
+ receive_thread.join(0.1)
+ except KeyboardInterrupt:
+ pass
def main(wb):
- test("192.168.0.42", 6000, 128*KB)
- test("192.168.0.42", 8000, 128*KB)
+ test("192.168.0.42", 6000, 128*KB)
+ test("192.168.0.42", 8000, 128*KB)
# Generic classes
class Port:
- def connect(self, port):
- r = [
- Record.connect(self.source, port.sink),
- Record.connect(port.source, self.sink)
- ]
- return r
+ def connect(self, port):
+ r = [
+ Record.connect(self.source, port.sink),
+ Record.connect(port.source, self.sink)
+ ]
+ return r
# Generic modules
class BufferizeEndpoints(ModuleTransformer):
- def __init__(self, *names):
- self.names = names
+ def __init__(self, *names):
+ self.names = names
- def transform_instance(self, submodule):
- endpoints = get_endpoints(submodule)
- sinks = {}
- sources = {}
- for name, endpoint in endpoints.items():
- if not self.names or name in self.names:
- if isinstance(endpoint, Sink):
- sinks.update({name : endpoint})
- elif isinstance(endpoint, Source):
- sources.update({name : endpoint})
+ def transform_instance(self, submodule):
+ endpoints = get_endpoints(submodule)
+ sinks = {}
+ sources = {}
+ for name, endpoint in endpoints.items():
+ if not self.names or name in self.names:
+ if isinstance(endpoint, Sink):
+ sinks.update({name : endpoint})
+ elif isinstance(endpoint, Source):
+ sources.update({name : endpoint})
- # add buffer on sinks
- for name, sink in sinks.items():
- buf = Buffer(sink.description)
- submodule.submodules += buf
- setattr(self, name, buf.d)
- submodule.comb += Record.connect(buf.q, sink)
+ # add buffer on sinks
+ for name, sink in sinks.items():
+ buf = Buffer(sink.description)
+ submodule.submodules += buf
+ setattr(self, name, buf.d)
+ submodule.comb += Record.connect(buf.q, sink)
- # add buffer on sources
- for name, source in sources.items():
- buf = Buffer(source.description)
- submodule.submodules += buf
- submodule.comb += Record.connect(source, buf.d)
- setattr(self, name, buf.q)
+ # add buffer on sources
+ for name, source in sources.items():
+ buf = Buffer(source.description)
+ submodule.submodules += buf
+ submodule.comb += Record.connect(source, buf.d)
+ setattr(self, name, buf.q)
class EndpointPacketStatus(Module):
- def __init__(self, endpoint):
- self.start = Signal()
- self.done = Signal()
- self.ongoing = Signal()
+ def __init__(self, endpoint):
+ self.start = Signal()
+ self.done = Signal()
+ self.ongoing = Signal()
- ongoing = Signal()
- self.comb += [
- self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack),
- self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack)
- ]
- self.sync += \
- If(self.start,
- ongoing.eq(1)
- ).Elif(self.done,
- ongoing.eq(0)
- )
- self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done)
+ ongoing = Signal()
+ self.comb += [
+ self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack),
+ self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack)
+ ]
+ self.sync += \
+ If(self.start,
+ ongoing.eq(1)
+ ).Elif(self.done,
+ ongoing.eq(0)
+ )
+ self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done)
class PacketBuffer(Module):
- def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
- self.sink = sink = Sink(description)
- self.source = source = Source(description)
+ def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
+ self.sink = sink = Sink(description)
+ self.source = source = Source(description)
- ###
- sink_status = EndpointPacketStatus(self.sink)
- source_status = EndpointPacketStatus(self.source)
- self.submodules += sink_status, source_status
+ ###
+ sink_status = EndpointPacketStatus(self.sink)
+ source_status = EndpointPacketStatus(self.source)
+ self.submodules += sink_status, source_status
- # store incoming packets
- # cmds
- def cmd_description():
- layout = [("error", 1)]
- return EndpointDescription(layout)
- cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
- self.submodules += cmd_fifo
- self.comb += cmd_fifo.sink.stb.eq(sink_status.done)
- if hasattr(sink, "error"):
- self.comb += cmd_fifo.sink.error.eq(sink.error)
+ # store incoming packets
+ # cmds
+ def cmd_description():
+ layout = [("error", 1)]
+ return EndpointDescription(layout)
+ cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
+ self.submodules += cmd_fifo
+ self.comb += cmd_fifo.sink.stb.eq(sink_status.done)
+ if hasattr(sink, "error"):
+ self.comb += cmd_fifo.sink.error.eq(sink.error)
- # data
- data_fifo = SyncFIFO(description, data_depth, buffered=True)
- self.submodules += data_fifo
- self.comb += [
- Record.connect(self.sink, data_fifo.sink),
- data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack),
- self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack),
- ]
+ # data
+ data_fifo = SyncFIFO(description, data_depth, buffered=True)
+ self.submodules += data_fifo
+ self.comb += [
+ Record.connect(self.sink, data_fifo.sink),
+ data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack),
+ self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack),
+ ]
- # output packets
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- If(cmd_fifo.source.stb,
- NextState("SEEK_SOP")
- )
- )
- fsm.act("SEEK_SOP",
- If(~data_fifo.source.sop,
- data_fifo.source.ack.eq(1)
- ).Else(
- NextState("OUTPUT")
- )
- )
- if hasattr(source, "error"):
- source_error = self.source.error
- else:
- source_error = Signal()
+ # output packets
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ If(cmd_fifo.source.stb,
+ NextState("SEEK_SOP")
+ )
+ )
+ fsm.act("SEEK_SOP",
+ If(~data_fifo.source.sop,
+ data_fifo.source.ack.eq(1)
+ ).Else(
+ NextState("OUTPUT")
+ )
+ )
+ if hasattr(source, "error"):
+ source_error = self.source.error
+ else:
+ source_error = Signal()
- fsm.act("OUTPUT",
- Record.connect(data_fifo.source, self.source),
- source_error.eq(cmd_fifo.source.error),
- If(source_status.done,
- cmd_fifo.source.ack.eq(1),
- NextState("IDLE")
- )
- )
+ fsm.act("OUTPUT",
+ Record.connect(data_fifo.source, self.source),
+ source_error.eq(cmd_fifo.source.error),
+ If(source_status.done,
+ cmd_fifo.source.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
- # compute almost full
- if almost_full is not None:
- self.almost_full = Signal()
- self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full)
+ # compute almost full
+ if almost_full is not None:
+ self.almost_full = Signal()
+ self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full)
from migen.genlib.record import *
class Arbiter(Module):
- def __init__(self, sources, sink):
- if len(sources) == 0:
- pass
- elif len(sources) == 1:
- self.grant = Signal()
- self.comb += Record.connect(sources.pop(), sink)
- else:
- self.submodules.rr = RoundRobin(len(sources))
- self.grant = self.rr.grant
- cases = {}
- for i, source in enumerate(sources):
- sop = Signal()
- eop = Signal()
- ongoing = Signal()
- self.comb += [
- sop.eq(source.stb & source.sop),
- eop.eq(source.stb & source.eop & source.ack),
- ]
- self.sync += ongoing.eq((sop | ongoing) & ~eop)
- self.comb += self.rr.request[i].eq((sop | ongoing) & ~eop)
- cases[i] = [Record.connect(source, sink)]
- self.comb += Case(self.grant, cases)
+ def __init__(self, sources, sink):
+ if len(sources) == 0:
+ pass
+ elif len(sources) == 1:
+ self.grant = Signal()
+ self.comb += Record.connect(sources.pop(), sink)
+ else:
+ self.submodules.rr = RoundRobin(len(sources))
+ self.grant = self.rr.grant
+ cases = {}
+ for i, source in enumerate(sources):
+ sop = Signal()
+ eop = Signal()
+ ongoing = Signal()
+ self.comb += [
+ sop.eq(source.stb & source.sop),
+ eop.eq(source.stb & source.eop & source.ack),
+ ]
+ self.sync += ongoing.eq((sop | ongoing) & ~eop)
+ self.comb += self.rr.request[i].eq((sop | ongoing) & ~eop)
+ cases[i] = [Record.connect(source, sink)]
+ self.comb += Case(self.grant, cases)
from misoclib.com.liteeth.generic.dispatcher import Dispatcher
class LiteEthCrossbar(Module):
- def __init__(self, master_port, dispatch_param):
- self.users = OrderedDict()
- self.master = master_port(8)
- self.dispatch_param = dispatch_param
+ def __init__(self, master_port, dispatch_param):
+ self.users = OrderedDict()
+ self.master = master_port(8)
+ self.dispatch_param = dispatch_param
- # overload this in derived classes
- def get_port(self, *args, **kwargs):
- pass
+ # overload this in derived classes
+ def get_port(self, *args, **kwargs):
+ pass
- def do_finalize(self):
- # TX arbitrate
- sinks = [port.sink for port in self.users.values()]
- self.submodules.arbiter = Arbiter(sinks, self.master.source)
+ def do_finalize(self):
+ # TX arbitrate
+ sinks = [port.sink for port in self.users.values()]
+ self.submodules.arbiter = Arbiter(sinks, self.master.source)
- # RX dispatch
- sources = [port.source for port in self.users.values()]
- self.submodules.dispatcher = Dispatcher(self.master.sink, sources, one_hot=True)
- cases = {}
- cases["default"] = self.dispatcher.sel.eq(0)
- for i, (k, v) in enumerate(self.users.items()):
- cases[k] = self.dispatcher.sel.eq(2**i)
- self.comb += \
- Case(getattr(self.master.sink, self.dispatch_param), cases)
+ # RX dispatch
+ sources = [port.source for port in self.users.values()]
+ self.submodules.dispatcher = Dispatcher(self.master.sink, sources, one_hot=True)
+ cases = {}
+ cases["default"] = self.dispatcher.sel.eq(0)
+ for i, (k, v) in enumerate(self.users.items()):
+ cases[k] = self.dispatcher.sel.eq(2**i)
+ self.comb += \
+ Case(getattr(self.master.sink, self.dispatch_param), cases)
from misoclib.com.liteeth.generic import *
def _decode_header(h_dict, h_signal, obj):
- r = []
- for k, v in sorted(h_dict.items()):
- start = v.byte*8+v.offset
- end = start+v.width
- r.append(getattr(obj, k).eq(reverse_bytes(h_signal[start:end])))
- return r
+ r = []
+ for k, v in sorted(h_dict.items()):
+ start = v.byte*8+v.offset
+ end = start+v.width
+ r.append(getattr(obj, k).eq(reverse_bytes(h_signal[start:end])))
+ return r
class LiteEthDepacketizer(Module):
- def __init__(self, sink_description, source_description, header_type, header_length):
- self.sink = sink = Sink(sink_description)
- self.source = source = Source(source_description)
- self.header = Signal(header_length*8)
- ###
- dw = flen(sink.data)
+ def __init__(self, sink_description, source_description, header_type, header_length):
+ self.sink = sink = Sink(sink_description)
+ self.source = source = Source(source_description)
+ self.header = Signal(header_length*8)
+ ###
+ dw = flen(sink.data)
- header_words = (header_length*8)//dw
+ header_words = (header_length*8)//dw
- shift = Signal()
- counter = Counter(max=max(header_words, 2))
- self.submodules += counter
+ shift = Signal()
+ counter = Counter(max=max(header_words, 2))
+ self.submodules += counter
- if header_words == 1:
- self.sync += \
- If(shift,
- self.header.eq(sink.data)
- )
- else:
- self.sync += \
- If(shift,
- self.header.eq(Cat(self.header[dw:], sink.data))
- )
+ if header_words == 1:
+ self.sync += \
+ If(shift,
+ self.header.eq(sink.data)
+ )
+ else:
+ self.sync += \
+ If(shift,
+ self.header.eq(Cat(self.header[dw:], sink.data))
+ )
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
- if header_words == 1:
- idle_next_state = "COPY"
- else:
- idle_next_state = "RECEIVE_HEADER"
+ if header_words == 1:
+ idle_next_state = "COPY"
+ else:
+ idle_next_state = "RECEIVE_HEADER"
- fsm.act("IDLE",
- sink.ack.eq(1),
- counter.reset.eq(1),
- If(sink.stb,
- shift.eq(1),
- NextState(idle_next_state)
- )
- )
- if header_words != 1:
- fsm.act("RECEIVE_HEADER",
- sink.ack.eq(1),
- If(sink.stb,
- counter.ce.eq(1),
- shift.eq(1),
- If(counter.value == header_words-2,
- NextState("COPY")
- )
- )
- )
- no_payload = Signal()
- self.sync += \
- If(fsm.before_entering("COPY"),
- source.sop.eq(1),
- no_payload.eq(sink.eop)
- ).Elif(source.stb & source.ack,
- source.sop.eq(0)
- )
- self.comb += [
- source.eop.eq(sink.eop | no_payload),
- source.data.eq(sink.data),
- source.error.eq(sink.error),
- _decode_header(header_type, self.header, source)
- ]
- fsm.act("COPY",
- sink.ack.eq(source.ack),
- source.stb.eq(sink.stb | no_payload),
- If(source.stb & source.ack & source.eop,
- NextState("IDLE")
- )
- )
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ counter.reset.eq(1),
+ If(sink.stb,
+ shift.eq(1),
+ NextState(idle_next_state)
+ )
+ )
+ if header_words != 1:
+ fsm.act("RECEIVE_HEADER",
+ sink.ack.eq(1),
+ If(sink.stb,
+ counter.ce.eq(1),
+ shift.eq(1),
+ If(counter.value == header_words-2,
+ NextState("COPY")
+ )
+ )
+ )
+ no_payload = Signal()
+ self.sync += \
+ If(fsm.before_entering("COPY"),
+ source.sop.eq(1),
+ no_payload.eq(sink.eop)
+ ).Elif(source.stb & source.ack,
+ source.sop.eq(0)
+ )
+ self.comb += [
+ source.eop.eq(sink.eop | no_payload),
+ source.data.eq(sink.data),
+ source.error.eq(sink.error),
+ _decode_header(header_type, self.header, source)
+ ]
+ fsm.act("COPY",
+ sink.ack.eq(source.ack),
+ source.stb.eq(sink.stb | no_payload),
+ If(source.stb & source.ack & source.eop,
+ NextState("IDLE")
+ )
+ )
from migen.genlib.record import *
class Dispatcher(Module):
- def __init__(self, source, sinks, one_hot=False):
- if len(sinks) == 0:
- self.sel = Signal()
- elif len(sinks) == 1:
- self.comb += Record.connect(source, sinks.pop())
- self.sel = Signal()
- else:
- if one_hot:
- self.sel = Signal(len(sinks))
- else:
- self.sel = Signal(max=len(sinks))
- ###
- sop = Signal()
- self.comb += sop.eq(source.stb & source.sop)
- sel = Signal(flen(self.sel))
- sel_r = Signal(flen(self.sel))
- self.sync += \
- If(sop,
- sel_r.eq(self.sel)
- )
- self.comb += \
- If(sop,
- sel.eq(self.sel)
- ).Else(
- sel.eq(sel_r)
- )
- cases = {}
- for i, sink in enumerate(sinks):
- if one_hot:
- idx = 2**i
- else:
- idx = i
- cases[idx] = [Record.connect(source, sink)]
- cases["default"] = [source.ack.eq(1)]
- self.comb += Case(sel, cases)
+ def __init__(self, source, sinks, one_hot=False):
+ if len(sinks) == 0:
+ self.sel = Signal()
+ elif len(sinks) == 1:
+ self.comb += Record.connect(source, sinks.pop())
+ self.sel = Signal()
+ else:
+ if one_hot:
+ self.sel = Signal(len(sinks))
+ else:
+ self.sel = Signal(max=len(sinks))
+ ###
+ sop = Signal()
+ self.comb += sop.eq(source.stb & source.sop)
+ sel = Signal(flen(self.sel))
+ sel_r = Signal(flen(self.sel))
+ self.sync += \
+ If(sop,
+ sel_r.eq(self.sel)
+ )
+ self.comb += \
+ If(sop,
+ sel.eq(self.sel)
+ ).Else(
+ sel.eq(sel_r)
+ )
+ cases = {}
+ for i, sink in enumerate(sinks):
+ if one_hot:
+ idx = 2**i
+ else:
+ idx = i
+ cases[idx] = [Record.connect(source, sink)]
+ cases["default"] = [source.ack.eq(1)]
+ self.comb += Case(sel, cases)
from misoclib.com.liteeth.generic import *
def _encode_header(h_dict, h_signal, obj):
- r = []
- for k, v in sorted(h_dict.items()):
- start = v.byte*8+v.offset
- end = start+v.width
- r.append(h_signal[start:end].eq(reverse_bytes(getattr(obj, k))))
- return r
+ r = []
+ for k, v in sorted(h_dict.items()):
+ start = v.byte*8+v.offset
+ end = start+v.width
+ r.append(h_signal[start:end].eq(reverse_bytes(getattr(obj, k))))
+ return r
class LiteEthPacketizer(Module):
- def __init__(self, sink_description, source_description, header_type, header_length):
- self.sink = sink = Sink(sink_description)
- self.source = source = Source(source_description)
- self.header = Signal(header_length*8)
- ###
- dw = flen(self.sink.data)
+ def __init__(self, sink_description, source_description, header_type, header_length):
+ self.sink = sink = Sink(sink_description)
+ self.source = source = Source(source_description)
+ self.header = Signal(header_length*8)
+ ###
+ dw = flen(self.sink.data)
- header_reg = Signal(header_length*8)
- header_words = (header_length*8)//dw
- load = Signal()
- shift = Signal()
- counter = Counter(max=max(header_words, 2))
- self.submodules += counter
+ header_reg = Signal(header_length*8)
+ header_words = (header_length*8)//dw
+ load = Signal()
+ shift = Signal()
+ counter = Counter(max=max(header_words, 2))
+ self.submodules += counter
- self.comb += _encode_header(header_type, self.header, sink)
- if header_words == 1:
- self.sync += [
- If(load,
- header_reg.eq(self.header)
- )
- ]
- else:
- self.sync += [
- If(load,
- header_reg.eq(self.header)
- ).Elif(shift,
- header_reg.eq(Cat(header_reg[dw:], Signal(dw)))
- )
- ]
+ self.comb += _encode_header(header_type, self.header, sink)
+ if header_words == 1:
+ self.sync += [
+ If(load,
+ header_reg.eq(self.header)
+ )
+ ]
+ else:
+ self.sync += [
+ If(load,
+ header_reg.eq(self.header)
+ ).Elif(shift,
+ header_reg.eq(Cat(header_reg[dw:], Signal(dw)))
+ )
+ ]
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
- if header_words == 1:
- idle_next_state = "COPY"
- else:
- idle_next_state = "SEND_HEADER"
+ if header_words == 1:
+ idle_next_state = "COPY"
+ else:
+ idle_next_state = "SEND_HEADER"
- fsm.act("IDLE",
- sink.ack.eq(1),
- counter.reset.eq(1),
- If(sink.stb & sink.sop,
- sink.ack.eq(0),
- source.stb.eq(1),
- source.sop.eq(1),
- source.eop.eq(0),
- source.data.eq(self.header[:dw]),
- If(source.stb & source.ack,
- load.eq(1),
- NextState(idle_next_state)
- )
- )
- )
- if header_words != 1:
- fsm.act("SEND_HEADER",
- source.stb.eq(1),
- source.sop.eq(0),
- source.eop.eq(0),
- source.data.eq(header_reg[dw:2*dw]),
- If(source.stb & source.ack,
- shift.eq(1),
- counter.ce.eq(1),
- If(counter.value == header_words-2,
- NextState("COPY")
- )
- )
- )
- fsm.act("COPY",
- source.stb.eq(sink.stb),
- source.sop.eq(0),
- source.eop.eq(sink.eop),
- source.data.eq(sink.data),
- source.error.eq(sink.error),
- If(source.stb & source.ack,
- sink.ack.eq(1),
- If(source.eop,
- NextState("IDLE")
- )
- )
- )
+ fsm.act("IDLE",
+ sink.ack.eq(1),
+ counter.reset.eq(1),
+ If(sink.stb & sink.sop,
+ sink.ack.eq(0),
+ source.stb.eq(1),
+ source.sop.eq(1),
+ source.eop.eq(0),
+ source.data.eq(self.header[:dw]),
+ If(source.stb & source.ack,
+ load.eq(1),
+ NextState(idle_next_state)
+ )
+ )
+ )
+ if header_words != 1:
+ fsm.act("SEND_HEADER",
+ source.stb.eq(1),
+ source.sop.eq(0),
+ source.eop.eq(0),
+ source.data.eq(header_reg[dw:2*dw]),
+ If(source.stb & source.ack,
+ shift.eq(1),
+ counter.ce.eq(1),
+ If(counter.value == header_words-2,
+ NextState("COPY")
+ )
+ )
+ )
+ fsm.act("COPY",
+ source.stb.eq(sink.stb),
+ source.sop.eq(0),
+ source.eop.eq(sink.eop),
+ source.data.eq(sink.data),
+ source.error.eq(sink.error),
+ If(source.stb & source.ack,
+ sink.ack.eq(1),
+ If(source.eop,
+ NextState("IDLE")
+ )
+ )
+ )
from misoclib.com.liteeth.mac.frontend.wishbone import LiteEthMACWishboneInterface
class LiteEthMAC(Module, AutoCSR):
- def __init__(self, phy, dw, interface="crossbar", endianness="big",
- with_hw_preamble_crc=True):
- self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_hw_preamble_crc)
- self.csrs = []
- if interface == "crossbar":
- self.submodules.crossbar = LiteEthMACCrossbar()
- self.submodules.packetizer = LiteEthMACPacketizer()
- self.submodules.depacketizer = LiteEthMACDepacketizer()
- self.comb += [
- Record.connect(self.crossbar.master.source, self.packetizer.sink),
- Record.connect(self.packetizer.source, self.core.sink),
- Record.connect(self.core.source, self.depacketizer.sink),
- Record.connect(self.depacketizer.source, self.crossbar.master.sink)
- ]
- elif interface == "wishbone":
- self.submodules.interface = LiteEthMACWishboneInterface(dw, 2, 2)
- self.comb += Port.connect(self.interface, self.core)
- self.ev, self.bus = self.interface.sram.ev, self.interface.bus
- self.csrs = self.interface.get_csrs() + self.core.get_csrs()
- elif interface == "dma":
- raise NotImplementedError
- else:
- raise ValueError(interface + " not supported by LiteEthMac!")
+ def __init__(self, phy, dw, interface="crossbar", endianness="big",
+ with_hw_preamble_crc=True):
+ self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_hw_preamble_crc)
+ self.csrs = []
+ if interface == "crossbar":
+ self.submodules.crossbar = LiteEthMACCrossbar()
+ self.submodules.packetizer = LiteEthMACPacketizer()
+ self.submodules.depacketizer = LiteEthMACDepacketizer()
+ self.comb += [
+ Record.connect(self.crossbar.master.source, self.packetizer.sink),
+ Record.connect(self.packetizer.source, self.core.sink),
+ Record.connect(self.core.source, self.depacketizer.sink),
+ Record.connect(self.depacketizer.source, self.crossbar.master.sink)
+ ]
+ elif interface == "wishbone":
+ self.submodules.interface = LiteEthMACWishboneInterface(dw, 2, 2)
+ self.comb += Port.connect(self.interface, self.core)
+ self.ev, self.bus = self.interface.sram.ev, self.interface.bus
+ self.csrs = self.interface.get_csrs() + self.core.get_csrs()
+ elif interface == "dma":
+ raise NotImplementedError
+ else:
+ raise ValueError(interface + " not supported by LiteEthMac!")
- def get_csrs(self):
- return self.csrs
+ def get_csrs(self):
+ return self.csrs
from misoclib.com.liteeth.generic.crossbar import LiteEthCrossbar
class LiteEthMACDepacketizer(LiteEthDepacketizer):
- def __init__(self):
- LiteEthDepacketizer.__init__(self,
- eth_phy_description(8),
- eth_mac_description(8),
- mac_header,
- mac_header_len)
+ def __init__(self):
+ LiteEthDepacketizer.__init__(self,
+ eth_phy_description(8),
+ eth_mac_description(8),
+ mac_header,
+ mac_header_len)
class LiteEthMACPacketizer(LiteEthPacketizer):
- def __init__(self):
- LiteEthPacketizer.__init__(self,
- eth_mac_description(8),
- eth_phy_description(8),
- mac_header,
- mac_header_len)
+ def __init__(self):
+ LiteEthPacketizer.__init__(self,
+ eth_mac_description(8),
+ eth_phy_description(8),
+ mac_header,
+ mac_header_len)
class LiteEthMACMasterPort:
- def __init__(self, dw):
- self.source = Source(eth_mac_description(dw))
- self.sink = Sink(eth_mac_description(dw))
+ def __init__(self, dw):
+ self.source = Source(eth_mac_description(dw))
+ self.sink = Sink(eth_mac_description(dw))
class LiteEthMACSlavePort:
- def __init__(self, dw):
- self.sink = Sink(eth_mac_description(dw))
- self.source = Source(eth_mac_description(dw))
+ def __init__(self, dw):
+ self.sink = Sink(eth_mac_description(dw))
+ self.source = Source(eth_mac_description(dw))
class LiteEthMACUserPort(LiteEthMACSlavePort):
- def __init__(self, dw):
- LiteEthMACSlavePort.__init__(self, dw)
+ def __init__(self, dw):
+ LiteEthMACSlavePort.__init__(self, dw)
class LiteEthMACCrossbar(LiteEthCrossbar):
- def __init__(self):
- LiteEthCrossbar.__init__(self, LiteEthMACMasterPort, "ethernet_type")
+ def __init__(self):
+ LiteEthCrossbar.__init__(self, LiteEthMACMasterPort, "ethernet_type")
- def get_port(self, ethernet_type):
- port = LiteEthMACUserPort(8)
- if ethernet_type in self.users.keys():
- raise ValueError("Ethernet type {0:#x} already assigned".format(ethernet_type))
- self.users[ethernet_type] = port
- return port
+ def get_port(self, ethernet_type):
+ port = LiteEthMACUserPort(8)
+ if ethernet_type in self.users.keys():
+ raise ValueError("Ethernet type {0:#x} already assigned".format(ethernet_type))
+ self.users[ethernet_type] = port
+ return port
from misoclib.com.liteeth.phy.sim import LiteEthPHYSim
class LiteEthMACCore(Module, AutoCSR):
- def __init__(self, phy, dw, endianness="big",
- with_preamble_crc=True,
- with_padding=True):
- if dw < phy.dw:
- raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw))
-
- rx_pipeline = [phy]
- tx_pipeline = [phy]
-
- # Interpacket gap
- tx_gap_inserter = gap.LiteEthMACGap(phy.dw)
- rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True)
- self.submodules += RenameClockDomains(tx_gap_inserter, "eth_tx")
- self.submodules += RenameClockDomains(rx_gap_checker, "eth_rx")
-
- tx_pipeline += [tx_gap_inserter]
- rx_pipeline += [rx_gap_checker]
-
- # Preamble / CRC
- if isinstance(phy, LiteEthPHYSim):
- # In simulation, avoid CRC/Preamble to enable direct connection
- # to the Ethernet tap.
- self._preamble_crc = CSRStatus(reset=1)
- elif with_preamble_crc:
- self._preamble_crc = CSRStatus(reset=1)
- # Preamble insert/check
- preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
- preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
- self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
- self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
-
- # CRC insert/check
- crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw))
- crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw))
- self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
- self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
-
- tx_pipeline += [preamble_inserter, crc32_inserter]
- rx_pipeline += [preamble_checker, crc32_checker]
-
- # Padding
- if with_padding:
- padding_inserter = padding.LiteEthMACPaddingInserter(phy.dw, 60)
- padding_checker = padding.LiteEthMACPaddingChecker(phy.dw, 60)
- self.submodules += RenameClockDomains(padding_inserter, "eth_tx")
- self.submodules += RenameClockDomains(padding_checker, "eth_rx")
-
- tx_pipeline += [padding_inserter]
- rx_pipeline += [padding_checker]
-
- # Delimiters
- if dw != 8:
- tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
- rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
- self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
- self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
-
- tx_pipeline += [tx_last_be]
- rx_pipeline += [rx_last_be]
-
- # Converters
- if dw != phy.dw:
- reverse = endianness == "big"
- tx_converter = Converter(eth_phy_description(dw), eth_phy_description(phy.dw), reverse=reverse)
- rx_converter = Converter(eth_phy_description(phy.dw), eth_phy_description(dw), reverse=reverse)
- self.submodules += RenameClockDomains(tx_converter, "eth_tx")
- self.submodules += RenameClockDomains(rx_converter, "eth_rx")
-
- tx_pipeline += [tx_converter]
- rx_pipeline += [rx_converter]
-
- # Cross Domain Crossing
- tx_cdc = AsyncFIFO(eth_phy_description(dw), 64)
- rx_cdc = AsyncFIFO(eth_phy_description(dw), 64)
- self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
- self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
-
- tx_pipeline += [tx_cdc]
- rx_pipeline += [rx_cdc]
-
- # Graph
- self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
- self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
-
- self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
+ def __init__(self, phy, dw, endianness="big",
+ with_preamble_crc=True,
+ with_padding=True):
+ if dw < phy.dw:
+ raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw))
+
+ rx_pipeline = [phy]
+ tx_pipeline = [phy]
+
+ # Interpacket gap
+ tx_gap_inserter = gap.LiteEthMACGap(phy.dw)
+ rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True)
+ self.submodules += RenameClockDomains(tx_gap_inserter, "eth_tx")
+ self.submodules += RenameClockDomains(rx_gap_checker, "eth_rx")
+
+ tx_pipeline += [tx_gap_inserter]
+ rx_pipeline += [rx_gap_checker]
+
+ # Preamble / CRC
+ if isinstance(phy, LiteEthPHYSim):
+ # In simulation, avoid CRC/Preamble to enable direct connection
+ # to the Ethernet tap.
+ self._preamble_crc = CSRStatus(reset=1)
+ elif with_preamble_crc:
+ self._preamble_crc = CSRStatus(reset=1)
+ # Preamble insert/check
+ preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
+ preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
+ self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
+ self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
+
+ # CRC insert/check
+ crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw))
+ crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw))
+ self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
+ self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
+
+ tx_pipeline += [preamble_inserter, crc32_inserter]
+ rx_pipeline += [preamble_checker, crc32_checker]
+
+ # Padding
+ if with_padding:
+ padding_inserter = padding.LiteEthMACPaddingInserter(phy.dw, 60)
+ padding_checker = padding.LiteEthMACPaddingChecker(phy.dw, 60)
+ self.submodules += RenameClockDomains(padding_inserter, "eth_tx")
+ self.submodules += RenameClockDomains(padding_checker, "eth_rx")
+
+ tx_pipeline += [padding_inserter]
+ rx_pipeline += [padding_checker]
+
+ # Delimiters
+ if dw != 8:
+ tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
+ rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
+ self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
+ self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
+
+ tx_pipeline += [tx_last_be]
+ rx_pipeline += [rx_last_be]
+
+ # Converters
+ if dw != phy.dw:
+ reverse = endianness == "big"
+ tx_converter = Converter(eth_phy_description(dw), eth_phy_description(phy.dw), reverse=reverse)
+ rx_converter = Converter(eth_phy_description(phy.dw), eth_phy_description(dw), reverse=reverse)
+ self.submodules += RenameClockDomains(tx_converter, "eth_tx")
+ self.submodules += RenameClockDomains(rx_converter, "eth_rx")
+
+ tx_pipeline += [tx_converter]
+ rx_pipeline += [rx_converter]
+
+ # Cross Domain Crossing
+ tx_cdc = AsyncFIFO(eth_phy_description(dw), 64)
+ rx_cdc = AsyncFIFO(eth_phy_description(dw), 64)
+ self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
+ self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
+
+ tx_pipeline += [tx_cdc]
+ rx_pipeline += [rx_cdc]
+
+ # Graph
+ self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
+ self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
+
+ self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
from misoclib.com.liteeth.generic import *
class LiteEthMACCRCEngine(Module):
- """Cyclic Redundancy Check Engine
-
- Compute next CRC value from last CRC value and data input using
- an optimized asynchronous LFSR.
-
- Parameters
- ----------
- data_width : int
- Width of the data bus.
- width : int
- Width of the CRC.
- polynom : int
- Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
-
- Attributes
- ----------
- data : in
- Data input.
- last : in
- last CRC value.
- next :
- next CRC value.
- """
- def __init__(self, data_width, width, polynom):
- self.data = Signal(data_width)
- self.last = Signal(width)
- self.next = Signal(width)
-
- ###
-
- def _optimize_eq(l):
- """
- Replace even numbers of XORs in the equation
- with an equivalent XOR
- """
- d = OrderedDict()
- for e in l:
- if e in d:
- d[e] += 1
- else:
- d[e] = 1
- r = []
- for key, value in d.items():
- if value%2 != 0:
- r.append(key)
- return r
-
- # compute and optimize CRC's LFSR
- curval = [[("state", i)] for i in range(width)]
- for i in range(data_width):
- feedback = curval.pop() + [("din", i)]
- for j in range(width-1):
- if (polynom & (1<<(j+1))):
- curval[j] += feedback
- curval[j] = _optimize_eq(curval[j])
- curval.insert(0, feedback)
-
- # implement logic
- for i in range(width):
- xors = []
- for t, n in curval[i]:
- if t == "state":
- xors += [self.last[n]]
- elif t == "din":
- xors += [self.data[n]]
- self.comb += self.next[i].eq(optree("^", xors))
+ """Cyclic Redundancy Check Engine
+
+ Compute next CRC value from last CRC value and data input using
+ an optimized asynchronous LFSR.
+
+ Parameters
+ ----------
+ data_width : int
+ Width of the data bus.
+ width : int
+ Width of the CRC.
+ polynom : int
+ Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
+
+ Attributes
+ ----------
+ data : in
+ Data input.
+ last : in
+ last CRC value.
+ next :
+ next CRC value.
+ """
+ def __init__(self, data_width, width, polynom):
+ self.data = Signal(data_width)
+ self.last = Signal(width)
+ self.next = Signal(width)
+
+ ###
+
+ def _optimize_eq(l):
+ """
+ Replace even numbers of XORs in the equation
+ with an equivalent XOR
+ """
+ d = OrderedDict()
+ for e in l:
+ if e in d:
+ d[e] += 1
+ else:
+ d[e] = 1
+ r = []
+ for key, value in d.items():
+ if value%2 != 0:
+ r.append(key)
+ return r
+
+ # compute and optimize CRC's LFSR
+ curval = [[("state", i)] for i in range(width)]
+ for i in range(data_width):
+ feedback = curval.pop() + [("din", i)]
+ for j in range(width-1):
+ if (polynom & (1<<(j+1))):
+ curval[j] += feedback
+ curval[j] = _optimize_eq(curval[j])
+ curval.insert(0, feedback)
+
+ # implement logic
+ for i in range(width):
+ xors = []
+ for t, n in curval[i]:
+ if t == "state":
+ xors += [self.last[n]]
+ elif t == "din":
+ xors += [self.data[n]]
+ self.comb += self.next[i].eq(optree("^", xors))
@DecorateModule(InsertReset)
@DecorateModule(InsertCE)
class LiteEthMACCRC32(Module):
- """IEEE 802.3 CRC
-
- Implement an IEEE 802.3 CRC generator/checker.
-
- Parameters
- ----------
- data_width : int
- Width of the data bus.
-
- Attributes
- ----------
- d : in
- Data input.
- value : out
- CRC value (used for generator).
- error : out
- CRC error (used for checker).
- """
- width = 32
- polynom = 0x04C11DB7
- init = 2**width-1
- check = 0xC704DD7B
- def __init__(self, data_width):
- self.data = Signal(data_width)
- self.value = Signal(self.width)
- self.error = Signal()
-
- ###
-
- self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom)
- reg = Signal(self.width, reset=self.init)
- self.sync += reg.eq(self.engine.next)
- self.comb += [
- self.engine.data.eq(self.data),
- self.engine.last.eq(reg),
-
- self.value.eq(~reg[::-1]),
- self.error.eq(self.engine.next != self.check)
- ]
+ """IEEE 802.3 CRC
+
+ Implement an IEEE 802.3 CRC generator/checker.
+
+ Parameters
+ ----------
+ data_width : int
+ Width of the data bus.
+
+ Attributes
+ ----------
+ d : in
+ Data input.
+ value : out
+ CRC value (used for generator).
+ error : out
+ CRC error (used for checker).
+ """
+ width = 32
+ polynom = 0x04C11DB7
+ init = 2**width-1
+ check = 0xC704DD7B
+ def __init__(self, data_width):
+ self.data = Signal(data_width)
+ self.value = Signal(self.width)
+ self.error = Signal()
+
+ ###
+
+ self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom)
+ reg = Signal(self.width, reset=self.init)
+ self.sync += reg.eq(self.engine.next)
+ self.comb += [
+ self.engine.data.eq(self.data),
+ self.engine.last.eq(reg),
+
+ self.value.eq(~reg[::-1]),
+ self.error.eq(self.engine.next != self.check)
+ ]
class LiteEthMACCRCInserter(Module):
- """CRC Inserter
-
- Append a CRC at the end of each packet.
-
- Parameters
- ----------
- description : description
- description of the dataflow.
-
- Attributes
- ----------
- sink : in
- Packets input without CRC.
- source : out
- Packets output with CRC.
- """
- def __init__(self, crc_class, description):
- self.sink = sink = Sink(description)
- self.source = source = Source(description)
- self.busy = Signal()
-
- ###
-
- dw = flen(sink.data)
- crc = crc_class(dw)
- fsm = FSM(reset_state="IDLE")
- self.submodules += crc, fsm
-
- fsm.act("IDLE",
- crc.reset.eq(1),
- sink.ack.eq(1),
- If(sink.stb & sink.sop,
- sink.ack.eq(0),
- NextState("COPY"),
- )
- )
- fsm.act("COPY",
- crc.ce.eq(sink.stb & source.ack),
- crc.data.eq(sink.data),
- Record.connect(sink, source),
- source.eop.eq(0),
- If(sink.stb & sink.eop & source.ack,
- NextState("INSERT"),
- )
- )
- ratio = crc.width//dw
- if ratio > 1:
- cnt = Signal(max=ratio, reset=ratio-1)
- cnt_done = Signal()
- fsm.act("INSERT",
- source.stb.eq(1),
- chooser(crc.value, cnt, source.data, reverse=True),
- If(cnt_done,
- source.eop.eq(1),
- If(source.ack, NextState("IDLE"))
- )
- )
- self.comb += cnt_done.eq(cnt == 0)
- self.sync += \
- If(fsm.ongoing("IDLE"),
- cnt.eq(cnt.reset)
- ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
- cnt.eq(cnt - source.ack)
- )
- else:
- fsm.act("INSERT",
- source.stb.eq(1),
- source.eop.eq(1),
- source.data.eq(crc.value),
- If(source.ack, NextState("IDLE"))
- )
- self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+ """CRC Inserter
+
+ Append a CRC at the end of each packet.
+
+ Parameters
+ ----------
+ description : description
+ description of the dataflow.
+
+ Attributes
+ ----------
+ sink : in
+ Packets input without CRC.
+ source : out
+ Packets output with CRC.
+ """
+ def __init__(self, crc_class, description):
+ self.sink = sink = Sink(description)
+ self.source = source = Source(description)
+ self.busy = Signal()
+
+ ###
+
+ dw = flen(sink.data)
+ crc = crc_class(dw)
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += crc, fsm
+
+ fsm.act("IDLE",
+ crc.reset.eq(1),
+ sink.ack.eq(1),
+ If(sink.stb & sink.sop,
+ sink.ack.eq(0),
+ NextState("COPY"),
+ )
+ )
+ fsm.act("COPY",
+ crc.ce.eq(sink.stb & source.ack),
+ crc.data.eq(sink.data),
+ Record.connect(sink, source),
+ source.eop.eq(0),
+ If(sink.stb & sink.eop & source.ack,
+ NextState("INSERT"),
+ )
+ )
+ ratio = crc.width//dw
+ if ratio > 1:
+ cnt = Signal(max=ratio, reset=ratio-1)
+ cnt_done = Signal()
+ fsm.act("INSERT",
+ source.stb.eq(1),
+ chooser(crc.value, cnt, source.data, reverse=True),
+ If(cnt_done,
+ source.eop.eq(1),
+ If(source.ack, NextState("IDLE"))
+ )
+ )
+ self.comb += cnt_done.eq(cnt == 0)
+ self.sync += \
+ If(fsm.ongoing("IDLE"),
+ cnt.eq(cnt.reset)
+ ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
+ cnt.eq(cnt - source.ack)
+ )
+ else:
+ fsm.act("INSERT",
+ source.stb.eq(1),
+ source.eop.eq(1),
+ source.data.eq(crc.value),
+ If(source.ack, NextState("IDLE"))
+ )
+ self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
class LiteEthMACCRC32Inserter(LiteEthMACCRCInserter):
- def __init__(self, description):
- LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, description)
+ def __init__(self, description):
+ LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, description)
class LiteEthMACCRCChecker(Module):
- """CRC Checker
-
- Check CRC at the end of each packet.
-
- Parameters
- ----------
- description : description
- description of the dataflow.
-
- Attributes
- ----------
- sink : in
- Packets input with CRC.
- source : out
- Packets output without CRC and "error" set to 0
- on eop when CRC OK / set to 1 when CRC KO.
- """
- def __init__(self, crc_class, description):
- self.sink = sink = Sink(description)
- self.source = source = Source(description)
- self.busy = Signal()
-
- ###
-
- dw = flen(sink.data)
- crc = crc_class(dw)
- self.submodules += crc
- ratio = crc.width//dw
-
- error = Signal()
- fifo = InsertReset(SyncFIFO(description, ratio + 1))
- self.submodules += fifo
-
- fsm = FSM(reset_state="RESET")
- self.submodules += fsm
-
- fifo_in = Signal()
- fifo_out = Signal()
- fifo_full = Signal()
-
- self.comb += [
- fifo_full.eq(fifo.fifo.level == ratio),
- fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
- fifo_out.eq(source.stb & source.ack),
-
- Record.connect(sink, fifo.sink),
- fifo.sink.stb.eq(fifo_in),
- self.sink.ack.eq(fifo_in),
-
- source.stb.eq(sink.stb & fifo_full),
- source.sop.eq(fifo.source.sop),
- source.eop.eq(sink.eop),
- fifo.source.ack.eq(fifo_out),
- source.payload.eq(fifo.source.payload),
-
- source.error.eq(sink.error | crc.error),
- ]
-
- fsm.act("RESET",
- crc.reset.eq(1),
- fifo.reset.eq(1),
- NextState("IDLE"),
- )
- fsm.act("IDLE",
- crc.data.eq(sink.data),
- If(sink.stb & sink.sop & sink.ack,
- crc.ce.eq(1),
- NextState("COPY")
- )
- )
- fsm.act("COPY",
- crc.data.eq(sink.data),
- If(sink.stb & sink.ack,
- crc.ce.eq(1),
- If(sink.eop,
- NextState("RESET")
- )
- )
- )
- self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+ """CRC Checker
+
+ Check CRC at the end of each packet.
+
+ Parameters
+ ----------
+ description : description
+ description of the dataflow.
+
+ Attributes
+ ----------
+ sink : in
+ Packets input with CRC.
+ source : out
+ Packets output without CRC and "error" set to 0
+ on eop when CRC OK / set to 1 when CRC KO.
+ """
+ def __init__(self, crc_class, description):
+ self.sink = sink = Sink(description)
+ self.source = source = Source(description)
+ self.busy = Signal()
+
+ ###
+
+ dw = flen(sink.data)
+ crc = crc_class(dw)
+ self.submodules += crc
+ ratio = crc.width//dw
+
+ error = Signal()
+ fifo = InsertReset(SyncFIFO(description, ratio + 1))
+ self.submodules += fifo
+
+ fsm = FSM(reset_state="RESET")
+ self.submodules += fsm
+
+ fifo_in = Signal()
+ fifo_out = Signal()
+ fifo_full = Signal()
+
+ self.comb += [
+ fifo_full.eq(fifo.fifo.level == ratio),
+ fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
+ fifo_out.eq(source.stb & source.ack),
+
+ Record.connect(sink, fifo.sink),
+ fifo.sink.stb.eq(fifo_in),
+ self.sink.ack.eq(fifo_in),
+
+ source.stb.eq(sink.stb & fifo_full),
+ source.sop.eq(fifo.source.sop),
+ source.eop.eq(sink.eop),
+ fifo.source.ack.eq(fifo_out),
+ source.payload.eq(fifo.source.payload),
+
+ source.error.eq(sink.error | crc.error),
+ ]
+
+ fsm.act("RESET",
+ crc.reset.eq(1),
+ fifo.reset.eq(1),
+ NextState("IDLE"),
+ )
+ fsm.act("IDLE",
+ crc.data.eq(sink.data),
+ If(sink.stb & sink.sop & sink.ack,
+ crc.ce.eq(1),
+ NextState("COPY")
+ )
+ )
+ fsm.act("COPY",
+ crc.data.eq(sink.data),
+ If(sink.stb & sink.ack,
+ crc.ce.eq(1),
+ If(sink.eop,
+ NextState("RESET")
+ )
+ )
+ )
+ self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
class LiteEthMACCRC32Checker(LiteEthMACCRCChecker):
- def __init__(self, description):
- LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, description)
+ def __init__(self, description):
+ LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, description)
from misoclib.com.liteeth.generic import *
class LiteEthMACGap(Module):
- def __init__(self, dw, ack_on_gap=False):
- self.sink = sink = Sink(eth_phy_description(dw))
- self.source = source = Source(eth_phy_description(dw))
- ###
- gap = math.ceil(eth_interpacket_gap/(dw//8))
- self.submodules.counter = counter = Counter(max=gap)
+ def __init__(self, dw, ack_on_gap=False):
+ self.sink = sink = Sink(eth_phy_description(dw))
+ self.source = source = Source(eth_phy_description(dw))
+ ###
+ gap = math.ceil(eth_interpacket_gap/(dw//8))
+ self.submodules.counter = counter = Counter(max=gap)
- self.submodules.fsm = fsm = FSM(reset_state="COPY")
- fsm.act("COPY",
- counter.reset.eq(1),
- Record.connect(sink, source),
- If(sink.stb & sink.eop & sink.ack,
- NextState("GAP")
- )
- )
- fsm.act("GAP",
- counter.ce.eq(1),
- sink.ack.eq(int(ack_on_gap)),
- If(counter.value == (gap-1),
- NextState("COPY")
- )
- )
+ self.submodules.fsm = fsm = FSM(reset_state="COPY")
+ fsm.act("COPY",
+ counter.reset.eq(1),
+ Record.connect(sink, source),
+ If(sink.stb & sink.eop & sink.ack,
+ NextState("GAP")
+ )
+ )
+ fsm.act("GAP",
+ counter.ce.eq(1),
+ sink.ack.eq(int(ack_on_gap)),
+ If(counter.value == (gap-1),
+ NextState("COPY")
+ )
+ )
from misoclib.com.liteeth.generic import *
class LiteEthMACTXLastBE(Module):
- def __init__(self, dw):
- self.sink = sink = Sink(eth_phy_description(dw))
- self.source = source = Source(eth_phy_description(dw))
- ###
- ongoing = Signal()
- self.sync += \
- If(sink.stb & sink.ack,
- If(sink.sop,
- ongoing.eq(1)
- ).Elif(sink.last_be,
- ongoing.eq(0)
- )
- )
- self.comb += [
- source.stb.eq(sink.stb & (sink.sop | ongoing)),
- source.sop.eq(sink.sop),
- source.eop.eq(sink.last_be),
- source.data.eq(sink.data),
- sink.ack.eq(source.ack)
- ]
+ def __init__(self, dw):
+ self.sink = sink = Sink(eth_phy_description(dw))
+ self.source = source = Source(eth_phy_description(dw))
+ ###
+ ongoing = Signal()
+ self.sync += \
+ If(sink.stb & sink.ack,
+ If(sink.sop,
+ ongoing.eq(1)
+ ).Elif(sink.last_be,
+ ongoing.eq(0)
+ )
+ )
+ self.comb += [
+ source.stb.eq(sink.stb & (sink.sop | ongoing)),
+ source.sop.eq(sink.sop),
+ source.eop.eq(sink.last_be),
+ source.data.eq(sink.data),
+ sink.ack.eq(source.ack)
+ ]
class LiteEthMACRXLastBE(Module):
- def __init__(self, dw):
- self.sink = sink = Sink(eth_phy_description(dw))
- self.source = source = Source(eth_phy_description(dw))
- ###
- self.comb += [
- source.stb.eq(sink.stb),
- source.sop.eq(sink.sop),
- source.eop.eq(sink.eop),
- source.data.eq(sink.data),
- source.last_be.eq(sink.eop),
- sink.ack.eq(source.ack)
- ]
+ def __init__(self, dw):
+ self.sink = sink = Sink(eth_phy_description(dw))
+ self.source = source = Source(eth_phy_description(dw))
+ ###
+ self.comb += [
+ source.stb.eq(sink.stb),
+ source.sop.eq(sink.sop),
+ source.eop.eq(sink.eop),
+ source.data.eq(sink.data),
+ source.last_be.eq(sink.eop),
+ sink.ack.eq(source.ack)
+ ]
from misoclib.com.liteeth.generic import *
class LiteEthMACPaddingInserter(Module):
- def __init__(self, dw, packet_min_length):
- self.sink = sink = Sink(eth_phy_description(dw))
- self.source = source = Source(eth_phy_description(dw))
- ###
- packet_min_data = math.ceil(packet_min_length/(dw/8))
+ def __init__(self, dw, packet_min_length):
+ self.sink = sink = Sink(eth_phy_description(dw))
+ self.source = source = Source(eth_phy_description(dw))
+ ###
+ packet_min_data = math.ceil(packet_min_length/(dw/8))
- self.submodules.counter = counter = Counter(max=eth_mtu)
+ self.submodules.counter = counter = Counter(max=eth_mtu)
- self.submodules.fsm = fsm = FSM(reset_state="COPY")
- fsm.act("COPY",
- counter.reset.eq(sink.stb & sink.sop),
- Record.connect(sink, source),
- If(sink.stb & sink.ack,
- counter.ce.eq(1),
- If(sink.eop,
- If(counter.value < packet_min_data,
- source.eop.eq(0),
- NextState("PADDING")
- )
- )
- )
- )
- fsm.act("PADDING",
- source.stb.eq(1),
- source.eop.eq(counter.value == packet_min_data),
- source.data.eq(0),
- If(source.ack,
- counter.ce.eq(1),
- If(source.eop,
- NextState("COPY")
- )
- )
- )
+ self.submodules.fsm = fsm = FSM(reset_state="COPY")
+ fsm.act("COPY",
+ counter.reset.eq(sink.stb & sink.sop),
+ Record.connect(sink, source),
+ If(sink.stb & sink.ack,
+ counter.ce.eq(1),
+ If(sink.eop,
+ If(counter.value < packet_min_data,
+ source.eop.eq(0),
+ NextState("PADDING")
+ )
+ )
+ )
+ )
+ fsm.act("PADDING",
+ source.stb.eq(1),
+ source.eop.eq(counter.value == packet_min_data),
+ source.data.eq(0),
+ If(source.ack,
+ counter.ce.eq(1),
+ If(source.eop,
+ NextState("COPY")
+ )
+ )
+ )
class LiteEthMACPaddingChecker(Module):
- def __init__(self, dw, packet_min_length):
- self.sink = sink = Sink(eth_phy_description(dw))
- self.source = source = Source(eth_phy_description(dw))
- ###
- # XXX see if we should drop the packet when
- # payload size < minimum ethernet payload size
- self.comb += Record.connect(sink, source)
+ def __init__(self, dw, packet_min_length):
+ self.sink = sink = Sink(eth_phy_description(dw))
+ self.source = source = Source(eth_phy_description(dw))
+ ###
+ # XXX see if we should drop the packet when
+ # payload size < minimum ethernet payload size
+ self.comb += Record.connect(sink, source)
from misoclib.com.liteeth.generic import *
class LiteEthMACPreambleInserter(Module):
- def __init__(self, dw):
- self.sink = Sink(eth_phy_description(dw))
- self.source = Source(eth_phy_description(dw))
-
- ###
-
- preamble = Signal(64, reset=eth_preamble)
- cnt_max = (64//dw)-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.data),
- 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"),
- )
- )
+ def __init__(self, dw):
+ self.sink = Sink(eth_phy_description(dw))
+ self.source = Source(eth_phy_description(dw))
+
+ ###
+
+ preamble = Signal(64, reset=eth_preamble)
+ cnt_max = (64//dw)-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.data),
+ 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 LiteEthMACPreambleChecker(Module):
- def __init__(self, dw):
- self.sink = Sink(eth_phy_description(dw))
- self.source = Source(eth_phy_description(dw))
-
- ###
-
- preamble = Signal(64, reset=eth_preamble)
- cnt_max = (64//dw) - 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(dw)
- match = Signal()
- self.comb += [
- chooser(preamble, cnt, ref),
- match.eq(self.sink.data == 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"),
- )
- )
+ def __init__(self, dw):
+ self.sink = Sink(eth_phy_description(dw))
+ self.source = Source(eth_phy_description(dw))
+
+ ###
+
+ preamble = Signal(64, reset=eth_preamble)
+ cnt_max = (64//dw) - 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(dw)
+ match = Signal()
+ self.comb += [
+ chooser(preamble, cnt, ref),
+ match.eq(self.sink.data == 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"),
+ )
+ )
from migen.bank.eventmanager import *
class LiteEthMACSRAMWriter(Module, AutoCSR):
- def __init__(self, dw, depth, nslots=2):
- self.sink = sink = Sink(eth_phy_description(dw))
- 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
- increment = Signal(3)
- self.comb += \
- If(sink.last_be[3],
- increment.eq(1)
- ).Elif(sink.last_be[2],
- increment.eq(2)
- ).Elif(sink.last_be[1],
- increment.eq(3)
- ).Else(
- increment.eq(4)
- )
- counter = Counter(lengthbits, increment=increment)
- self.submodules += counter
-
- # slot computation
- slot = Counter(slotbits)
- self.submodules += slot
-
- ongoing = 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",
- If(sink.stb & sink.sop,
- If(fifo.sink.ack,
- ongoing.eq(1),
- counter.ce.eq(1),
- NextState("WRITE")
- )
- )
- )
- fsm.act("WRITE",
- counter.ce.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",
- counter.reset.eq(1),
- NextState("IDLE")
- )
- self.comb += [
- fifo.sink.slot.eq(slot.value),
- fifo.sink.length.eq(counter.value)
- ]
- fsm.act("TERMINATE",
- counter.reset.eq(1),
- slot.ce.eq(1),
- fifo.sink.stb.eq(1),
- NextState("IDLE")
- )
- self.comb += [
- fifo.source.ack.eq(self.ev.available.clear),
- self.ev.available.trigger.eq(fifo.source.stb),
- self._slot.status.eq(fifo.source.slot),
- self._length.status.eq(fifo.source.length),
- ]
-
- # memory
- mems = [None]*nslots
- ports = [None]*nslots
- for n in range(nslots):
- mems[n] = Memory(dw, 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(counter.value[2:]),
- ports[n].dat_w.eq(sink.data),
- If(sink.stb & ongoing,
- ports[n].we.eq(0xf)
- )
- ]
- self.comb += Case(slot.value, cases)
+ def __init__(self, dw, depth, nslots=2):
+ self.sink = sink = Sink(eth_phy_description(dw))
+ 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
+ increment = Signal(3)
+ self.comb += \
+ If(sink.last_be[3],
+ increment.eq(1)
+ ).Elif(sink.last_be[2],
+ increment.eq(2)
+ ).Elif(sink.last_be[1],
+ increment.eq(3)
+ ).Else(
+ increment.eq(4)
+ )
+ counter = Counter(lengthbits, increment=increment)
+ self.submodules += counter
+
+ # slot computation
+ slot = Counter(slotbits)
+ self.submodules += slot
+
+ ongoing = 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",
+ If(sink.stb & sink.sop,
+ If(fifo.sink.ack,
+ ongoing.eq(1),
+ counter.ce.eq(1),
+ NextState("WRITE")
+ )
+ )
+ )
+ fsm.act("WRITE",
+ counter.ce.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",
+ counter.reset.eq(1),
+ NextState("IDLE")
+ )
+ self.comb += [
+ fifo.sink.slot.eq(slot.value),
+ fifo.sink.length.eq(counter.value)
+ ]
+ fsm.act("TERMINATE",
+ counter.reset.eq(1),
+ slot.ce.eq(1),
+ fifo.sink.stb.eq(1),
+ NextState("IDLE")
+ )
+ self.comb += [
+ fifo.source.ack.eq(self.ev.available.clear),
+ self.ev.available.trigger.eq(fifo.source.stb),
+ self._slot.status.eq(fifo.source.slot),
+ self._length.status.eq(fifo.source.length),
+ ]
+
+ # memory
+ mems = [None]*nslots
+ ports = [None]*nslots
+ for n in range(nslots):
+ mems[n] = Memory(dw, 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(counter.value[2:]),
+ ports[n].dat_w.eq(sink.data),
+ If(sink.stb & ongoing,
+ ports[n].we.eq(0xf)
+ )
+ ]
+ self.comb += Case(slot.value, cases)
class LiteEthMACSRAMReader(Module, AutoCSR):
- def __init__(self, dw, depth, nslots=2):
- self.source = source = Source(eth_phy_description(dw))
-
- 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.sink.stb.eq(self._start.re),
- fifo.sink.slot.eq(self._slot.storage),
- fifo.sink.length.eq(self._length.storage),
- self._ready.status.eq(fifo.sink.ack)
- ]
-
- # length computation
- self.submodules.counter = counter = Counter(lengthbits, increment=4)
-
- # fsm
- first = Signal()
- last = Signal()
- last_d = Signal()
-
- fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
-
- fsm.act("IDLE",
- counter.reset.eq(1),
- If(fifo.source.stb,
- NextState("CHECK")
- )
- )
- fsm.act("CHECK",
- If(~last_d,
- NextState("SEND"),
- ).Else(
- NextState("END"),
- )
- )
- length_lsb = fifo.source.length[0:2]
- self.comb += [
- 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)
- )
- )
- ]
- fsm.act("SEND",
- source.stb.eq(1),
- source.sop.eq(first),
- source.eop.eq(last),
- If(source.ack,
- counter.ce.eq(~last),
- NextState("CHECK")
- )
- )
- fsm.act("END",
- fifo.source.ack.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((counter.value + 4) >= fifo.source.length)
- self.sync += last_d.eq(last)
-
- # memory
- rd_slot = fifo.source.slot
-
- mems = [None]*nslots
- ports = [None]*nslots
- for n in range(nslots):
- mems[n] = Memory(dw, 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(counter.value[2:])
- cases[n] = [source.data.eq(port.dat_r)]
- self.comb += Case(rd_slot, cases)
+ def __init__(self, dw, depth, nslots=2):
+ self.source = source = Source(eth_phy_description(dw))
+
+ 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.sink.stb.eq(self._start.re),
+ fifo.sink.slot.eq(self._slot.storage),
+ fifo.sink.length.eq(self._length.storage),
+ self._ready.status.eq(fifo.sink.ack)
+ ]
+
+ # length computation
+ self.submodules.counter = counter = Counter(lengthbits, increment=4)
+
+ # fsm
+ first = Signal()
+ last = Signal()
+ last_d = Signal()
+
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+
+ fsm.act("IDLE",
+ counter.reset.eq(1),
+ If(fifo.source.stb,
+ NextState("CHECK")
+ )
+ )
+ fsm.act("CHECK",
+ If(~last_d,
+ NextState("SEND"),
+ ).Else(
+ NextState("END"),
+ )
+ )
+ length_lsb = fifo.source.length[0:2]
+ self.comb += [
+ 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)
+ )
+ )
+ ]
+ fsm.act("SEND",
+ source.stb.eq(1),
+ source.sop.eq(first),
+ source.eop.eq(last),
+ If(source.ack,
+ counter.ce.eq(~last),
+ NextState("CHECK")
+ )
+ )
+ fsm.act("END",
+ fifo.source.ack.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((counter.value + 4) >= fifo.source.length)
+ self.sync += last_d.eq(last)
+
+ # memory
+ rd_slot = fifo.source.slot
+
+ mems = [None]*nslots
+ ports = [None]*nslots
+ for n in range(nslots):
+ mems[n] = Memory(dw, 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(counter.value[2:])
+ cases[n] = [source.data.eq(port.dat_r)]
+ self.comb += Case(rd_slot, cases)
class LiteEthMACSRAM(Module, AutoCSR):
- def __init__(self, dw, depth, nrxslots, ntxslots):
- self.submodules.writer = LiteEthMACSRAMWriter(dw, depth, nrxslots)
- self.submodules.reader = LiteEthMACSRAMReader(dw, depth, ntxslots)
- self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
- self.sink, self.source = self.writer.sink, self.reader.source
+ def __init__(self, dw, depth, nrxslots, ntxslots):
+ self.submodules.writer = LiteEthMACSRAMWriter(dw, depth, nrxslots)
+ self.submodules.reader = LiteEthMACSRAMReader(dw, depth, ntxslots)
+ self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
+ self.sink, self.source = self.writer.sink, self.reader.source
from migen.fhdl.simplify import FullMemoryWE
class LiteEthMACWishboneInterface(Module, AutoCSR):
- def __init__(self, dw, nrxslots=2, ntxslots=2):
- self.sink = Sink(eth_phy_description(dw))
- self.source = Source(eth_phy_description(dw))
- self.bus = wishbone.Interface()
- ###
- # storage in SRAM
- sram_depth = buffer_depth//(dw//8)
- self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots)
- self.comb += [
- Record.connect(self.sink, self.sram.sink),
- Record.connect(self.sram.source, self.source)
- ]
+ def __init__(self, dw, nrxslots=2, ntxslots=2):
+ self.sink = Sink(eth_phy_description(dw))
+ self.source = Source(eth_phy_description(dw))
+ self.bus = wishbone.Interface()
+ ###
+ # storage in SRAM
+ sram_depth = buffer_depth//(dw//8)
+ self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots)
+ self.comb += [
+ Record.connect(self.sink, self.sram.sink),
+ Record.connect(self.sram.source, self.source)
+ ]
- # Wishbone 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
+ # Wishbone 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
+ 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
from misoclib.com.liteeth.generic import *
def LiteEthPHY(clock_pads, pads, **kwargs):
- # Autodetect PHY
- if hasattr(pads, "source_stb"):
- # This is a simulation PHY
- from misoclib.com.liteeth.phy.sim import LiteEthPHYSim
- return LiteEthPHYSim(pads)
- elif hasattr(clock_pads, "gtx") and flen(pads.tx_data) == 8:
- if hasattr(clock_pads, "tx"):
- # This is a 10/100/1G PHY
- from misoclib.com.liteeth.phy.gmii_mii import LiteEthPHYGMIIMII
- return LiteEthPHYGMIIMII(clock_pads, pads, **kwargs)
- else:
- # This is a pure 1G PHY
- from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII
- return LiteEthPHYGMII(clock_pads, pads, **kwargs)
- elif flen(pads.tx_data) == 4:
- # This is a MII PHY
- from misoclib.com.liteeth.phy.mii import LiteEthPHYMII
- return LiteEthPHYMII(clock_pads, pads, **kwargs)
- else:
- raise ValueError("Unable to autodetect PHY from platform file, use direct instantiation")
+ # Autodetect PHY
+ if hasattr(pads, "source_stb"):
+ # This is a simulation PHY
+ from misoclib.com.liteeth.phy.sim import LiteEthPHYSim
+ return LiteEthPHYSim(pads)
+ elif hasattr(clock_pads, "gtx") and flen(pads.tx_data) == 8:
+ if hasattr(clock_pads, "tx"):
+ # This is a 10/100/1G PHY
+ from misoclib.com.liteeth.phy.gmii_mii import LiteEthPHYGMIIMII
+ return LiteEthPHYGMIIMII(clock_pads, pads, **kwargs)
+ else:
+ # This is a pure 1G PHY
+ from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMII
+ return LiteEthPHYGMII(clock_pads, pads, **kwargs)
+ elif flen(pads.tx_data) == 4:
+ # This is a MII PHY
+ from misoclib.com.liteeth.phy.mii import LiteEthPHYMII
+ return LiteEthPHYMII(clock_pads, pads, **kwargs)
+ else:
+ raise ValueError("Unable to autodetect PHY from platform file, use direct instantiation")
from misoclib.com.liteeth.generic import *
class LiteEthPHYGMIITX(Module):
- def __init__(self, pads, pads_register):
- self.sink = sink = Sink(eth_phy_description(8))
- ###
- if hasattr(pads, "tx_er"):
- self.sync += pads.tx_er.eq(0)
- pads_eq = [
- pads.tx_en.eq(sink.stb),
- pads.tx_data.eq(sink.data)
- ]
- if pads_register:
- self.sync += pads_eq
- else:
- self.comb += pads_eq
- self.comb += sink.ack.eq(1)
+ def __init__(self, pads, pads_register):
+ self.sink = sink = Sink(eth_phy_description(8))
+ ###
+ if hasattr(pads, "tx_er"):
+ self.sync += pads.tx_er.eq(0)
+ pads_eq = [
+ pads.tx_en.eq(sink.stb),
+ pads.tx_data.eq(sink.data)
+ ]
+ if pads_register:
+ self.sync += pads_eq
+ else:
+ self.comb += pads_eq
+ self.comb += sink.ack.eq(1)
class LiteEthPHYGMIIRX(Module):
- def __init__(self, pads):
- self.source = source = Source(eth_phy_description(8))
- ###
- dv_d = Signal()
- self.sync += dv_d.eq(pads.dv)
+ def __init__(self, pads):
+ self.source = source = Source(eth_phy_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.data.eq(pads.rx_data)
- ]
- self.comb += source.eop.eq(eop)
+ 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.data.eq(pads.rx_data)
+ ]
+ self.comb += source.eop.eq(eop)
class LiteEthPHYGMIICRG(Module, AutoCSR):
- def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0):
- self._reset = CSRStorage()
- ###
- self.clock_domains.cd_eth_rx = ClockDomain()
- self.clock_domains.cd_eth_tx = ClockDomain()
+ def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0):
+ self._reset = CSRStorage()
+ ###
+ self.clock_domains.cd_eth_rx = ClockDomain()
+ self.clock_domains.cd_eth_tx = ClockDomain()
# RX : Let the synthesis tool insert the appropriate clock buffer
- self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
+ self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
- # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused
- # MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx
- self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx"))
- # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer?
- self.specials += Instance("BUFGMUX",
- i_I0=self.cd_eth_rx.clk,
- i_I1=clock_pads.tx,
- i_S=mii_mode,
- o_O=self.cd_eth_tx.clk)
+ # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused
+ # MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx
+ self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx"))
+ # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer?
+ self.specials += Instance("BUFGMUX",
+ i_I0=self.cd_eth_rx.clk,
+ i_I1=clock_pads.tx,
+ i_S=mii_mode,
+ o_O=self.cd_eth_tx.clk)
- if with_hw_init_reset:
- reset = Signal()
- counter_done = Signal()
- self.submodules.counter = counter = Counter(max=512)
- self.comb += [
- counter_done.eq(counter.value == 256),
- counter.ce.eq(~counter_done),
- reset.eq(~counter_done | self._reset.storage)
- ]
- else:
- 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),
- ]
+ if with_hw_init_reset:
+ reset = Signal()
+ counter_done = Signal()
+ self.submodules.counter = counter = Counter(max=512)
+ self.comb += [
+ counter_done.eq(counter.value == 256),
+ counter.ce.eq(~counter_done),
+ reset.eq(~counter_done | self._reset.storage)
+ ]
+ else:
+ 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 LiteEthPHYGMII(Module, AutoCSR):
- def __init__(self, clock_pads, pads, with_hw_init_reset=True):
- self.dw = 8
- self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset)
- self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads), "eth_tx")
- self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads), "eth_rx")
- self.sink, self.source = self.tx.sink, self.rx.source
+ def __init__(self, clock_pads, pads, with_hw_init_reset=True):
+ self.dw = 8
+ self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset)
+ self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads), "eth_tx")
+ self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads), "eth_rx")
+ self.sink, self.source = self.tx.sink, self.rx.source
from misoclib.com.liteeth.phy.gmii import LiteEthPHYGMIITX, LiteEthPHYGMIIRX
modes = {
- "GMII" : 0,
- "MII" : 1
+ "GMII" : 0,
+ "MII" : 1
}
tx_pads_layout = [("tx_er", 1), ("tx_en", 1), ("tx_data", 8)]
rx_pads_layout = [("rx_er", 1), ("dv", 1), ("rx_data", 8)]
class LiteEthPHYGMIIMIITX(Module):
- def __init__(self, pads, mode):
- self.sink = sink = Sink(eth_phy_description(8))
- ###
- gmii_tx_pads = Record(tx_pads_layout)
- gmii_tx = LiteEthPHYGMIITX(gmii_tx_pads, pads_register=False)
- self.submodules += gmii_tx
+ def __init__(self, pads, mode):
+ self.sink = sink = Sink(eth_phy_description(8))
+ ###
+ gmii_tx_pads = Record(tx_pads_layout)
+ gmii_tx = LiteEthPHYGMIITX(gmii_tx_pads, pads_register=False)
+ self.submodules += gmii_tx
- mii_tx_pads = Record(tx_pads_layout)
- mii_tx = LiteEthPHYMIITX(mii_tx_pads, pads_register=False)
- self.submodules += mii_tx
+ mii_tx_pads = Record(tx_pads_layout)
+ mii_tx = LiteEthPHYMIITX(mii_tx_pads, pads_register=False)
+ self.submodules += mii_tx
- demux = Demultiplexer(eth_phy_description(8), 2)
- self.submodules += demux
- self.comb += [
- demux.sel.eq(mode==modes["MII"]),
- Record.connect(sink, demux.sink),
- Record.connect(demux.source0, gmii_tx.sink),
- Record.connect(demux.source1, mii_tx.sink),
- ]
+ demux = Demultiplexer(eth_phy_description(8), 2)
+ self.submodules += demux
+ self.comb += [
+ demux.sel.eq(mode==modes["MII"]),
+ Record.connect(sink, demux.sink),
+ Record.connect(demux.source0, gmii_tx.sink),
+ Record.connect(demux.source1, mii_tx.sink),
+ ]
- if hasattr(pads, "tx_er"):
- self.comb += pads.tx_er.eq(0)
- self.sync += [
- If(mode==modes["MII"],
- pads.tx_en.eq(mii_tx_pads.tx_en),
- pads.tx_data.eq(mii_tx_pads.tx_data),
- ).Else(
- pads.tx_en.eq(gmii_tx_pads.tx_en),
- pads.tx_data.eq(gmii_tx_pads.tx_data),
- )
- ]
+ if hasattr(pads, "tx_er"):
+ self.comb += pads.tx_er.eq(0)
+ self.sync += [
+ If(mode==modes["MII"],
+ pads.tx_en.eq(mii_tx_pads.tx_en),
+ pads.tx_data.eq(mii_tx_pads.tx_data),
+ ).Else(
+ pads.tx_en.eq(gmii_tx_pads.tx_en),
+ pads.tx_data.eq(gmii_tx_pads.tx_data),
+ )
+ ]
class LiteEthPHYGMIIMIIRX(Module):
- def __init__(self, pads, mode):
- self.source = source = Source(eth_phy_description(8))
- ###
- pads_d = Record(rx_pads_layout)
- self.sync += [
- pads_d.dv.eq(pads.dv),
- pads_d.rx_data.eq(pads.rx_data)
- ]
+ def __init__(self, pads, mode):
+ self.source = source = Source(eth_phy_description(8))
+ ###
+ pads_d = Record(rx_pads_layout)
+ self.sync += [
+ pads_d.dv.eq(pads.dv),
+ pads_d.rx_data.eq(pads.rx_data)
+ ]
- gmii_rx = LiteEthPHYGMIIRX(pads_d)
- self.submodules += gmii_rx
+ gmii_rx = LiteEthPHYGMIIRX(pads_d)
+ self.submodules += gmii_rx
- mii_rx = LiteEthPHYMIIRX(pads_d)
- self.submodules += mii_rx
+ mii_rx = LiteEthPHYMIIRX(pads_d)
+ self.submodules += mii_rx
- mux = Multiplexer(eth_phy_description(8), 2)
- self.submodules += mux
- self.comb += [
- mux.sel.eq(mode==modes["MII"]),
- Record.connect(gmii_rx.source, mux.sink0),
- Record.connect(mii_rx.source, mux.sink1),
- Record.connect(mux.source, source)
- ]
+ mux = Multiplexer(eth_phy_description(8), 2)
+ self.submodules += mux
+ self.comb += [
+ mux.sel.eq(mode==modes["MII"]),
+ Record.connect(gmii_rx.source, mux.sink0),
+ Record.connect(mii_rx.source, mux.sink1),
+ Record.connect(mux.source, source)
+ ]
class LiteEthGMIIMIIClockCounter(Module, AutoCSR):
- def __init__(self):
- self._reset = CSRStorage()
- self._value = CSRStatus(32)
- ###
- counter = RenameClockDomains(Counter(32), "eth_rx")
- self.submodules += counter
- self.comb += [
- counter.reset.eq(self._reset.storage), #slow, don't need CDC
- counter.ce.eq(1),
- ]
- self.specials += MultiReg(counter.value, self._value.status)
+ def __init__(self):
+ self._reset = CSRStorage()
+ self._value = CSRStatus(32)
+ ###
+ counter = RenameClockDomains(Counter(32), "eth_rx")
+ self.submodules += counter
+ self.comb += [
+ counter.reset.eq(self._reset.storage), #slow, don't need CDC
+ counter.ce.eq(1),
+ ]
+ self.specials += MultiReg(counter.value, self._value.status)
class LiteEthPHYGMIIMII(Module, AutoCSR):
- def __init__(self, clock_pads, pads, with_hw_init_reset=True):
- self.dw = 8
- self._mode = CSRStorage()
- mode = self._mode.storage
- # Note: we can use GMII CRG since it also handles tx clock pad used for MII
- self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode==modes["MII"])
- self.submodules.clock_counter = LiteEthGMIIMIIClockCounter()
- self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")
- self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx")
- self.sink, self.source = self.tx.sink, self.rx.source
+ def __init__(self, clock_pads, pads, with_hw_init_reset=True):
+ self.dw = 8
+ self._mode = CSRStorage()
+ mode = self._mode.storage
+ # Note: we can use GMII CRG since it also handles tx clock pad used for MII
+ self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode==modes["MII"])
+ self.submodules.clock_counter = LiteEthGMIIMIIClockCounter()
+ self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")
+ self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx")
+ self.sink, self.source = self.tx.sink, self.rx.source
from misoclib.com.liteeth.generic import *
class LiteEthPHYLoopbackCRG(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())
- ]
+ 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)
- ]
+ reset = self._reset.storage
+ self.comb += [
+ self.cd_eth_rx.rst.eq(reset),
+ self.cd_eth_tx.rst.eq(reset)
+ ]
class LiteEthPHYLoopback(Module, AutoCSR):
- def __init__(self):
- self.dw = 8
- self.submodules.crg = LiteEthLoopbackPHYCRG()
- self.sink = sink = Sink(eth_phy_description(8))
- self.source = source = Source(eth_phy_description(8))
- self.comb += Record.connect(self.sink, self.source)
+ def __init__(self):
+ self.dw = 8
+ self.submodules.crg = LiteEthLoopbackPHYCRG()
+ self.sink = sink = Sink(eth_phy_description(8))
+ self.source = source = Source(eth_phy_description(8))
+ self.comb += Record.connect(self.sink, self.source)
from misoclib.com.liteeth.generic import *
def converter_description(dw):
- payload_layout = [("data", dw)]
- return EndpointDescription(payload_layout, packetized=True)
+ payload_layout = [("data", dw)]
+ return EndpointDescription(payload_layout, packetized=True)
class LiteEthPHYMIITX(Module):
- def __init__(self, pads, pads_register=True):
- self.sink = sink = Sink(eth_phy_description(8))
- ###
- if hasattr(pads, "tx_er"):
- self.sync += pads.tx_er.eq(0)
- converter = Converter(converter_description(8), converter_description(4))
- self.submodules += converter
- self.comb += [
- converter.sink.stb.eq(sink.stb),
- converter.sink.data.eq(sink.data),
- sink.ack.eq(converter.sink.ack),
- converter.source.ack.eq(1)
- ]
- pads_eq = [
- pads.tx_en.eq(converter.source.stb),
- pads.tx_data.eq(converter.source.data)
- ]
- if pads_register:
- self.sync += pads_eq
- else:
- self.comb += pads_eq
+ def __init__(self, pads, pads_register=True):
+ self.sink = sink = Sink(eth_phy_description(8))
+ ###
+ if hasattr(pads, "tx_er"):
+ self.sync += pads.tx_er.eq(0)
+ converter = Converter(converter_description(8), converter_description(4))
+ self.submodules += converter
+ self.comb += [
+ converter.sink.stb.eq(sink.stb),
+ converter.sink.data.eq(sink.data),
+ sink.ack.eq(converter.sink.ack),
+ converter.source.ack.eq(1)
+ ]
+ pads_eq = [
+ pads.tx_en.eq(converter.source.stb),
+ pads.tx_data.eq(converter.source.data)
+ ]
+ if pads_register:
+ self.sync += pads_eq
+ else:
+ self.comb += pads_eq
class LiteEthPHYMIIRX(Module):
- def __init__(self, pads):
- self.source = source = Source(eth_phy_description(8))
- ###
- sop = FlipFlop(reset=1)
- self.submodules += sop
+ def __init__(self, pads):
+ self.source = source = Source(eth_phy_description(8))
+ ###
+ sop = FlipFlop(reset=1)
+ self.submodules += sop
- converter = Converter(converter_description(4), converter_description(8))
- converter = InsertReset(converter)
- self.submodules += converter
+ converter = Converter(converter_description(4), converter_description(8))
+ converter = InsertReset(converter)
+ self.submodules += converter
- self.sync += [
- converter.reset.eq(~pads.dv),
- converter.sink.stb.eq(1),
- converter.sink.data.eq(pads.rx_data)
- ]
- self.comb += [
- sop.reset.eq(~pads.dv),
- sop.ce.eq(pads.dv),
- converter.sink.sop.eq(sop.q),
- converter.sink.eop.eq(~pads.dv)
- ]
- self.comb += Record.connect(converter.source, source)
+ self.sync += [
+ converter.reset.eq(~pads.dv),
+ converter.sink.stb.eq(1),
+ converter.sink.data.eq(pads.rx_data)
+ ]
+ self.comb += [
+ sop.reset.eq(~pads.dv),
+ sop.ce.eq(pads.dv),
+ converter.sink.sop.eq(sop.q),
+ converter.sink.eop.eq(~pads.dv)
+ ]
+ self.comb += Record.connect(converter.source, source)
class LiteEthPHYMIICRG(Module, AutoCSR):
- def __init__(self, clock_pads, pads, with_hw_init_reset):
- self._reset = CSRStorage()
- ###
- if hasattr(clock_pads, "phy"):
- self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy)
+ def __init__(self, clock_pads, pads, with_hw_init_reset):
+ self._reset = CSRStorage()
+ ###
+ if hasattr(clock_pads, "phy"):
+ 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)
+ 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)
- if with_hw_init_reset:
- reset = Signal()
- counter_done = Signal()
- self.submodules.counter = counter = Counter(max=512)
- self.comb += [
- counter_done.eq(counter.value == 256),
- counter.ce.eq(~counter_done),
- reset.eq(~counter_done | self._reset.storage)
- ]
- else:
- 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),
- ]
+ if with_hw_init_reset:
+ reset = Signal()
+ counter_done = Signal()
+ self.submodules.counter = counter = Counter(max=512)
+ self.comb += [
+ counter_done.eq(counter.value == 256),
+ counter.ce.eq(~counter_done),
+ reset.eq(~counter_done | self._reset.storage)
+ ]
+ else:
+ 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 LiteEthPHYMII(Module, AutoCSR):
- def __init__(self, clock_pads, pads, with_hw_init_reset=True):
- self.dw = 8
- self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads, with_hw_init_reset)
- self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx")
- self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx")
- self.sink, self.source = self.tx.sink, self.rx.source
+ def __init__(self, clock_pads, pads, with_hw_init_reset=True):
+ self.dw = 8
+ self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads, with_hw_init_reset)
+ self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx")
+ self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx")
+ self.sink, self.source = self.tx.sink, self.rx.source
from misoclib.com.liteeth.generic import *
class LiteEthPHYSimCRG(Module, AutoCSR):
- def __init__(self):
- self._reset = CSRStorage()
+ 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())
- ]
+ 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)
- ]
+ reset = self._reset.storage
+ self.comb += [
+ self.cd_eth_rx.rst.eq(reset),
+ self.cd_eth_tx.rst.eq(reset)
+ ]
class LiteEthPHYSim(Module, AutoCSR):
- def __init__(self, pads, tap="tap0", ip_address="192.168.0.14"):
- self.dw = 8
- self.submodules.crg = LiteEthPHYSimCRG()
- self.sink = sink = Sink(eth_phy_description(8))
- self.source = source = Source(eth_phy_description(8))
- self.tap = tap
- self.ip_address = ip_address
-
- self.comb += [
- pads.source_stb.eq(self.sink.stb),
- pads.source_data.eq(self.sink.data),
- self.sink.ack.eq(1)
- ]
-
- self.sync += [
- self.source.stb.eq(pads.sink_stb),
- self.source.sop.eq(pads.sink_stb & ~self.source.stb),
- self.source.data.eq(pads.sink_data),
- ]
- self.comb += [
- self.source.eop.eq(~pads.sink_stb & self.source.stb),
- ]
-
- # XXX avoid use of os.system
- os.system("openvpn --mktun --dev {}".format(self.tap))
- os.system("ifconfig {} {} up".format(self.tap, self.ip_address))
- os.system("mknod /dev/net/{} c 10 200".format(self.tap))
-
- def do_exit(self, *args, **kwargs):
- # XXX avoid use of os.system
- os.system("rm -f /dev/net/{}".format(self.tap))
- os.system("openvpn --rmtun --dev {}".format(self.tap))
+ def __init__(self, pads, tap="tap0", ip_address="192.168.0.14"):
+ self.dw = 8
+ self.submodules.crg = LiteEthPHYSimCRG()
+ self.sink = sink = Sink(eth_phy_description(8))
+ self.source = source = Source(eth_phy_description(8))
+ self.tap = tap
+ self.ip_address = ip_address
+
+ self.comb += [
+ pads.source_stb.eq(self.sink.stb),
+ pads.source_data.eq(self.sink.data),
+ self.sink.ack.eq(1)
+ ]
+
+ self.sync += [
+ self.source.stb.eq(pads.sink_stb),
+ self.source.sop.eq(pads.sink_stb & ~self.source.stb),
+ self.source.data.eq(pads.sink_data),
+ ]
+ self.comb += [
+ self.source.eop.eq(~pads.sink_stb & self.source.stb),
+ ]
+
+ # XXX avoid use of os.system
+ os.system("openvpn --mktun --dev {}".format(self.tap))
+ os.system("ifconfig {} {} up".format(self.tap, self.ip_address))
+ os.system("mknod /dev/net/{} c 10 200".format(self.tap))
+
+ def do_exit(self, *args, **kwargs):
+ # XXX avoid use of os.system
+ os.system("rm -f /dev/net/{}".format(self.tap))
+ os.system("openvpn --rmtun --dev {}".format(self.tap))
mac_address = 0x12345678abcd
class TB(Module):
- def __init__(self):
- self.submodules.phy_model = phy.PHY(8, debug=False)
- self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
- self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
-
- self.submodules.mac = LiteEthMAC(self.phy_model, dw=8, with_hw_preamble_crc=True)
- self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, 100000)
-
- # 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
-
- for i in range(100):
- yield
-
- while selfp.arp.table.request.ack != 1:
- selfp.arp.table.request.stb = 1
- selfp.arp.table.request.ip_address = 0x12345678
- yield
- selfp.arp.table.request.stb = 0
- while selfp.arp.table.response.stb != 1:
- selfp.arp.table.response.ack = 1
- yield
- print("Received MAC : 0x{:12x}".format(selfp.arp.table.response.mac_address))
+ def __init__(self):
+ self.submodules.phy_model = phy.PHY(8, debug=False)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
+ self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
+
+ self.submodules.mac = LiteEthMAC(self.phy_model, dw=8, with_hw_preamble_crc=True)
+ self.submodules.arp = LiteEthARP(self.mac, mac_address, ip_address, 100000)
+
+ # 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
+
+ for i in range(100):
+ yield
+
+ while selfp.arp.table.request.ack != 1:
+ selfp.arp.table.request.stb = 1
+ selfp.arp.table.request.ip_address = 0x12345678
+ yield
+ selfp.arp.table.request.stb = 0
+ while selfp.arp.table.response.stb != 1:
+ selfp.arp.table.response.ack = 1
+ yield
+ print("Received MAC : 0x{:12x}".format(selfp.arp.table.response.mac_address))
if __name__ == "__main__":
- run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
from misoclib.com.liteeth.common import *
def print_with_prefix(s, prefix=""):
- if not isinstance(s, str):
- s = s.__repr__()
- s = s.split("\n")
- for l in s:
- print(prefix + l)
+ if not isinstance(s, str):
+ s = s.__repr__()
+ s = s.split("\n")
+ for l in s:
+ print(prefix + l)
def seed_to_data(seed, random=True):
- if random:
- return (seed * 0x31415979 + 1) & 0xffffffff
- else:
- return seed
+ if random:
+ return (seed * 0x31415979 + 1) & 0xffffffff
+ else:
+ return seed
def split_bytes(v, n, endianness="big"):
- r = []
- r_bytes = v.to_bytes(n, byteorder=endianness)
- for byte in r_bytes:
- r.append(int(byte))
- return r
+ r = []
+ r_bytes = v.to_bytes(n, byteorder=endianness)
+ for byte in r_bytes:
+ r.append(int(byte))
+ return r
def merge_bytes(b, endianness="big"):
- return int.from_bytes(bytes(b), endianness)
+ return int.from_bytes(bytes(b), endianness)
def get_field_data(field, datas):
- v = merge_bytes(datas[field.byte:field.byte+math.ceil(field.width/8)])
- return (v >> field.offset) & (2**field.width-1)
+ v = merge_bytes(datas[field.byte:field.byte+math.ceil(field.width/8)])
+ return (v >> field.offset) & (2**field.width-1)
def comp(p1, p2):
- r = True
- for x, y in zip(p1, p2):
- if x != y:
- r = False
- return r
+ r = True
+ for x, y in zip(p1, p2):
+ if x != y:
+ r = False
+ return r
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
+ 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)
+ 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)
+ def __init__(self, init=[]):
+ self.ongoing = False
+ self.done = False
+ for data in init:
+ self.append(data)
class PacketStreamer(Module):
- def __init__(self, description, last_be=None):
- self.source = Source(description)
- self.last_be = last_be
- ###
- self.packets = []
- self.packet = Packet()
- self.packet.done = True
-
- def send(self, packet):
- packet = copy.deepcopy(packet)
- self.packets.append(packet)
- return packet
-
- def send_blocking(self, packet):
- packet = self.send(packet)
- while not packet.done:
- yield
-
- 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.data = self.packet.pop(0)
- self.packet.ongoing = True
- elif selfp.source.stb == 1 and selfp.source.ack == 1:
- selfp.source.sop = 0
- if len(self.packet) == 1:
- selfp.source.eop = 1
- if self.last_be is not None:
- selfp.source.last_be = self.last_be
- else:
- selfp.source.eop = 0
- if self.last_be is not None:
- selfp.source.last_be = 0
- if len(self.packet) > 0:
- selfp.source.stb = 1
- selfp.source.data = self.packet.pop(0)
- else:
- self.packet.done = True
- selfp.source.stb = 0
+ def __init__(self, description, last_be=None):
+ self.source = Source(description)
+ self.last_be = last_be
+ ###
+ self.packets = []
+ self.packet = Packet()
+ self.packet.done = True
+
+ def send(self, packet):
+ packet = copy.deepcopy(packet)
+ self.packets.append(packet)
+ return packet
+
+ def send_blocking(self, packet):
+ packet = self.send(packet)
+ while not packet.done:
+ yield
+
+ 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.data = self.packet.pop(0)
+ self.packet.ongoing = True
+ elif selfp.source.stb == 1 and selfp.source.ack == 1:
+ selfp.source.sop = 0
+ if len(self.packet) == 1:
+ selfp.source.eop = 1
+ if self.last_be is not None:
+ selfp.source.last_be = self.last_be
+ else:
+ selfp.source.eop = 0
+ if self.last_be is not None:
+ selfp.source.last_be = 0
+ if len(self.packet) > 0:
+ selfp.source.stb = 1
+ selfp.source.data = self.packet.pop(0)
+ else:
+ self.packet.done = True
+ selfp.source.stb = 0
class PacketLogger(Module):
- def __init__(self, description):
- self.sink = Sink(description)
- ###
- self.packet = Packet()
-
- def receive(self):
- self.packet.done = False
- while not self.packet.done:
- 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.data)
- elif selfp.sink.stb:
- self.packet.append(selfp.sink.data)
- if selfp.sink.stb == 1 and selfp.sink.eop == 1:
- self.packet.done = True
+ def __init__(self, description):
+ self.sink = Sink(description)
+ ###
+ self.packet = Packet()
+
+ def receive(self):
+ self.packet.done = False
+ while not self.packet.done:
+ 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.data)
+ elif selfp.sink.stb:
+ self.packet.append(selfp.sink.data)
+ 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
+ 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
mac_address = 0x12345678abcd
class TB(Module):
- def __init__(self):
- self.submodules.phy_model = phy.PHY(8, debug=False)
- self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
- self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
- self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False)
- self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=False)
- self.submodules.etherbone_model = etherbone.Etherbone(self.udp_model, debug=False)
-
- self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000)
- self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000)
-
- self.submodules.sram = wishbone.SRAM(1024)
- self.submodules.interconnect = wishbone.InterconnectPointToPoint(self.etherbone.master.bus, self.sram.bus)
-
- # 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
-
- for i in range(100):
- yield
-
- test_probe = True
- test_writes = True
- test_reads = True
-
- # test probe
- if test_probe:
- packet = etherbone.EtherbonePacket()
- packet.pf = 1
- self.etherbone_model.send(packet)
- yield from self.etherbone_model.receive()
- print("probe: " + str(bool(self.etherbone_model.rx_packet.pr)))
-
- for i in range(8):
- # test writes
- if test_writes:
- writes_datas = [j for j in range(16)]
- writes = etherbone.EtherboneWrites(base_addr=0x1000, datas=writes_datas)
- record = etherbone.EtherboneRecord()
- record.writes = writes
- record.reads = None
- record.bca = 0
- record.rca = 0
- record.rff = 0
- record.cyc = 0
- record.wca = 0
- record.wff = 0
- record.byte_enable = 0xf
- record.wcount = len(writes_datas)
- record.rcount = 0
-
- packet = etherbone.EtherbonePacket()
- packet.records = [record]
- self.etherbone_model.send(packet)
- for i in range(256):
- yield
-
- # test reads
- if test_reads:
- reads_addrs = [0x1000 + 4*j for j in range(16)]
- reads = etherbone.EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
- record = etherbone.EtherboneRecord()
- record.writes = None
- record.reads = reads
- record.bca = 0
- record.rca = 0
- record.rff = 0
- record.cyc = 0
- record.wca = 0
- record.wff = 0
- record.byte_enable = 0xf
- record.wcount = 0
- record.rcount = len(reads_addrs)
-
- packet = etherbone.EtherbonePacket()
- packet.records = [record]
- self.etherbone_model.send(packet)
- yield from self.etherbone_model.receive()
- loopback_writes_datas = []
- loopback_writes_datas = self.etherbone_model.rx_packet.records.pop().writes.get_datas()
-
- # check results
- s, l, e = check(writes_datas, loopback_writes_datas)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ def __init__(self):
+ self.submodules.phy_model = phy.PHY(8, debug=False)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
+ self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
+ self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False)
+ self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=False)
+ self.submodules.etherbone_model = etherbone.Etherbone(self.udp_model, debug=False)
+
+ self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000)
+ self.submodules.etherbone = LiteEthEtherbone(self.core.udp, 20000)
+
+ self.submodules.sram = wishbone.SRAM(1024)
+ self.submodules.interconnect = wishbone.InterconnectPointToPoint(self.etherbone.master.bus, self.sram.bus)
+
+ # 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
+
+ for i in range(100):
+ yield
+
+ test_probe = True
+ test_writes = True
+ test_reads = True
+
+ # test probe
+ if test_probe:
+ packet = etherbone.EtherbonePacket()
+ packet.pf = 1
+ self.etherbone_model.send(packet)
+ yield from self.etherbone_model.receive()
+ print("probe: " + str(bool(self.etherbone_model.rx_packet.pr)))
+
+ for i in range(8):
+ # test writes
+ if test_writes:
+ writes_datas = [j for j in range(16)]
+ writes = etherbone.EtherboneWrites(base_addr=0x1000, datas=writes_datas)
+ record = etherbone.EtherboneRecord()
+ record.writes = writes
+ record.reads = None
+ record.bca = 0
+ record.rca = 0
+ record.rff = 0
+ record.cyc = 0
+ record.wca = 0
+ record.wff = 0
+ record.byte_enable = 0xf
+ record.wcount = len(writes_datas)
+ record.rcount = 0
+
+ packet = etherbone.EtherbonePacket()
+ packet.records = [record]
+ self.etherbone_model.send(packet)
+ for i in range(256):
+ yield
+
+ # test reads
+ if test_reads:
+ reads_addrs = [0x1000 + 4*j for j in range(16)]
+ reads = etherbone.EtherboneReads(base_ret_addr=0x1000, addrs=reads_addrs)
+ record = etherbone.EtherboneRecord()
+ record.writes = None
+ record.reads = reads
+ record.bca = 0
+ record.rca = 0
+ record.rff = 0
+ record.cyc = 0
+ record.wca = 0
+ record.wff = 0
+ record.byte_enable = 0xf
+ record.wcount = 0
+ record.rcount = len(reads_addrs)
+
+ packet = etherbone.EtherbonePacket()
+ packet.records = [record]
+ self.etherbone_model.send(packet)
+ yield from self.etherbone_model.receive()
+ loopback_writes_datas = []
+ loopback_writes_datas = self.etherbone_model.rx_packet.records.pop().writes.get_datas()
+
+ # check results
+ s, l, e = check(writes_datas, loopback_writes_datas)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True)
\ No newline at end of file
+ run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True)
\ No newline at end of file
mac_address = 0x12345678abcd
class TB(Module):
- def __init__(self):
- self.submodules.phy_model = phy.PHY(8, debug=True)
- self.submodules.mac_model = mac.MAC(self.phy_model, debug=True, loopback=False)
- self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=True)
- self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=True, loopback=False)
- self.submodules.icmp_model = icmp.ICMP(self.ip_model, ip_address, debug=True)
-
- self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000)
-
- # 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
-
- for i in range(100):
- yield
-
- packet = MACPacket(ping_request)
- packet.decode_remove_header()
- packet = IPPacket(packet)
- packet.decode()
- packet = ICMPPacket(packet)
- packet.decode()
- self.icmp_model.send(packet)
+ def __init__(self):
+ self.submodules.phy_model = phy.PHY(8, debug=True)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=True, loopback=False)
+ self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=True)
+ self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=True, loopback=False)
+ self.submodules.icmp_model = icmp.ICMP(self.ip_model, ip_address, debug=True)
+
+ self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000)
+
+ # 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
+
+ for i in range(100):
+ yield
+
+ packet = MACPacket(ping_request)
+ packet.decode_remove_header()
+ packet = IPPacket(packet)
+ packet.decode()
+ packet = ICMPPacket(packet)
+ packet.decode()
+ self.icmp_model.send(packet)
if __name__ == "__main__":
- run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
mac_address = 0x12345678abcd
class TB(Module):
- def __init__(self):
- self.submodules.phy_model = phy.PHY(8, debug=False)
- self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
- self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
- self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=True)
-
- self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000)
- self.ip_port = self.ip.ip.crossbar.get_port(udp_protocol)
-
- # 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
-
- for i in range(100):
- yield
-
- while True:
- selfp.ip_port.sink.stb = 1
- selfp.ip_port.sink.sop = 1
- selfp.ip_port.sink.eop = 1
- selfp.ip_port.sink.ip_address = 0x12345678
- selfp.ip_port.sink.protocol = udp_protocol
-
- selfp.ip_port.source.ack = 1
- if selfp.ip_port.source.stb == 1 and selfp.ip_port.source.sop == 1:
- print("packet from IP 0x{:08x}".format(selfp.ip_port.sink.ip_address))
-
- yield
+ def __init__(self):
+ self.submodules.phy_model = phy.PHY(8, debug=False)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
+ self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
+ self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=True)
+
+ self.submodules.ip = LiteEthIPCore(self.phy_model, mac_address, ip_address, 100000)
+ self.ip_port = self.ip.ip.crossbar.get_port(udp_protocol)
+
+ # 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
+
+ for i in range(100):
+ yield
+
+ while True:
+ selfp.ip_port.sink.stb = 1
+ selfp.ip_port.sink.sop = 1
+ selfp.ip_port.sink.eop = 1
+ selfp.ip_port.sink.ip_address = 0x12345678
+ selfp.ip_port.sink.protocol = udp_protocol
+
+ selfp.ip_port.source.ack = 1
+ if selfp.ip_port.source.stb == 1 and selfp.ip_port.source.sop == 1:
+ print("packet from IP 0x{:08x}".format(selfp.ip_port.sink.ip_address))
+
+ yield
if __name__ == "__main__":
- run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
from misoclib.com.liteeth.test.model import phy, mac
class TB(Module):
- def __init__(self):
- self.submodules.phy_model = phy.PHY(8, debug=False)
- self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True)
- self.submodules.core = LiteEthMACCore(phy=self.phy_model, dw=8, with_hw_preamble_crc=True)
-
- self.submodules.streamer = PacketStreamer(eth_phy_description(8), last_be=1)
- self.submodules.streamer_randomizer = AckRandomizer(eth_phy_description(8), level=50)
-
- self.submodules.logger_randomizer = AckRandomizer(eth_phy_description(8), level=50)
- self.submodules.logger = PacketLogger(eth_phy_description(8))
-
- # 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()),
- ]
-
- self.comb += [
- Record.connect(self.streamer.source, self.streamer_randomizer.sink),
- Record.connect(self.streamer_randomizer.source, self.core.sink),
- Record.connect(self.core.source, self.logger_randomizer.sink),
- Record.connect(self.logger_randomizer.source, self.logger.sink)
- ]
-
- 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
-
- for i in range(8):
- packet = mac.MACPacket([i for i in range(64)])
- packet.target_mac = 0x010203040506
- packet.sender_mac = 0x090A0B0C0C0D
- packet.ethernet_type = 0x0800
- packet.encode_header()
- yield from self.streamer.send(packet)
- yield from self.logger.receive()
-
- # check results
- s, l, e = check(packet, self.logger.packet)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ def __init__(self):
+ self.submodules.phy_model = phy.PHY(8, debug=False)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True)
+ self.submodules.core = LiteEthMACCore(phy=self.phy_model, dw=8, with_hw_preamble_crc=True)
+
+ self.submodules.streamer = PacketStreamer(eth_phy_description(8), last_be=1)
+ self.submodules.streamer_randomizer = AckRandomizer(eth_phy_description(8), level=50)
+
+ self.submodules.logger_randomizer = AckRandomizer(eth_phy_description(8), level=50)
+ self.submodules.logger = PacketLogger(eth_phy_description(8))
+
+ # 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()),
+ ]
+
+ self.comb += [
+ Record.connect(self.streamer.source, self.streamer_randomizer.sink),
+ Record.connect(self.streamer_randomizer.source, self.core.sink),
+ Record.connect(self.core.source, self.logger_randomizer.sink),
+ Record.connect(self.logger_randomizer.source, self.logger.sink)
+ ]
+
+ 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
+
+ for i in range(8):
+ packet = mac.MACPacket([i for i in range(64)])
+ packet.target_mac = 0x010203040506
+ packet.sender_mac = 0x090A0B0C0C0D
+ packet.ethernet_type = 0x0800
+ packet.encode_header()
+ yield from self.streamer.send(packet)
+ yield from self.logger.receive()
+
+ # check results
+ s, l, e = check(packet, self.logger.packet)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- run_simulation(TB(), ncycles=4000, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=4000, vcd_name="my.vcd", keep_files=True)
from misoclib.com.liteeth.test.model import phy, mac
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
+ 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
+ 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 SRAMWriterDriver:
- def __init__(self, obj):
- self.obj = obj
+ def __init__(self, obj):
+ self.obj = obj
- def wait_available(self):
- while self.obj.ev.available.pending == 0:
- yield
+ def wait_available(self):
+ while self.obj.ev.available.pending == 0:
+ yield
- def clear_available(self):
- self.obj.ev.available.clear = 1
- yield
- self.obj.ev.available.clear = 0
- yield
+ def clear_available(self):
+ self.obj.ev.available.clear = 1
+ yield
+ self.obj.ev.available.clear = 0
+ yield
class TB(Module):
- def __init__(self):
- self.submodules.phy_model = phy.PHY(8, debug=False)
- self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True)
- self.submodules.ethmac = LiteEthMAC(phy=self.phy_model, dw=32, interface="wishbone", 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.interface.sram.reader)
- sram_writer_driver = SRAMWriterDriver(selfp.ethmac.interface.sram.writer)
-
- sram_writer_slots_offset = [0x000, 0x200]
- sram_reader_slots_offset = [0x400, 0x600]
-
- length = 150+2
-
- tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0]
-
- errors = 0
-
- while True:
- for slot in range(2):
- print("slot {}: ".format(slot), end="")
- # 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()
-
- # wait rx
- yield from sram_writer_driver.wait_available()
- yield from sram_writer_driver.clear_available()
-
- # 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))
+ def __init__(self):
+ self.submodules.phy_model = phy.PHY(8, debug=False)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=True)
+ self.submodules.ethmac = LiteEthMAC(phy=self.phy_model, dw=32, interface="wishbone", 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.interface.sram.reader)
+ sram_writer_driver = SRAMWriterDriver(selfp.ethmac.interface.sram.writer)
+
+ sram_writer_slots_offset = [0x000, 0x200]
+ sram_reader_slots_offset = [0x400, 0x600]
+
+ length = 150+2
+
+ tx_payload = [seed_to_data(i, True) % 0xFF for i in range(length)] + [0, 0, 0, 0]
+
+ errors = 0
+
+ while True:
+ for slot in range(2):
+ print("slot {}: ".format(slot), end="")
+ # 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()
+
+ # wait rx
+ yield from sram_writer_driver.wait_available()
+ yield from sram_writer_driver.clear_available()
+
+ # 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(), ncycles=3000, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=3000, vcd_name="my.vcd", keep_files=True)
from misoclib.com.liteeth.test.model import mac
def print_arp(s):
- print_with_prefix(s, "[ARP]")
+ print_with_prefix(s, "[ARP]")
preamble = split_bytes(eth_preamble, 8)
# ARP model
class ARPPacket(Packet):
- def __init__(self, init=[]):
- Packet.__init__(self, init)
-
- def decode(self):
- header = []
- for byte in self[:arp_header_len]:
- header.append(self.pop(0))
- for k, v in sorted(arp_header.items()):
- setattr(self, k, get_field_data(v, header))
-
- def encode(self):
- header = 0
- for k, v in sorted(arp_header.items()):
- value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
- header += (value << v.offset+(v.byte*8))
- for d in split_bytes(header, arp_header_len):
- self.insert(0, d)
-
- def __repr__(self):
- r = "--------\n"
- for k in sorted(arp_header.keys()):
- r += k + " : 0x{:0x}\n".format(getattr(self,k))
- r += "payload: "
- for d in self:
- r += "{:02x}".format(d)
- return r
+ def __init__(self, init=[]):
+ Packet.__init__(self, init)
+
+ def decode(self):
+ header = []
+ for byte in self[:arp_header_len]:
+ header.append(self.pop(0))
+ for k, v in sorted(arp_header.items()):
+ setattr(self, k, get_field_data(v, header))
+
+ def encode(self):
+ header = 0
+ for k, v in sorted(arp_header.items()):
+ value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
+ header += (value << v.offset+(v.byte*8))
+ for d in split_bytes(header, arp_header_len):
+ self.insert(0, d)
+
+ def __repr__(self):
+ r = "--------\n"
+ for k in sorted(arp_header.keys()):
+ r += k + " : 0x{:0x}\n".format(getattr(self,k))
+ r += "payload: "
+ for d in self:
+ r += "{:02x}".format(d)
+ return r
class ARP(Module):
- def __init__(self, mac, mac_address, ip_address, debug=False):
- self.mac = mac
- self.mac_address = mac_address
- self.ip_address = ip_address
- self.debug = debug
- self.tx_packets = []
- self.tx_packet = ARPPacket()
- self.rx_packet = ARPPacket()
- self.table = {}
- self.request_pending = False
-
- self.mac.set_arp_callback(self.callback)
-
- def send(self, packet):
- packet.encode()
- if self.debug:
- print_arp(">>>>>>>>")
- print_arp(packet)
- mac_packet = mac.MACPacket(packet)
- mac_packet.target_mac = packet.target_mac
- mac_packet.sender_mac = packet.sender_mac
- mac_packet.ethernet_type = ethernet_type_arp
- self.mac.send(mac_packet)
-
- def callback(self, packet):
- packet = ARPPacket(packet)
- packet.decode()
- if self.debug:
- print_arp("<<<<<<<<")
- print_arp(packet)
- self.process(packet)
-
- def process(self, packet):
- if len(packet) != eth_min_len-arp_header_len:
- raise ValueError
- if packet.hwtype != arp_hwtype_ethernet:
- raise ValueError
- if packet.proto != arp_proto_ip:
- raise ValueError
- if packet.hwsize != 6:
- raise ValueError
- if packet.protosize != 4:
- raise ValueError
- if packet.opcode == arp_opcode_request:
- self.process_request(packet)
- elif packet.opcode == arp_opcode_reply:
- self.process_reply(packet)
-
- def process_request(self, request):
- if request.target_ip == self.ip_address:
- reply = ARPPacket([0]*(eth_min_len-arp_header_len))
- reply.hwtype = arp_hwtype_ethernet
- reply.proto = arp_proto_ip
- reply.opcode = arp_opcode_reply
- reply.hwsize = 6
- reply.protosize = 4
- reply.sender_mac = self.mac_address
- reply.sender_ip = self.ip_address
- reply.target_mac = request.sender_mac
- reply.target_ip = request.sender_ip
- self.send(reply)
-
- def process_reply(self, reply):
- self.table[reply.sender_ip] = reply.sender_mac
-
- def request(self, ip_address):
- request = ARPPacket([0]*(eth_min_len-arp_header_len))
- request.hwtype = arp_hwtype_ethernet
- request.proto = arp_proto_ip
- request.opcode = arp_opcode_request
- request.hwsize = 6
- request.protosize = 4
- request.sender_mac = self.mac_address
- request.sender_ip = self.ip_address
- request.target_mac = 0xffffffffffff
- request.target_ip = ip_address
+ def __init__(self, mac, mac_address, ip_address, debug=False):
+ self.mac = mac
+ self.mac_address = mac_address
+ self.ip_address = ip_address
+ self.debug = debug
+ self.tx_packets = []
+ self.tx_packet = ARPPacket()
+ self.rx_packet = ARPPacket()
+ self.table = {}
+ self.request_pending = False
+
+ self.mac.set_arp_callback(self.callback)
+
+ def send(self, packet):
+ packet.encode()
+ if self.debug:
+ print_arp(">>>>>>>>")
+ print_arp(packet)
+ mac_packet = mac.MACPacket(packet)
+ mac_packet.target_mac = packet.target_mac
+ mac_packet.sender_mac = packet.sender_mac
+ mac_packet.ethernet_type = ethernet_type_arp
+ self.mac.send(mac_packet)
+
+ def callback(self, packet):
+ packet = ARPPacket(packet)
+ packet.decode()
+ if self.debug:
+ print_arp("<<<<<<<<")
+ print_arp(packet)
+ self.process(packet)
+
+ def process(self, packet):
+ if len(packet) != eth_min_len-arp_header_len:
+ raise ValueError
+ if packet.hwtype != arp_hwtype_ethernet:
+ raise ValueError
+ if packet.proto != arp_proto_ip:
+ raise ValueError
+ if packet.hwsize != 6:
+ raise ValueError
+ if packet.protosize != 4:
+ raise ValueError
+ if packet.opcode == arp_opcode_request:
+ self.process_request(packet)
+ elif packet.opcode == arp_opcode_reply:
+ self.process_reply(packet)
+
+ def process_request(self, request):
+ if request.target_ip == self.ip_address:
+ reply = ARPPacket([0]*(eth_min_len-arp_header_len))
+ reply.hwtype = arp_hwtype_ethernet
+ reply.proto = arp_proto_ip
+ reply.opcode = arp_opcode_reply
+ reply.hwsize = 6
+ reply.protosize = 4
+ reply.sender_mac = self.mac_address
+ reply.sender_ip = self.ip_address
+ reply.target_mac = request.sender_mac
+ reply.target_ip = request.sender_ip
+ self.send(reply)
+
+ def process_reply(self, reply):
+ self.table[reply.sender_ip] = reply.sender_mac
+
+ def request(self, ip_address):
+ request = ARPPacket([0]*(eth_min_len-arp_header_len))
+ request.hwtype = arp_hwtype_ethernet
+ request.proto = arp_proto_ip
+ request.opcode = arp_opcode_request
+ request.hwsize = 6
+ request.protosize = 4
+ request.sender_mac = self.mac_address
+ request.sender_ip = self.ip_address
+ request.target_mac = 0xffffffffffff
+ request.target_ip = ip_address
if __name__ == "__main__":
- from misoclib.com.liteeth.test.model.dumps import *
- from misoclib.com.liteeth.test.model.mac import *
- errors = 0
- # ARP request
- packet = MACPacket(arp_request)
- packet.decode_remove_header()
- packet = ARPPacket(packet)
- # check decoding
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, arp_request_infos)
- # check encoding
- packet.encode()
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, arp_request_infos)
-
- # ARP Reply
- packet = MACPacket(arp_reply)
- packet.decode_remove_header()
- packet = ARPPacket(packet)
- # check decoding
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, arp_reply_infos)
- # check encoding
- packet.encode()
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, arp_reply_infos)
-
- print("arp errors " + str(errors))
\ No newline at end of file
+ from misoclib.com.liteeth.test.model.dumps import *
+ from misoclib.com.liteeth.test.model.mac import *
+ errors = 0
+ # ARP request
+ packet = MACPacket(arp_request)
+ packet.decode_remove_header()
+ packet = ARPPacket(packet)
+ # check decoding
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, arp_request_infos)
+ # check encoding
+ packet.encode()
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, arp_request_infos)
+
+ # ARP Reply
+ packet = MACPacket(arp_reply)
+ packet.decode_remove_header()
+ packet = ARPPacket(packet)
+ # check decoding
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, arp_reply_infos)
+ # check encoding
+ packet.encode()
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, arp_reply_infos)
+
+ print("arp errors " + str(errors))
\ No newline at end of file
import re
def format_dump(dump):
- return [int(s, 16) for s in re.split(r'[;,\s\n]\s*', dump) if s is not ""]
+ return [int(s, 16) for s in re.split(r'[;,\s\n]\s*', dump) if s is not ""]
def verify_packet(packet, infos):
- errors = 0
- for k, v in infos.items():
- if hasattr(packet, k):
- if getattr(packet, k) != v:
- print("[Error] " + k)
- errors += 1
- return errors
+ errors = 0
+ for k, v in infos.items():
+ if hasattr(packet, k):
+ if getattr(packet, k) != v:
+ print("[Error] " + k)
+ errors += 1
+ return errors
arp_request = format_dump("""
00 22 19 22 54 9e 00 12 3f 97 92 01 08 06 00 01
00 22 19 22 54 9e a9 fe 64 62""")
arp_request_infos = {
- "sender_mac" : 0x00123f979201,
- "target_mac" : 0x00221922549e,
- "ethernet_type" : 0x806,
- "hwtype" : 0x1,
- "opcode" : 0x1,
- "protosize" : 0x4,
- "proto" : 0x800,
- "sender_ip" : 0xa9feff42,
- "target_ip" : 0xa9fe6462
+ "sender_mac" : 0x00123f979201,
+ "target_mac" : 0x00221922549e,
+ "ethernet_type" : 0x806,
+ "hwtype" : 0x1,
+ "opcode" : 0x1,
+ "protosize" : 0x4,
+ "proto" : 0x800,
+ "sender_ip" : 0xa9feff42,
+ "target_ip" : 0xa9fe6462
}
00 00 00 00 00 00 00 00 00 00 00 00""")
arp_reply_infos = {
- "sender_mac" : 0x00221922549e,
- "target_mac" : 0x00123f979201,
- "ethernet_type" : 0x806,
- "hwtype" : 0x1,
- "opcode" : 0x2,
- "protosize" : 0x4,
- "proto" : 0x800,
- "sender_ip" : 0xa9fe6462,
- "target_ip" : 0xa9feff42
+ "sender_mac" : 0x00221922549e,
+ "target_mac" : 0x00123f979201,
+ "ethernet_type" : 0x806,
+ "hwtype" : 0x1,
+ "opcode" : 0x2,
+ "protosize" : 0x4,
+ "proto" : 0x800,
+ "sender_ip" : 0xa9fe6462,
+ "target_ip" : 0xa9feff42
}
udp = format_dump("""
34 3a 55 54 7e 62 31 3a 79 31 3a 71 65""")
udp_infos = {
- "sender_mac" : 0x00140b333327,
- "target_mac" : 0xd07ab596cd0a,
- "protocol" : 0x11,
- "sender_ip" : 0xc0a80165,
- "target_ip" : 0xb27b0d78,
- "src_port" : 0xa63f,
- "dst_port" : 0x690f
+ "sender_mac" : 0x00140b333327,
+ "target_mac" : 0xd07ab596cd0a,
+ "protocol" : 0x11,
+ "sender_ip" : 0xc0a80165,
+ "target_ip" : 0xb27b0d78,
+ "src_port" : 0xa63f,
+ "dst_port" : 0x690f
}
ping_request = format_dump("""
77 61 62 63 64 65 66 67 68 69""")
ping_request_infos = {
- "code" : 0x0,
- "msgtype" : 0x8,
- "quench" : 0x2002100
+ "code" : 0x0,
+ "msgtype" : 0x8,
+ "quench" : 0x2002100
}
ping_reply = format_dump("""
from misoclib.com.liteeth.test.model import udp
def print_etherbone(s):
- print_with_prefix(s, "[ETHERBONE]")
+ print_with_prefix(s, "[ETHERBONE]")
# Etherbone model
class EtherboneWrite:
- def __init__(self, data):
- self.data = data
+ def __init__(self, data):
+ self.data = data
- def __repr__(self):
- return "WR32 0x{:08x}".format(self.data)
+ def __repr__(self):
+ return "WR32 0x{:08x}".format(self.data)
class EtherboneRead:
- def __init__(self, addr):
- self.addr = addr
+ def __init__(self, addr):
+ self.addr = addr
- def __repr__(self):
- return "RD32 @ 0x{:08x}".format(self.addr)
+ def __repr__(self):
+ return "RD32 @ 0x{:08x}".format(self.addr)
class EtherboneWrites(Packet):
- def __init__(self, init=[], base_addr=0, datas=[]):
- Packet.__init__(self, init)
- self.base_addr = base_addr
- self.writes = []
- self.encoded = init != []
- for data in datas:
- self.add(EtherboneWrite(data))
-
- def add(self, write):
- self.writes.append(write)
-
- def get_datas(self):
- datas = []
- for write in self.writes:
- datas.append(write.data)
- return datas
-
- def encode(self):
- if self.encoded:
- raise ValueError
- for byte in split_bytes(self.base_addr, 4):
- self.append(byte)
- for write in self.writes:
- for byte in split_bytes(write.data, 4):
- self.append(byte)
- self.encoded = True
-
- def decode(self):
- if not self.encoded:
- raise ValueError
- base_addr = []
- for i in range(4):
- base_addr.append(self.pop(0))
- self.base_addr = merge_bytes(base_addr)
- self.writes = []
- while len(self) != 0:
- write = []
- for i in range(4):
- write.append(self.pop(0))
- self.writes.append(EtherboneWrite(merge_bytes(write)))
- self.encoded = False
-
- def __repr__(self):
- r = "Writes\n"
- r += "--------\n"
- r += "BaseAddr @ 0x{:08x}\n".format(self.base_addr)
- for write in self.writes:
- r += write.__repr__() + "\n"
- return r
+ def __init__(self, init=[], base_addr=0, datas=[]):
+ Packet.__init__(self, init)
+ self.base_addr = base_addr
+ self.writes = []
+ self.encoded = init != []
+ for data in datas:
+ self.add(EtherboneWrite(data))
+
+ def add(self, write):
+ self.writes.append(write)
+
+ def get_datas(self):
+ datas = []
+ for write in self.writes:
+ datas.append(write.data)
+ return datas
+
+ def encode(self):
+ if self.encoded:
+ raise ValueError
+ for byte in split_bytes(self.base_addr, 4):
+ self.append(byte)
+ for write in self.writes:
+ for byte in split_bytes(write.data, 4):
+ self.append(byte)
+ self.encoded = True
+
+ def decode(self):
+ if not self.encoded:
+ raise ValueError
+ base_addr = []
+ for i in range(4):
+ base_addr.append(self.pop(0))
+ self.base_addr = merge_bytes(base_addr)
+ self.writes = []
+ while len(self) != 0:
+ write = []
+ for i in range(4):
+ write.append(self.pop(0))
+ self.writes.append(EtherboneWrite(merge_bytes(write)))
+ self.encoded = False
+
+ def __repr__(self):
+ r = "Writes\n"
+ r += "--------\n"
+ r += "BaseAddr @ 0x{:08x}\n".format(self.base_addr)
+ for write in self.writes:
+ r += write.__repr__() + "\n"
+ return r
class EtherboneReads(Packet):
- def __init__(self, init=[], base_ret_addr=0, addrs=[]):
- Packet.__init__(self, init)
- self.base_ret_addr = base_ret_addr
- self.reads = []
- self.encoded = init != []
- for addr in addrs:
- self.add(EtherboneRead(addr))
-
- def add(self, read):
- self.reads.append(read)
-
- def get_addrs(self):
- addrs = []
- for read in self.reads:
- addrs.append(read.addr)
- return addrs
-
- def encode(self):
- if self.encoded:
- raise ValueError
- for byte in split_bytes(self.base_ret_addr, 4):
- self.append(byte)
- for read in self.reads:
- for byte in split_bytes(read.addr, 4):
- self.append(byte)
- self.encoded = True
-
- def decode(self):
- if not self.encoded:
- raise ValueError
- base_ret_addr = []
- for i in range(4):
- base_ret_addr.append(self.pop(0))
- self.base_ret_addr = merge_bytes(base_ret_addr)
- self.reads = []
- while len(self) != 0:
- read = []
- for i in range(4):
- read.append(self.pop(0))
- self.reads.append(EtherboneRead(merge_bytes(read)))
- self.encoded = False
-
- def __repr__(self):
- r = "Reads\n"
- r += "--------\n"
- r += "BaseRetAddr @ 0x{:08x}\n".format(self.base_ret_addr)
- for read in self.reads:
- r += read.__repr__() + "\n"
- return r
+ def __init__(self, init=[], base_ret_addr=0, addrs=[]):
+ Packet.__init__(self, init)
+ self.base_ret_addr = base_ret_addr
+ self.reads = []
+ self.encoded = init != []
+ for addr in addrs:
+ self.add(EtherboneRead(addr))
+
+ def add(self, read):
+ self.reads.append(read)
+
+ def get_addrs(self):
+ addrs = []
+ for read in self.reads:
+ addrs.append(read.addr)
+ return addrs
+
+ def encode(self):
+ if self.encoded:
+ raise ValueError
+ for byte in split_bytes(self.base_ret_addr, 4):
+ self.append(byte)
+ for read in self.reads:
+ for byte in split_bytes(read.addr, 4):
+ self.append(byte)
+ self.encoded = True
+
+ def decode(self):
+ if not self.encoded:
+ raise ValueError
+ base_ret_addr = []
+ for i in range(4):
+ base_ret_addr.append(self.pop(0))
+ self.base_ret_addr = merge_bytes(base_ret_addr)
+ self.reads = []
+ while len(self) != 0:
+ read = []
+ for i in range(4):
+ read.append(self.pop(0))
+ self.reads.append(EtherboneRead(merge_bytes(read)))
+ self.encoded = False
+
+ def __repr__(self):
+ r = "Reads\n"
+ r += "--------\n"
+ r += "BaseRetAddr @ 0x{:08x}\n".format(self.base_ret_addr)
+ for read in self.reads:
+ r += read.__repr__() + "\n"
+ return r
class EtherboneRecord(Packet):
- def __init__(self, init=[]):
- Packet.__init__(self, init)
- self.writes = None
- self.reads = None
- self.encoded = init != []
-
- def get_writes(self):
- if self.wcount == 0:
- return None
- else:
- writes = []
- for i in range((self.wcount+1)*4):
- writes.append(self.pop(0))
- return EtherboneWrites(writes)
-
- def get_reads(self):
- if self.rcount == 0:
- return None
- else:
- reads = []
- for i in range((self.rcount+1)*4):
- reads.append(self.pop(0))
- return EtherboneReads(reads)
-
- def decode(self):
- if not self.encoded:
- raise ValueError
- header = []
- for byte in self[:etherbone_record_header_len]:
- header.append(self.pop(0))
- for k, v in sorted(etherbone_record_header.items()):
- setattr(self, k, get_field_data(v, header))
- self.writes = self.get_writes()
- if self.writes is not None:
- self.writes.decode()
- self.reads = self.get_reads()
- if self.reads is not None:
- self.reads.decode()
- self.encoded = False
-
- def set_writes(self, writes):
- self.wcount = len(writes.writes)
- writes.encode()
- for byte in writes:
- self.append(byte)
-
- def set_reads(self, reads):
- self.rcount = len(reads.reads)
- reads.encode()
- for byte in reads:
- self.append(byte)
-
- def encode(self):
- if self.encoded:
- raise ValueError
- if self.writes is not None:
- self.set_writes(self.writes)
- if self.reads is not None:
- self.set_reads(self.reads)
- header = 0
- for k, v in sorted(etherbone_record_header.items()):
- value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
- header += (value << v.offset+(v.byte*8))
- for d in split_bytes(header, etherbone_record_header_len):
- self.insert(0, d)
- self.encoded = True
-
- def __repr__(self, n=0):
- r = "Record {}\n".format(n)
- r += "--------\n"
- if self.encoded:
- for d in self:
- r += "{:02x}".format(d)
- else:
- for k in sorted(etherbone_record_header.keys()):
- r += k + " : 0x{:0x}\n".format(getattr(self,k))
- if self.wcount != 0:
- r += self.writes.__repr__()
- if self.rcount != 0:
- r += self.reads.__repr__()
- return r
+ def __init__(self, init=[]):
+ Packet.__init__(self, init)
+ self.writes = None
+ self.reads = None
+ self.encoded = init != []
+
+ def get_writes(self):
+ if self.wcount == 0:
+ return None
+ else:
+ writes = []
+ for i in range((self.wcount+1)*4):
+ writes.append(self.pop(0))
+ return EtherboneWrites(writes)
+
+ def get_reads(self):
+ if self.rcount == 0:
+ return None
+ else:
+ reads = []
+ for i in range((self.rcount+1)*4):
+ reads.append(self.pop(0))
+ return EtherboneReads(reads)
+
+ def decode(self):
+ if not self.encoded:
+ raise ValueError
+ header = []
+ for byte in self[:etherbone_record_header_len]:
+ header.append(self.pop(0))
+ for k, v in sorted(etherbone_record_header.items()):
+ setattr(self, k, get_field_data(v, header))
+ self.writes = self.get_writes()
+ if self.writes is not None:
+ self.writes.decode()
+ self.reads = self.get_reads()
+ if self.reads is not None:
+ self.reads.decode()
+ self.encoded = False
+
+ def set_writes(self, writes):
+ self.wcount = len(writes.writes)
+ writes.encode()
+ for byte in writes:
+ self.append(byte)
+
+ def set_reads(self, reads):
+ self.rcount = len(reads.reads)
+ reads.encode()
+ for byte in reads:
+ self.append(byte)
+
+ def encode(self):
+ if self.encoded:
+ raise ValueError
+ if self.writes is not None:
+ self.set_writes(self.writes)
+ if self.reads is not None:
+ self.set_reads(self.reads)
+ header = 0
+ for k, v in sorted(etherbone_record_header.items()):
+ value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
+ header += (value << v.offset+(v.byte*8))
+ for d in split_bytes(header, etherbone_record_header_len):
+ self.insert(0, d)
+ self.encoded = True
+
+ def __repr__(self, n=0):
+ r = "Record {}\n".format(n)
+ r += "--------\n"
+ if self.encoded:
+ for d in self:
+ r += "{:02x}".format(d)
+ else:
+ for k in sorted(etherbone_record_header.keys()):
+ r += k + " : 0x{:0x}\n".format(getattr(self,k))
+ if self.wcount != 0:
+ r += self.writes.__repr__()
+ if self.rcount != 0:
+ r += self.reads.__repr__()
+ return r
class EtherbonePacket(Packet):
- def __init__(self, init=[]):
- Packet.__init__(self, init)
- self.encoded = init != []
- self.records = []
-
- self.magic = etherbone_magic
- self.version = etherbone_version
- self.addr_size = 32//8
- self.port_size = 32//8
- self.nr = 0
- self.pr = 0
- self.pf = 0
-
- def get_records(self):
- records = []
- done = False
- payload = self
- while len(payload) != 0:
- record = EtherboneRecord(payload)
- record.decode()
- records.append(copy.deepcopy(record))
- payload = record
- return records
-
- def decode(self):
- if not self.encoded:
- raise ValueError
- header = []
- for byte in self[:etherbone_packet_header_len]:
- header.append(self.pop(0))
- for k, v in sorted(etherbone_packet_header.items()):
- setattr(self, k, get_field_data(v, header))
- self.records = self.get_records()
- self.encoded = False
-
- def set_records(self, records):
- for record in records:
- record.encode()
- for byte in record:
- self.append(byte)
-
- def encode(self):
- if self.encoded:
- raise ValueError
- self.set_records(self.records)
- header = 0
- for k, v in sorted(etherbone_packet_header.items()):
- value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
- header += (value << v.offset+(v.byte*8))
- for d in split_bytes(header, etherbone_packet_header_len):
- self.insert(0, d)
- self.encoded = True
-
- def __repr__(self):
- r = "Packet\n"
- r += "--------\n"
- if self.encoded:
- for d in self:
- r += "{:02x}".format(d)
- else:
- for k in sorted(etherbone_packet_header.keys()):
- r += k + " : 0x{:0x}\n".format(getattr(self,k))
- for i, record in enumerate(self.records):
- r += record.__repr__(i)
- return r
+ def __init__(self, init=[]):
+ Packet.__init__(self, init)
+ self.encoded = init != []
+ self.records = []
+
+ self.magic = etherbone_magic
+ self.version = etherbone_version
+ self.addr_size = 32//8
+ self.port_size = 32//8
+ self.nr = 0
+ self.pr = 0
+ self.pf = 0
+
+ def get_records(self):
+ records = []
+ done = False
+ payload = self
+ while len(payload) != 0:
+ record = EtherboneRecord(payload)
+ record.decode()
+ records.append(copy.deepcopy(record))
+ payload = record
+ return records
+
+ def decode(self):
+ if not self.encoded:
+ raise ValueError
+ header = []
+ for byte in self[:etherbone_packet_header_len]:
+ header.append(self.pop(0))
+ for k, v in sorted(etherbone_packet_header.items()):
+ setattr(self, k, get_field_data(v, header))
+ self.records = self.get_records()
+ self.encoded = False
+
+ def set_records(self, records):
+ for record in records:
+ record.encode()
+ for byte in record:
+ self.append(byte)
+
+ def encode(self):
+ if self.encoded:
+ raise ValueError
+ self.set_records(self.records)
+ header = 0
+ for k, v in sorted(etherbone_packet_header.items()):
+ value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
+ header += (value << v.offset+(v.byte*8))
+ for d in split_bytes(header, etherbone_packet_header_len):
+ self.insert(0, d)
+ self.encoded = True
+
+ def __repr__(self):
+ r = "Packet\n"
+ r += "--------\n"
+ if self.encoded:
+ for d in self:
+ r += "{:02x}".format(d)
+ else:
+ for k in sorted(etherbone_packet_header.keys()):
+ r += k + " : 0x{:0x}\n".format(getattr(self,k))
+ for i, record in enumerate(self.records):
+ r += record.__repr__(i)
+ return r
class Etherbone(Module):
- def __init__(self, udp, debug=False):
- self.udp = udp
- self.debug = debug
- self.tx_packets = []
- self.tx_packet = EtherbonePacket()
- self.rx_packet = EtherbonePacket()
-
- udp.set_etherbone_callback(self.callback)
-
- def send(self, packet):
- packet.encode()
- if self.debug:
- print_etherbone(">>>>>>>>")
- print_etherbone(packet)
- udp_packet = udp.UDPPacket(packet)
- udp_packet.src_port = 0x1234 # XXX
- udp_packet.dst_port = 20000 # XXX
- udp_packet.length = len(packet)
- udp_packet.checksum = 0
- self.udp.send(udp_packet)
-
- def receive(self):
- self.rx_packet = EtherbonePacket()
- while not self.rx_packet.done:
- yield
-
- def callback(self, packet):
- packet = EtherbonePacket(packet)
- packet.decode()
- if self.debug:
- print_etherbone("<<<<<<<<")
- print_etherbone(packet)
- self.rx_packet = packet
- self.rx_packet.done = True
- self.process(packet)
-
- def process(self, packet):
- pass
+ def __init__(self, udp, debug=False):
+ self.udp = udp
+ self.debug = debug
+ self.tx_packets = []
+ self.tx_packet = EtherbonePacket()
+ self.rx_packet = EtherbonePacket()
+
+ udp.set_etherbone_callback(self.callback)
+
+ def send(self, packet):
+ packet.encode()
+ if self.debug:
+ print_etherbone(">>>>>>>>")
+ print_etherbone(packet)
+ udp_packet = udp.UDPPacket(packet)
+ udp_packet.src_port = 0x1234 # XXX
+ udp_packet.dst_port = 20000 # XXX
+ udp_packet.length = len(packet)
+ udp_packet.checksum = 0
+ self.udp.send(udp_packet)
+
+ def receive(self):
+ self.rx_packet = EtherbonePacket()
+ while not self.rx_packet.done:
+ yield
+
+ def callback(self, packet):
+ packet = EtherbonePacket(packet)
+ packet.decode()
+ if self.debug:
+ print_etherbone("<<<<<<<<")
+ print_etherbone(packet)
+ self.rx_packet = packet
+ self.rx_packet.done = True
+ self.process(packet)
+
+ def process(self, packet):
+ pass
if __name__ == "__main__":
- # Writes/Reads
- writes = EtherboneWrites(base_addr=0x1000, datas=[i for i in range(16)])
- reads = EtherboneReads(base_ret_addr=0x2000, addrs=[i for i in range(16)])
-
- # Record
- record = EtherboneRecord()
- record.writes = writes
- record.reads = reads
- record.bca = 0
- record.rca = 0
- record.rff = 0
- record.cyc = 0
- record.wca = 0
- record.wff = 0
- record.byte_enable = 0
- record.wcount = len(writes.get_datas())
- record.rcount = len(reads.get_addrs())
-
- # Packet
- packet = EtherbonePacket()
- packet.records = [copy.deepcopy(record) for i in range(8)]
- packet.nr = 0
- packet.pr = 0
- packet.pf = 0
- #print(packet)
- packet.encode()
- #print(packet)
-
- # Send packet over UDP to check against Wireshark dissector
- import socket
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- sock.sendto(bytes(packet), ("192.168.1.1", 20000))
-
- packet = EtherbonePacket(packet)
- packet.decode()
- print(packet)
+ # Writes/Reads
+ writes = EtherboneWrites(base_addr=0x1000, datas=[i for i in range(16)])
+ reads = EtherboneReads(base_ret_addr=0x2000, addrs=[i for i in range(16)])
+
+ # Record
+ record = EtherboneRecord()
+ record.writes = writes
+ record.reads = reads
+ record.bca = 0
+ record.rca = 0
+ record.rff = 0
+ record.cyc = 0
+ record.wca = 0
+ record.wff = 0
+ record.byte_enable = 0
+ record.wcount = len(writes.get_datas())
+ record.rcount = len(reads.get_addrs())
+
+ # Packet
+ packet = EtherbonePacket()
+ packet.records = [copy.deepcopy(record) for i in range(8)]
+ packet.nr = 0
+ packet.pr = 0
+ packet.pf = 0
+ #print(packet)
+ packet.encode()
+ #print(packet)
+
+ # Send packet over UDP to check against Wireshark dissector
+ import socket
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ sock.sendto(bytes(packet), ("192.168.1.1", 20000))
+
+ packet = EtherbonePacket(packet)
+ packet.decode()
+ print(packet)
from misoclib.com.liteeth.test.model import ip
def print_icmp(s):
- print_with_prefix(s, "[ICMP]")
+ print_with_prefix(s, "[ICMP]")
# ICMP model
class ICMPPacket(Packet):
- def __init__(self, init=[]):
- Packet.__init__(self, init)
+ def __init__(self, init=[]):
+ Packet.__init__(self, init)
- def decode(self):
- header = []
- for byte in self[:icmp_header_len]:
- header.append(self.pop(0))
- for k, v in sorted(icmp_header.items()):
- setattr(self, k, get_field_data(v, header))
+ def decode(self):
+ header = []
+ for byte in self[:icmp_header_len]:
+ header.append(self.pop(0))
+ for k, v in sorted(icmp_header.items()):
+ setattr(self, k, get_field_data(v, header))
- def encode(self):
- header = 0
- for k, v in sorted(icmp_header.items()):
- value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
- header += (value << v.offset+(v.byte*8))
- for d in split_bytes(header, icmp_header_len):
- self.insert(0, d)
+ def encode(self):
+ header = 0
+ for k, v in sorted(icmp_header.items()):
+ value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
+ header += (value << v.offset+(v.byte*8))
+ for d in split_bytes(header, icmp_header_len):
+ self.insert(0, d)
- def __repr__(self):
- r = "--------\n"
- for k in sorted(icmp_header.keys()):
- r += k + " : 0x{:0x}\n".format(getattr(self,k))
- r += "payload: "
- for d in self:
- r += "{:02x}".format(d)
- return r
+ def __repr__(self):
+ r = "--------\n"
+ for k in sorted(icmp_header.keys()):
+ r += k + " : 0x{:0x}\n".format(getattr(self,k))
+ r += "payload: "
+ for d in self:
+ r += "{:02x}".format(d)
+ return r
class ICMP(Module):
- def __init__(self, ip, ip_address, debug=False):
- self.ip = ip
- self.ip_address = ip_address
- self.debug = debug
- self.tx_packets = []
- self.tx_packet = ICMPPacket()
- self.rx_packet = ICMPPacket()
+ def __init__(self, ip, ip_address, debug=False):
+ self.ip = ip
+ self.ip_address = ip_address
+ self.debug = debug
+ self.tx_packets = []
+ self.tx_packet = ICMPPacket()
+ self.rx_packet = ICMPPacket()
- self.ip.set_icmp_callback(self.callback)
+ self.ip.set_icmp_callback(self.callback)
- def send(self, packet):
- packet.encode()
- if self.debug:
- print_icmp(">>>>>>>>")
- print_icmp(packet)
- ip_packet = ip.IPPacket(packet)
- ip_packet.version = 0x4
- ip_packet.ihl = 0x5
- ip_packet.total_length = len(packet) + ip_packet.ihl
- ip_packet.identification = 0
- ip_packet.flags = 0
- ip_packet.fragment_offset = 0
- ip_packet.ttl = 0x80
- ip_packet.sender_ip = self.ip_address
- ip_packet.target_ip = 0x12345678 # XXX
- ip_packet.checksum = 0
- ip_packet.protocol = icmp_protocol
- self.ip.send(ip_packet)
+ def send(self, packet):
+ packet.encode()
+ if self.debug:
+ print_icmp(">>>>>>>>")
+ print_icmp(packet)
+ ip_packet = ip.IPPacket(packet)
+ ip_packet.version = 0x4
+ ip_packet.ihl = 0x5
+ ip_packet.total_length = len(packet) + ip_packet.ihl
+ ip_packet.identification = 0
+ ip_packet.flags = 0
+ ip_packet.fragment_offset = 0
+ ip_packet.ttl = 0x80
+ ip_packet.sender_ip = self.ip_address
+ ip_packet.target_ip = 0x12345678 # XXX
+ ip_packet.checksum = 0
+ ip_packet.protocol = icmp_protocol
+ self.ip.send(ip_packet)
- def callback(self, packet):
- packet = ICMPPacket(packet)
- packet.decode()
- if self.debug:
- print_icmp("<<<<<<<<")
- print_icmp(packet)
- self.process(packet)
+ def callback(self, packet):
+ packet = ICMPPacket(packet)
+ packet.decode()
+ if self.debug:
+ print_icmp("<<<<<<<<")
+ print_icmp(packet)
+ self.process(packet)
- def process(self, packet):
- pass
+ def process(self, packet):
+ pass
if __name__ == "__main__":
- from misoclib.com.liteeth.test.model.dumps import *
- from misoclib.com.liteeth.test.model.mac import *
- from misoclib.com.liteeth.test.model.ip import *
- errors = 0
- # ICMP packet
- packet = MACPacket(ping_request)
- packet.decode_remove_header()
- #print(packet)
- packet = IPPacket(packet)
- packet.decode()
- #print(packet)
- packet = ICMPPacket(packet)
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, ping_request_infos)
- packet.encode()
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, ping_request_infos)
+ from misoclib.com.liteeth.test.model.dumps import *
+ from misoclib.com.liteeth.test.model.mac import *
+ from misoclib.com.liteeth.test.model.ip import *
+ errors = 0
+ # ICMP packet
+ packet = MACPacket(ping_request)
+ packet.decode_remove_header()
+ #print(packet)
+ packet = IPPacket(packet)
+ packet.decode()
+ #print(packet)
+ packet = ICMPPacket(packet)
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, ping_request_infos)
+ packet.encode()
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, ping_request_infos)
- print("icmp errors " + str(errors))
\ No newline at end of file
+ print("icmp errors " + str(errors))
\ No newline at end of file
from misoclib.com.liteeth.test.model import mac
def print_ip(s):
- print_with_prefix(s, "[IP]")
+ print_with_prefix(s, "[IP]")
def carry_around_add(a, b):
c = a + b
# IP model
class IPPacket(Packet):
- def __init__(self, init=[]):
- Packet.__init__(self, init)
-
- def get_checksum(self):
- return self[10] | (self[11] << 8)
-
- def check_checksum(self):
- return checksum(self[:ipv4_header_len]) == 0
-
- def decode(self):
- header = []
- for byte in self[:ipv4_header_len]:
- header.append(self.pop(0))
- for k, v in sorted(ipv4_header.items()):
- setattr(self, k, get_field_data(v, header))
-
- def encode(self):
- header = 0
- for k, v in sorted(ipv4_header.items()):
- value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
- header += (value << v.offset+(v.byte*8))
- for d in split_bytes(header, ipv4_header_len):
- self.insert(0, d)
-
- def insert_checksum(self):
- self[10] = 0
- self[11] = 0
- c = checksum(self[:ipv4_header_len])
- self[10] = c & 0xff
- self[11] = (c >> 8) & 0xff
-
- def __repr__(self):
- r = "--------\n"
- for k in sorted(ipv4_header.keys()):
- r += k + " : 0x{:0x}\n".format(getattr(self,k))
- r += "payload: "
- for d in self:
- r += "{:02x}".format(d)
- return r
+ def __init__(self, init=[]):
+ Packet.__init__(self, init)
+
+ def get_checksum(self):
+ return self[10] | (self[11] << 8)
+
+ def check_checksum(self):
+ return checksum(self[:ipv4_header_len]) == 0
+
+ def decode(self):
+ header = []
+ for byte in self[:ipv4_header_len]:
+ header.append(self.pop(0))
+ for k, v in sorted(ipv4_header.items()):
+ setattr(self, k, get_field_data(v, header))
+
+ def encode(self):
+ header = 0
+ for k, v in sorted(ipv4_header.items()):
+ value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
+ header += (value << v.offset+(v.byte*8))
+ for d in split_bytes(header, ipv4_header_len):
+ self.insert(0, d)
+
+ def insert_checksum(self):
+ self[10] = 0
+ self[11] = 0
+ c = checksum(self[:ipv4_header_len])
+ self[10] = c & 0xff
+ self[11] = (c >> 8) & 0xff
+
+ def __repr__(self):
+ r = "--------\n"
+ for k in sorted(ipv4_header.keys()):
+ r += k + " : 0x{:0x}\n".format(getattr(self,k))
+ r += "payload: "
+ for d in self:
+ r += "{:02x}".format(d)
+ return r
class IP(Module):
- def __init__(self, mac, mac_address, ip_address, debug=False, loopback=False):
- self.mac = mac
- self.mac_address = mac_address
- self.ip_address = ip_address
- self.debug = debug
- self.loopback = loopback
- self.rx_packet = IPPacket()
- self.table = {}
- self.request_pending = False
-
- self.udp_callback = None
- self.icmp_callback = None
-
- self.mac.set_ip_callback(self.callback)
-
- def set_udp_callback(self, callback):
- self.udp_callback = callback
-
- def set_icmp_callback(self, callback):
- self.icmp_callback = callback
-
- def send(self, packet):
- packet.encode()
- packet.insert_checksum()
- if self.debug:
- print_ip(">>>>>>>>")
- print_ip(packet)
- mac_packet = mac.MACPacket(packet)
- mac_packet.target_mac = 0x12345678abcd # XXX
- mac_packet.sender_mac = self.mac_address
- mac_packet.ethernet_type = ethernet_type_ip
- self.mac.send(mac_packet)
-
- def callback(self, packet):
- packet = IPPacket(packet)
- if not packet.check_checksum():
- received = packet.get_checksum()
- packet.insert_checksum()
- expected = packet.get_checksum()
- raise ValueError("Checksum error received {:04x} / expected {:04x}".format(received, expected))
- packet.decode()
- if self.debug:
- print_ip("<<<<<<<<")
- print_ip(packet)
- if self.loopback:
- self.send(packet)
- else:
- if packet.version != 0x4:
- raise ValueError
- if packet.ihl != 0x5:
- raise ValueError
- self.process(packet)
-
- def process(self, packet):
- if packet.protocol == udp_protocol:
- if self.udp_callback is not None:
- self.udp_callback(packet)
- elif packet.protocol == icmp_protocol:
- if self.icmp_callback is not None:
- self.icmp_callback(packet)
+ def __init__(self, mac, mac_address, ip_address, debug=False, loopback=False):
+ self.mac = mac
+ self.mac_address = mac_address
+ self.ip_address = ip_address
+ self.debug = debug
+ self.loopback = loopback
+ self.rx_packet = IPPacket()
+ self.table = {}
+ self.request_pending = False
+
+ self.udp_callback = None
+ self.icmp_callback = None
+
+ self.mac.set_ip_callback(self.callback)
+
+ def set_udp_callback(self, callback):
+ self.udp_callback = callback
+
+ def set_icmp_callback(self, callback):
+ self.icmp_callback = callback
+
+ def send(self, packet):
+ packet.encode()
+ packet.insert_checksum()
+ if self.debug:
+ print_ip(">>>>>>>>")
+ print_ip(packet)
+ mac_packet = mac.MACPacket(packet)
+ mac_packet.target_mac = 0x12345678abcd # XXX
+ mac_packet.sender_mac = self.mac_address
+ mac_packet.ethernet_type = ethernet_type_ip
+ self.mac.send(mac_packet)
+
+ def callback(self, packet):
+ packet = IPPacket(packet)
+ if not packet.check_checksum():
+ received = packet.get_checksum()
+ packet.insert_checksum()
+ expected = packet.get_checksum()
+ raise ValueError("Checksum error received {:04x} / expected {:04x}".format(received, expected))
+ packet.decode()
+ if self.debug:
+ print_ip("<<<<<<<<")
+ print_ip(packet)
+ if self.loopback:
+ self.send(packet)
+ else:
+ if packet.version != 0x4:
+ raise ValueError
+ if packet.ihl != 0x5:
+ raise ValueError
+ self.process(packet)
+
+ def process(self, packet):
+ if packet.protocol == udp_protocol:
+ if self.udp_callback is not None:
+ self.udp_callback(packet)
+ elif packet.protocol == icmp_protocol:
+ if self.icmp_callback is not None:
+ self.icmp_callback(packet)
if __name__ == "__main__":
- from misoclib.com.liteeth.test.model.dumps import *
- from misoclib.com.liteeth.test.model.mac import *
- errors = 0
- # UDP packet
- packet = MACPacket(udp)
- packet.decode_remove_header()
- #print(packet)
- packet = IPPacket(packet)
- # check decoding
- errors += not packet.check_checksum()
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, {})
- # check encoding
- packet.encode()
- packet.insert_checksum()
- errors += not packet.check_checksum()
- packet.decode()
- #print(packet)
- errors += verify_packet(packet, {})
-
- print("ip errors " + str(errors))
\ No newline at end of file
+ from misoclib.com.liteeth.test.model.dumps import *
+ from misoclib.com.liteeth.test.model.mac import *
+ errors = 0
+ # UDP packet
+ packet = MACPacket(udp)
+ packet.decode_remove_header()
+ #print(packet)
+ packet = IPPacket(packet)
+ # check decoding
+ errors += not packet.check_checksum()
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, {})
+ # check encoding
+ packet.encode()
+ packet.insert_checksum()
+ errors += not packet.check_checksum()
+ packet.decode()
+ #print(packet)
+ errors += verify_packet(packet, {})
+
+ print("ip errors " + str(errors))
\ No newline at end of file
from misoclib.com.liteeth.test.common import *
def print_mac(s):
- print_with_prefix(s, "[MAC]")
+ print_with_prefix(s, "[MAC]")
preamble = split_bytes(eth_preamble, 8, "little")
def crc32(l):
- crc = []
- crc_bytes = split_bytes(binascii.crc32(bytes(l)), 4, "little")
- for byte in crc_bytes:
- crc.append(int(byte))
- return crc
+ crc = []
+ crc_bytes = split_bytes(binascii.crc32(bytes(l)), 4, "little")
+ for byte in crc_bytes:
+ crc.append(int(byte))
+ return crc
# MAC model
class MACPacket(Packet):
- def __init__(self, init=[]):
- Packet.__init__(self, init)
- self.preamble_error = False
- self.crc_error = False
-
- def check_remove_preamble(self):
- if comp(self[0:8], preamble):
- for i in range(8):
- self.pop(0)
- return False
- else:
- return True
-
- def check_remove_crc(self):
- if comp(self[-4:], crc32(self[:-4])):
- for i in range(4):
- self.pop()
- return False
- else:
- return True
-
- def decode_remove_header(self):
- header = []
- for byte in self[:mac_header_len]:
- header.append(self.pop(0))
- for k, v in sorted(mac_header.items()):
- setattr(self, k, get_field_data(v, header))
-
- def decode(self):
- self.preamble_error = self.check_remove_preamble()
- self.crc_error = self.check_remove_crc()
- if self.crc_error or self.preamble_error:
- raise ValueError # XXX handle this properly
- else:
- self.decode_remove_header()
-
- def encode_header(self):
- header = 0
- for k, v in sorted(mac_header.items()):
- value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
- header += (value << v.offset+(v.byte*8))
- for d in split_bytes(header, mac_header_len):
- self.insert(0, d)
-
- def insert_crc(self):
- for d in crc32(self):
- self.append(d)
-
- def insert_preamble(self):
- for d in reversed(preamble):
- self.insert(0, d)
-
- def encode(self):
- self.encode_header()
- self.insert_crc()
- self.insert_preamble()
-
- def __repr__(self):
- r = "--------\n"
- for k in sorted(mac_header.keys()):
- r += k + " : 0x{:0x}\n".format(getattr(self,k))
- r += "payload: "
- for d in self:
- r += "{:02x}".format(d)
- return r
+ def __init__(self, init=[]):
+ Packet.__init__(self, init)
+ self.preamble_error = False
+ self.crc_error = False
+
+ def check_remove_preamble(self):
+ if comp(self[0:8], preamble):
+ for i in range(8):
+ self.pop(0)
+ return False
+ else:
+ return True
+
+ def check_remove_crc(self):
+ if comp(self[-4:], crc32(self[:-4])):
+ for i in range(4):
+ self.pop()
+ return False
+ else:
+ return True
+
+ def decode_remove_header(self):
+ header = []
+ for byte in self[:mac_header_len]:
+ header.append(self.pop(0))
+ for k, v in sorted(mac_header.items()):
+ setattr(self, k, get_field_data(v, header))
+
+ def decode(self):
+ self.preamble_error = self.check_remove_preamble()
+ self.crc_error = self.check_remove_crc()
+ if self.crc_error or self.preamble_error:
+ raise ValueError # XXX handle this properly
+ else:
+ self.decode_remove_header()
+
+ def encode_header(self):
+ header = 0
+ for k, v in sorted(mac_header.items()):
+ value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
+ header += (value << v.offset+(v.byte*8))
+ for d in split_bytes(header, mac_header_len):
+ self.insert(0, d)
+
+ def insert_crc(self):
+ for d in crc32(self):
+ self.append(d)
+
+ def insert_preamble(self):
+ for d in reversed(preamble):
+ self.insert(0, d)
+
+ def encode(self):
+ self.encode_header()
+ self.insert_crc()
+ self.insert_preamble()
+
+ def __repr__(self):
+ r = "--------\n"
+ for k in sorted(mac_header.keys()):
+ r += k + " : 0x{:0x}\n".format(getattr(self,k))
+ r += "payload: "
+ for d in self:
+ r += "{:02x}".format(d)
+ return r
class MAC(Module):
- def __init__(self, phy, debug=False, loopback=False):
- self.phy = phy
- self.debug = debug
- self.loopback = loopback
- self.rx_packet = MACPacket()
-
- self.ip_callback = None
- self.arp_callback = None
-
- phy.set_mac_callback(self.callback)
-
- def set_ip_callback(self, callback):
- self.ip_callback = callback
-
- def set_arp_callback(self, callback):
- self.arp_callback = callback
-
- def send(self, packet):
- if self.debug:
- print_mac(">>>>>>>>")
- print_mac(packet)
- packet.encode()
- self.phy.send(packet)
-
- def callback(self, datas):
- packet = MACPacket(datas)
- packet.decode()
- if self.debug:
- print_mac("<<<<<<<<")
- print_mac(packet)
- if self.loopback:
- self.send(packet)
- else:
- if packet.ethernet_type == ethernet_type_ip:
- if self.ip_callback is not None:
- self.ip_callback(packet)
- elif packet.ethernet_type == ethernet_type_arp:
- if self.arp_callback is not None:
- self.arp_callback(packet)
- else:
- raise ValueError # XXX handle this properly
+ def __init__(self, phy, debug=False, loopback=False):
+ self.phy = phy
+ self.debug = debug
+ self.loopback = loopback
+ self.rx_packet = MACPacket()
+
+ self.ip_callback = None
+ self.arp_callback = None
+
+ phy.set_mac_callback(self.callback)
+
+ def set_ip_callback(self, callback):
+ self.ip_callback = callback
+
+ def set_arp_callback(self, callback):
+ self.arp_callback = callback
+
+ def send(self, packet):
+ if self.debug:
+ print_mac(">>>>>>>>")
+ print_mac(packet)
+ packet.encode()
+ self.phy.send(packet)
+
+ def callback(self, datas):
+ packet = MACPacket(datas)
+ packet.decode()
+ if self.debug:
+ print_mac("<<<<<<<<")
+ print_mac(packet)
+ if self.loopback:
+ self.send(packet)
+ else:
+ if packet.ethernet_type == ethernet_type_ip:
+ if self.ip_callback is not None:
+ self.ip_callback(packet)
+ elif packet.ethernet_type == ethernet_type_arp:
+ if self.arp_callback is not None:
+ self.arp_callback(packet)
+ else:
+ raise ValueError # XXX handle this properly
if __name__ == "__main__":
- from misoclib.com.liteeth.test.model.dumps import *
- errors = 0
- packet = MACPacket(arp_request)
- packet.decode_remove_header()
- #print(packet)
- errors += verify_packet(packet, arp_request_infos)
- packet.encode_header()
- packet.decode_remove_header()
- #print(packet)
- errors += verify_packet(packet, arp_request_infos)
-
- #print(packet)
- packet = MACPacket(arp_reply)
- packet.decode_remove_header()
- errors += verify_packet(packet, arp_reply_infos)
- packet.encode_header()
- packet.decode_remove_header()
- #print(packet)
- errors += verify_packet(packet, arp_reply_infos)
-
- print("mac errors " + str(errors))
+ from misoclib.com.liteeth.test.model.dumps import *
+ errors = 0
+ packet = MACPacket(arp_request)
+ packet.decode_remove_header()
+ #print(packet)
+ errors += verify_packet(packet, arp_request_infos)
+ packet.encode_header()
+ packet.decode_remove_header()
+ #print(packet)
+ errors += verify_packet(packet, arp_request_infos)
+
+ #print(packet)
+ packet = MACPacket(arp_reply)
+ packet.decode_remove_header()
+ errors += verify_packet(packet, arp_reply_infos)
+ packet.encode_header()
+ packet.decode_remove_header()
+ #print(packet)
+ errors += verify_packet(packet, arp_reply_infos)
+
+ print("mac errors " + str(errors))
from misoclib.com.liteeth.test.common import *
def print_phy(s):
- print_with_prefix(s, "[PHY]")
+ print_with_prefix(s, "[PHY]")
# PHY model
class PHYSource(PacketStreamer):
- def __init__(self, dw):
- PacketStreamer.__init__(self, eth_phy_description(dw))
+ def __init__(self, dw):
+ PacketStreamer.__init__(self, eth_phy_description(dw))
class PHYSink(PacketLogger):
- def __init__(self, dw):
- PacketLogger.__init__(self, eth_phy_description(dw))
+ def __init__(self, dw):
+ PacketLogger.__init__(self, eth_phy_description(dw))
class PHY(Module):
- def __init__(self, dw, debug=False):
- self.dw = dw
- self.debug = debug
-
- self.submodules.phy_source = PHYSource(dw)
- self.submodules.phy_sink = PHYSink(dw)
-
- self.source = self.phy_source.source
- self.sink = self.phy_sink.sink
-
- self.mac_callback = None
-
- def set_mac_callback(self, callback):
- self.mac_callback = callback
-
- def send(self, datas):
- packet = Packet(datas)
- if self.debug:
- r = ">>>>>>>>\n"
- r += "length " + str(len(datas)) + "\n"
- for d in datas:
- r += "{:02x}".format(d)
- print_phy(r)
- self.phy_source.send(packet)
-
- def receive(self):
- yield from self.phy_sink.receive()
- if self.debug:
- r = "<<<<<<<<\n"
- r += "length " + str(len(self.phy_sink.packet)) + "\n"
- for d in self.phy_sink.packet:
- r += "{:02x}".format(d)
- print_phy(r)
- self.packet = self.phy_sink.packet
-
- def gen_simulation(self, selfp):
- while True:
- yield from self.receive()
- if self.mac_callback is not None:
- self.mac_callback(self.packet)
+ def __init__(self, dw, debug=False):
+ self.dw = dw
+ self.debug = debug
+
+ self.submodules.phy_source = PHYSource(dw)
+ self.submodules.phy_sink = PHYSink(dw)
+
+ self.source = self.phy_source.source
+ self.sink = self.phy_sink.sink
+
+ self.mac_callback = None
+
+ def set_mac_callback(self, callback):
+ self.mac_callback = callback
+
+ def send(self, datas):
+ packet = Packet(datas)
+ if self.debug:
+ r = ">>>>>>>>\n"
+ r += "length " + str(len(datas)) + "\n"
+ for d in datas:
+ r += "{:02x}".format(d)
+ print_phy(r)
+ self.phy_source.send(packet)
+
+ def receive(self):
+ yield from self.phy_sink.receive()
+ if self.debug:
+ r = "<<<<<<<<\n"
+ r += "length " + str(len(self.phy_sink.packet)) + "\n"
+ for d in self.phy_sink.packet:
+ r += "{:02x}".format(d)
+ print_phy(r)
+ self.packet = self.phy_sink.packet
+
+ def gen_simulation(self, selfp):
+ while True:
+ yield from self.receive()
+ if self.mac_callback is not None:
+ self.mac_callback(self.packet)
from misoclib.com.liteeth.test.model import ip
def print_udp(s):
- print_with_prefix(s, "[UDP]")
+ print_with_prefix(s, "[UDP]")
# UDP model
class UDPPacket(Packet):
- def __init__(self, init=[]):
- Packet.__init__(self, init)
-
- def decode(self):
- header = []
- for byte in self[:udp_header_len]:
- header.append(self.pop(0))
- for k, v in sorted(udp_header.items()):
- setattr(self, k, get_field_data(v, header))
-
- def encode(self):
- header = 0
- for k, v in sorted(udp_header.items()):
- value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
- header += (value << v.offset+(v.byte*8))
- for d in split_bytes(header, udp_header_len):
- self.insert(0, d)
-
- def __repr__(self):
- r = "--------\n"
- for k in sorted(udp_header.keys()):
- r += k + " : 0x{:0x}\n".format(getattr(self,k))
- r += "payload: "
- for d in self:
- r += "{:02x}".format(d)
- return r
+ def __init__(self, init=[]):
+ Packet.__init__(self, init)
+
+ def decode(self):
+ header = []
+ for byte in self[:udp_header_len]:
+ header.append(self.pop(0))
+ for k, v in sorted(udp_header.items()):
+ setattr(self, k, get_field_data(v, header))
+
+ def encode(self):
+ header = 0
+ for k, v in sorted(udp_header.items()):
+ value = merge_bytes(split_bytes(getattr(self, k), math.ceil(v.width/8)), "little")
+ header += (value << v.offset+(v.byte*8))
+ for d in split_bytes(header, udp_header_len):
+ self.insert(0, d)
+
+ def __repr__(self):
+ r = "--------\n"
+ for k in sorted(udp_header.keys()):
+ r += k + " : 0x{:0x}\n".format(getattr(self,k))
+ r += "payload: "
+ for d in self:
+ r += "{:02x}".format(d)
+ return r
class UDP(Module):
- def __init__(self, ip, ip_address, debug=False, loopback=False):
- self.ip = ip
- self.ip_address = ip_address
- self.debug = debug
- self.loopback = loopback
- self.tx_packets = []
- self.tx_packet = UDPPacket()
- self.rx_packet = UDPPacket()
-
- self.etherbone_callback = None
-
- self.ip.set_udp_callback(self.callback)
-
- def set_etherbone_callback(self, callback):
- self.etherbone_callback = callback
-
- def send(self, packet):
- packet.encode()
- if self.debug:
- print_udp(">>>>>>>>")
- print_udp(packet)
- ip_packet = ip.IPPacket(packet)
- ip_packet.version = 0x4
- ip_packet.ihl = 0x5
- ip_packet.total_length = len(packet) + ip_packet.ihl
- ip_packet.identification = 0
- ip_packet.flags = 0
- ip_packet.fragment_offset = 0
- ip_packet.ttl = 0x80
- ip_packet.sender_ip = self.ip_address
- ip_packet.target_ip = 0x12345678 # XXX
- ip_packet.checksum = 0
- ip_packet.protocol = udp_protocol
- self.ip.send(ip_packet)
-
- def callback(self, packet):
- packet = UDPPacket(packet)
- packet.decode()
- if self.debug:
- print_udp("<<<<<<<<")
- print_udp(packet)
- if self.loopback:
- self.send(packet)
- else:
- self.process(packet)
-
- def process(self, packet):
- if packet.dst_port == 20000:
- if self.etherbone_callback is not None:
- self.etherbone_callback(packet)
+ def __init__(self, ip, ip_address, debug=False, loopback=False):
+ self.ip = ip
+ self.ip_address = ip_address
+ self.debug = debug
+ self.loopback = loopback
+ self.tx_packets = []
+ self.tx_packet = UDPPacket()
+ self.rx_packet = UDPPacket()
+
+ self.etherbone_callback = None
+
+ self.ip.set_udp_callback(self.callback)
+
+ def set_etherbone_callback(self, callback):
+ self.etherbone_callback = callback
+
+ def send(self, packet):
+ packet.encode()
+ if self.debug:
+ print_udp(">>>>>>>>")
+ print_udp(packet)
+ ip_packet = ip.IPPacket(packet)
+ ip_packet.version = 0x4
+ ip_packet.ihl = 0x5
+ ip_packet.total_length = len(packet) + ip_packet.ihl
+ ip_packet.identification = 0
+ ip_packet.flags = 0
+ ip_packet.fragment_offset = 0
+ ip_packet.ttl = 0x80
+ ip_packet.sender_ip = self.ip_address
+ ip_packet.target_ip = 0x12345678 # XXX
+ ip_packet.checksum = 0
+ ip_packet.protocol = udp_protocol
+ self.ip.send(ip_packet)
+
+ def callback(self, packet):
+ packet = UDPPacket(packet)
+ packet.decode()
+ if self.debug:
+ print_udp("<<<<<<<<")
+ print_udp(packet)
+ if self.loopback:
+ self.send(packet)
+ else:
+ self.process(packet)
+
+ def process(self, packet):
+ if packet.dst_port == 20000:
+ if self.etherbone_callback is not None:
+ self.etherbone_callback(packet)
if __name__ == "__main__":
- from misoclib.com.liteeth.test.model.dumps import *
- from misoclib.com.liteeth.test.model.mac import *
- from misoclib.com.liteeth.test.model.ip import *
- errors = 0
- # UDP packet
- packet = MACPacket(udp)
- packet.decode_remove_header()
- #print(packet)
- packet = IPPacket(packet)
- packet.decode()
- #print(packet)
- packet = UDPPacket(packet)
- packet.decode()
- #print(packet)
- if packet.length != (len(packet)+udp_header_len):
- errors += 1
- errors += verify_packet(packet, udp_infos)
- packet.encode()
- packet.decode()
- #print(packet)
- if packet.length != (len(packet)+udp_header_len):
- errors += 1
- errors += verify_packet(packet, udp_infos)
-
- print("udp errors " + str(errors))
\ No newline at end of file
+ from misoclib.com.liteeth.test.model.dumps import *
+ from misoclib.com.liteeth.test.model.mac import *
+ from misoclib.com.liteeth.test.model.ip import *
+ errors = 0
+ # UDP packet
+ packet = MACPacket(udp)
+ packet.decode_remove_header()
+ #print(packet)
+ packet = IPPacket(packet)
+ packet.decode()
+ #print(packet)
+ packet = UDPPacket(packet)
+ packet.decode()
+ #print(packet)
+ if packet.length != (len(packet)+udp_header_len):
+ errors += 1
+ errors += verify_packet(packet, udp_infos)
+ packet.encode()
+ packet.decode()
+ #print(packet)
+ if packet.length != (len(packet)+udp_header_len):
+ errors += 1
+ errors += verify_packet(packet, udp_infos)
+
+ print("udp errors " + str(errors))
\ No newline at end of file
mac_address = 0x12345678abcd
class TB(Module):
- def __init__(self, dw=8):
- self.dw = dw
- self.submodules.phy_model = phy.PHY(8, debug=False)
- self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
- self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
- self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False)
- self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=True)
+ def __init__(self, dw=8):
+ self.dw = dw
+ self.submodules.phy_model = phy.PHY(8, debug=False)
+ self.submodules.mac_model = mac.MAC(self.phy_model, debug=False, loopback=False)
+ self.submodules.arp_model = arp.ARP(self.mac_model, mac_address, ip_address, debug=False)
+ self.submodules.ip_model = ip.IP(self.mac_model, mac_address, ip_address, debug=False, loopback=False)
+ self.submodules.udp_model = udp.UDP(self.ip_model, ip_address, debug=False, loopback=True)
- self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000)
- udp_port = self.core.udp.crossbar.get_port(0x5678, dw)
- self.submodules.streamer = PacketStreamer(eth_udp_user_description(dw))
- self.submodules.logger = PacketLogger(eth_udp_user_description(dw))
- self.comb += [
- Record.connect(self.streamer.source, udp_port.sink),
- udp_port.sink.ip_address.eq(0x12345678),
- udp_port.sink.src_port.eq(0x1234),
- udp_port.sink.dst_port.eq(0x5678),
- udp_port.sink.length.eq(64//(dw//8)),
- Record.connect(udp_port.source, self.logger.sink)
- ]
+ self.submodules.core = LiteEthUDPIPCore(self.phy_model, mac_address, ip_address, 100000)
+ udp_port = self.core.udp.crossbar.get_port(0x5678, dw)
+ self.submodules.streamer = PacketStreamer(eth_udp_user_description(dw))
+ self.submodules.logger = PacketLogger(eth_udp_user_description(dw))
+ self.comb += [
+ Record.connect(self.streamer.source, udp_port.sink),
+ udp_port.sink.ip_address.eq(0x12345678),
+ udp_port.sink.src_port.eq(0x1234),
+ udp_port.sink.dst_port.eq(0x5678),
+ udp_port.sink.length.eq(64//(dw//8)),
+ Record.connect(udp_port.source, self.logger.sink)
+ ]
- # 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()),
- ]
+ # 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
+ 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
- for i in range(100):
- yield
+ for i in range(100):
+ yield
- while True:
- packet = Packet([i for i in range(64//(self.dw//8))])
- yield from self.streamer.send(packet)
- yield from self.logger.receive()
+ while True:
+ packet = Packet([i for i in range(64//(self.dw//8))])
+ yield from self.streamer.send(packet)
+ yield from self.logger.receive()
- # check results
- s, l, e = check(packet, self.logger.packet)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ # check results
+ s, l, e = check(packet, self.logger.packet)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- run_simulation(TB(8), ncycles=2048, vcd_name="my.vcd", keep_files=True)
- run_simulation(TB(16), ncycles=2048, vcd_name="my.vcd", keep_files=True)
- run_simulation(TB(32), ncycles=2048, vcd_name="my.vcd", keep_files=True)
\ No newline at end of file
+ run_simulation(TB(8), ncycles=2048, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(16), ncycles=2048, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(32), ncycles=2048, vcd_name="my.vcd", keep_files=True)
\ No newline at end of file