Skip to content

Commit

Permalink
gateware.usb2: USBInTransferManager - toggle DATA pid when sending ZLP
Browse files Browse the repository at this point in the history
Previously the pid was not toggled because it was tied to buffer
swapping and we stay on the same buffer when sending a ZLP.

This separates the buffer toggle & the pid value signals, and fixes the
missing pid toggle on sending a ZLP.

fixes #127
  • Loading branch information
ronyrus1 authored and miek committed Aug 19, 2021
1 parent e56a3ee commit 273be7c
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions luna/gateware/usb/usb2/transfer.py
Expand Up @@ -86,6 +86,7 @@ def __init__(self, max_packet_size):
# Note: we'll start with DATA1 in our register; as we'll toggle our data PID
# before we send.
self.data_pid = Signal(2, reset=1)
self.buffer_toggle = Signal()

self.tokenizer = TokenDetectorInterface()
self.handshakes_in = HandshakeExchangeInterface(is_detector=True)
Expand Down Expand Up @@ -126,8 +127,6 @@ def elaborate(self, platform):
#

# We'll create two buffers; so we can fill one as we empty the other.
# Since each buffer will be used for every other transaction, and our PID toggle flips every other transcation,
# we'll identify which buffer we're targeting by the current PID toggle.
buffer = Array(Memory(width=8, depth=self._max_packet_size, name=f"transmit_buffer_{i}") for i in range(2))
buffer_write_ports = Array(buffer[i].write_port(domain="usb") for i in range(2))
buffer_read_ports = Array(buffer[i].read_port(domain="usb") for i in range(2))
Expand All @@ -137,8 +136,8 @@ def elaborate(self, platform):

# Create values equivalent to the buffer numbers for our read and write buffer; which switch
# whenever we swap our two buffers.
write_buffer_number = self.data_pid[0]
read_buffer_number = ~self.data_pid[0]
write_buffer_number = self.buffer_toggle
read_buffer_number = ~self.buffer_toggle

# Create a shorthand that refers to the buffer to be filled; and the buffer to send from.
# We'll call these the Read and Write buffers.
Expand Down Expand Up @@ -227,6 +226,7 @@ def elaborate(self, platform):

# We're now ready to take the data we've captured and _transmit_ it.
# We'll swap our read and write buffers, and toggle our data PID.
self.buffer_toggle .eq(~self.buffer_toggle),
self.data_pid[0] .eq(~self.data_pid[0]),

# Mark our current stream as no longer having ended.
Expand Down Expand Up @@ -309,6 +309,7 @@ def elaborate(self, platform):
# If we're following up with a ZLP, move back to our "wait to send" state.
# Since we've now cleared our fill count; this next go-around will emit a ZLP.
with m.If(follow_up_with_zlp):
m.d.usb += self.data_pid[0].eq(~self.data_pid[0]),
m.next = "WAIT_TO_SEND"

# Otherwise, there's a possibility we already have a packet-worth of data waiting
Expand All @@ -319,6 +320,7 @@ def elaborate(self, platform):
with m.Elif(~in_stream.ready | packet_completing):
m.next = "WAIT_TO_SEND"
m.d.usb += [
self.buffer_toggle .eq(~self.buffer_toggle),
self.data_pid[0] .eq(~self.data_pid[0]),
read_stream_ended .eq(0)
]
Expand Down Expand Up @@ -483,6 +485,7 @@ def test_zlp_generation(self):
for value in [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]:
self.assertEqual((yield packet_stream.payload), value)
yield
yield self.assertEqual((yield dut.data_pid), 0)
yield from self.pulse(dut.handshakes_in.ack)


Expand All @@ -505,11 +508,13 @@ def test_zlp_generation(self):
for value in [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]:
self.assertEqual((yield packet_stream.payload), value)
yield
self.assertEqual((yield dut.data_pid), 1)
yield from self.pulse(dut.handshakes_in.ack)

# ... followed by a ZLP.
yield from self.pulse(dut.tokenizer.ready_for_response, step_after=False)
self.assertEqual((yield packet_stream.last), 1)
self.assertEqual((yield dut.data_pid), 0)
yield from self.pulse(dut.handshakes_in.ack)


Expand All @@ -531,6 +536,7 @@ def test_zlp_generation(self):
self.assertEqual((yield packet_stream.payload), value)
yield
yield from self.pulse(dut.handshakes_in.ack)
self.assertEqual((yield dut.data_pid), 1)


# ... and we shouldn't emit a ZLP; meaning we should be ready to receive new data.
Expand Down

0 comments on commit 273be7c

Please sign in to comment.