diff --git a/.gitmodules b/.gitmodules index c5fad37..c382199 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "software/fpga/migen"] path = software/fpga/migen - url = git://github.com/m-labs/migen.git + url = https://github.com/m-labs/migen.git [submodule "software/fpga/misoc"] path = software/fpga/misoc url = https://github.com/m-labs/misoc diff --git a/software/fpga/migen b/software/fpga/migen index cff127d..12eb563 160000 --- a/software/fpga/migen +++ b/software/fpga/migen @@ -1 +1 @@ -Subproject commit cff127daae3a495d66726fac030a0cf37c5fd8f9 +Subproject commit 12eb563e89ffc4a5e046239171207c9476f8f665 diff --git a/software/fpga/misoc b/software/fpga/misoc index 57ebe11..26f039f 160000 --- a/software/fpga/misoc +++ b/software/fpga/misoc @@ -1 +1 @@ -Subproject commit 57ebe119d80beabad30d232fc3c9229882042807 +Subproject commit 26f039f9f6931a20a04ccd0f0a5402f67f553916 diff --git a/software/fpga/ov3/ovhw/constants.py b/software/fpga/ov3/ovhw/constants.py index 6e1c1d7..770c9f6 100644 --- a/software/fpga/ov3/ovhw/constants.py +++ b/software/fpga/ov3/ovhw/constants.py @@ -5,6 +5,8 @@ RXCMD_MASK = 0xBF +# 1 byte PID + (HS interrupt/isochronous) 1024 bytes data + 2 byte CRC +MAX_PACKET_SIZE = 1027 # Physical layer error HF0_ERR = 0x01 @@ -15,7 +17,7 @@ # Clipped by Filter HF0_CLIP = 0x04 -# Clipped due to packet length (> 800 bytes) +# Clipped due to packet length (> MAX_PACKET_SIZE bytes) HF0_TRUNC = 0x08 # First packet of capture session; IE, when the cap hardware was enabled diff --git a/software/fpga/ov3/ovhw/ftdi_bus.py b/software/fpga/ov3/ovhw/ftdi_bus.py index e288e59..d7a1f43 100644 --- a/software/fpga/ov3/ovhw/ftdi_bus.py +++ b/software/fpga/ov3/ovhw/ftdi_bus.py @@ -1,4 +1,5 @@ from migen import * +from migen.genlib.cdc import MultiReg from migen.genlib.fsm import * from migen.genlib.fifo import * diff --git a/software/fpga/ov3/ovhw/top.py b/software/fpga/ov3/ovhw/top.py index e206e05..9fc8f80 100644 --- a/software/fpga/ov3/ovhw/top.py +++ b/software/fpga/ov3/ovhw/top.py @@ -98,7 +98,7 @@ def __init__(self, plat): ) self.submodules.cfilt = RXCmdFilter() - self.submodules.cstream = Whacker(1024) + self.submodules.cstream = Whacker(2048) self.comb += [ self.ulpi.data_out_source.connect(self.ovf_insert.sink), diff --git a/software/fpga/ov3/ovhw/whacker/producer.py b/software/fpga/ov3/ovhw/whacker/producer.py index 1660fac..34e82ea 100644 --- a/software/fpga/ov3/ovhw/whacker/producer.py +++ b/software/fpga/ov3/ovhw/whacker/producer.py @@ -7,7 +7,6 @@ from ovhw.constants import * from ovhw.whacker.util import * -MAX_PACKET_SIZE = 800 class Producer(Module): def __init__(self, wrport, depth, consume_watermark, ena, la_filters=[]): @@ -22,7 +21,7 @@ def __init__(self, wrport, depth, consume_watermark, ena, la_filters=[]): self.consume_point = Acc(max=depth) - self.submodules.size = Acc_inc(16) + self.submodules.size = Acc_inc_sat(16) self.submodules.flags = Acc_or(16) self.submodules.to_start = Acc(1) @@ -146,10 +145,7 @@ def write_hdr(statename, nextname, hdr_offs, val): self.comb += packet_too_long.eq(self.size.v >= MAX_PACKET_SIZE) self.fsm.act("DATA", - If(packet_too_long, - self.flags._or(HF0_TRUNC), - NextState("WH0") - ).Elif(has_space & self.ulpi_sink.stb, + If(has_space & self.ulpi_sink.stb, self.ulpi_sink.ack.eq(1), If(payload_is_rxcmd, @@ -173,11 +169,15 @@ def write_hdr(statename, nextname, hdr_offs, val): NextState("waitdone") ).Else( self.size.inc(), - self.produce_write.inc(), - wrport.adr.eq(self.produce_write.v), - wrport.dat_w.eq(self.ulpi_sink.payload.d), - wrport.we.eq(1), - do_filter_write.eq(1) + If(packet_too_long, + self.flags._or(HF0_TRUNC) + ).Else( + self.produce_write.inc(), + wrport.adr.eq(self.produce_write.v), + wrport.dat_w.eq(self.ulpi_sink.payload.d), + wrport.we.eq(1), + do_filter_write.eq(1) + ) ) ) ) @@ -209,7 +209,11 @@ def write_hdr(statename, nextname, hdr_offs, val): self.fsm.act("SEND", self.out_addr.stb.eq(1), self.out_addr.payload.start.eq(self.produce_header.v), - self.out_addr.payload.count.eq(self.size.v + 8), + If(packet_too_long, + self.out_addr.payload.count.eq(MAX_PACKET_SIZE + 8) + ).Else( + self.out_addr.payload.count.eq(self.size.v + 8), + ), If(self.out_addr.ack, self.produce_header.set(self.produce_write.v), NextState("IDLE") diff --git a/software/fpga/ov3/ovhw/whacker/whacker.py b/software/fpga/ov3/ovhw/whacker/whacker.py index d344fd4..445e5f0 100644 --- a/software/fpga/ov3/ovhw/whacker/whacker.py +++ b/software/fpga/ov3/ovhw/whacker/whacker.py @@ -108,7 +108,7 @@ def __init__(self): self.source = Endpoint(ULPI_DATA_D) SimActor.__init__(self, gen()) - self.submodules.w = Whacker(1024) + self.submodules.w = Whacker(2048) self.submodules.src = SimSource() self.comb += self.src.source.connect(self.w.sink) diff --git a/software/host/LibOV.py b/software/host/LibOV.py index 26265fc..02aa843 100644 --- a/software/host/LibOV.py +++ b/software/host/LibOV.py @@ -412,13 +412,15 @@ def stats(self): def hd(x): return " ".join("%02x" % i for i in x) +MAX_PACKET_SIZE = 1027 + # Physical layer error HF0_ERR = 0x01 # RX Path Overflow HF0_OVF = 0x02 # Clipped by Filter HF0_CLIP = 0x04 -# Clipped due to packet length (> 800 bytes) +# Clipped due to packet length (> MAX_PACKET_SIZE bytes) HF0_TRUNC = 0x08 # First packet of capture session; IE, when the cap hardware was enabled HF0_FIRST = 0x10 @@ -467,13 +469,16 @@ def getPacketSize(self, buf): return 2 else: #print("SIZING: %s" % " ".join("%02x" %i for i in buf)) + flags = buf[1] | buf[2] << 8 + if flags & HF0_TRUNC: + return MAX_PACKET_SIZE + 8 return (buf[4] << 8 | buf[3]) + 8 def consume(self, buf): if buf[0] == 0xA0: flags = buf[1] | buf[2] << 8 - + orig_len = buf[4] << 8 | buf[3] ts = buf[5] | buf[6] << 8 | buf[7] << 16 if flags != 0 and flags != HF0_FIRST and flags != HF0_LAST: @@ -483,18 +488,18 @@ def consume(self, buf): self.got_start = True if self.got_start: - self.handle_usb(ts, buf[8:], flags) + self.handle_usb(ts, buf[8:], flags, orig_len) if flags & HF0_LAST: self.got_start = False - def handle_usb(self, ts, buf, flags): + def handle_usb(self, ts, buf, flags, orig_len): for handler in self.handlers: - handler(ts, buf, flags) + handler(ts, buf, flags, orig_len) - def handle_usb_verbose(self, ts, buf, flags): + def handle_usb_verbose(self, ts, buf, flags, orig_len): # ChandlePacket(ts, flags, buf, len(buf)) - self.ui.handlePacket(ts, buf, flags) + self.ui.handlePacket(ts, buf, flags, orig_len) def __init__(self): diff --git a/software/host/ov3.fwpkg b/software/host/ov3.fwpkg index 4697951..c381bba 100644 Binary files a/software/host/ov3.fwpkg and b/software/host/ov3.fwpkg differ diff --git a/software/host/ovctl.py b/software/host/ovctl.py index 337b2fc..29c82e8 100755 --- a/software/host/ovctl.py +++ b/software/host/ovctl.py @@ -147,7 +147,7 @@ def __init__(self, output, speed): except: self.template = "data=%s speed=%s time=%f\n" - def handle_usb(self, ts, pkt, flags): + def handle_usb(self, ts, pkt, flags, orig_len): if ts < self.last_ts: self.ts_offset += 0x1000000 self.last_ts = ts @@ -162,7 +162,7 @@ def __init__(self, output, speed): self.ts_offset = 0 self.ts_last = None - def handle_usb(self, ts, pkt, flags): + def handle_usb(self, ts, pkt, flags, orig_len): buf = [] # Skip SOF and empty packets @@ -217,7 +217,7 @@ def __init__(self, output): self.last_ts = 0 self.ts_offset = 0 - def handle_usb(self, ts, pkt, flags): + def handle_usb(self, ts, pkt, flags, orig_len): # Increment timestamp based on the 60 MHz 24-bit counter value. # Convert remaining clocks to nanoseconds: 1 clk = 1 / 60 MHz = 16.(6) ns if ts < self.last_ts: @@ -232,10 +232,7 @@ def handle_usb(self, ts, pkt, flags): if len(pkt) == 0: return # Write pcap record header in host endian - # TODO: FPGA does not provide us with the untruncated packet length thus incl_len is set to orig_len - # When (and if) FPGA does indicate the length of truncated packets, change the record header to - # contain different incl_len (len(pkt)) and orig_len (untruncated packet size) - self.output.write(struct.pack("IIII", self.utc_ts, nanosec, len(pkt), len(pkt))) + self.output.write(struct.pack("IIII", self.utc_ts, nanosec, len(pkt), orig_len)) # Write USB packet, beginning with a PID as it appeared on the bus self.output.write(pkt) diff --git a/software/host/usb_interp.py b/software/host/usb_interp.py index e26f9e5..387c265 100644 --- a/software/host/usb_interp.py +++ b/software/host/usb_interp.py @@ -18,7 +18,7 @@ def __init__(self, highspeed): self.ts_base = 0 self.ts_roll_cyc = 2**24 - def handlePacket(self, ts, buf, flags): + def handlePacket(self, ts, buf, flags, orig_len): CRC_BAD = 1 CRC_GOOD = 2 CRC_NONE = 3 @@ -75,7 +75,9 @@ def handlePacket(self, ts, buf, flags): msg += "DATA%d: %s" % (n,hd(buf[1:])) - if len(buf) > 2: + if orig_len > len(buf): + msg += "\tTruncated %d bytes" % (orig_len - len(buf)) + elif len(buf) > 2: calc_check = self.data_crc(buf[1:-2])^0xFFFF pkt_check = buf[-2] | buf[-1] << 8