diff --git a/luna/gateware/stream/generator.py b/luna/gateware/stream/generator.py index 81a99e0..ee14345 100644 --- a/luna/gateware/stream/generator.py +++ b/luna/gateware/stream/generator.py @@ -177,6 +177,9 @@ class ConstantStreamGenerator(Elaboratable): (position_in_stream == (data_length - 1)) | \ (bytes_sent + bytes_per_word >= self.max_length) + on_packet_end = position_in_stream[:6] == 63 + on_packet_start = position_in_stream[:6] == 0 + # # Output length field. @@ -211,6 +214,14 @@ class ConstantStreamGenerator(Elaboratable): m.next = 'STREAMING' + # WAITING -- we've finished one packet and are waiting to send the next. + with m.State('WAITING'): + + # Once the user requests that we start, move to our stream being valid. + with m.If(self.start & (self.max_length > 0)): + m.next = 'STREAMING' + + # STREAMING -- we're actively transmitting data with m.State('STREAMING'): m.d.comb += [ @@ -219,8 +230,8 @@ class ConstantStreamGenerator(Elaboratable): self.stream.payload .eq(rom_read_port.data), ## ... and base First and Last based on our current position in the stream. - self.stream.first .eq(on_first_packet), - self.stream.last .eq(on_last_packet) + self.stream.first .eq(on_first_packet | on_packet_start), + self.stream.last .eq(on_last_packet | on_packet_end) ] # Our ``valid`` flag requires a bunch of special handling, since it could be @@ -295,6 +306,9 @@ class ConstantStreamGenerator(Elaboratable): # If the current data byte is accepted, move past it. with m.If(self.stream.ready): + with m.If(on_packet_end): + m.next = 'WAITING' + # If there's still data left to transmit, move forward. with m.If(~on_last_packet): m.d.sync += position_in_stream.eq(position_in_stream + 1) diff --git a/luna/gateware/usb/usb2/control.py b/luna/gateware/usb/usb2/control.py index 9fcb67b..956a89f 100644 --- a/luna/gateware/usb/usb2/control.py +++ b/luna/gateware/usb/usb2/control.py @@ -200,7 +200,7 @@ class USBControlEndpoint(Elaboratable): # Fix our data PIDs to DATA1, for now, as we don't support multi-packet responses, yet. # Per [USB2.0: 8.5.3], the first packet of the DATA or STATUS phase always carries a DATA1 PID. - interface.tx_pid_toggle.eq(1) + #interface.tx_pid_toggle.eq(1) ] @@ -218,6 +218,8 @@ class USBControlEndpoint(Elaboratable): # We won't do anything until we receive a SETUP token. with m.If(setup_decoder.packet.received & endpoint_targeted): + m.d.usb += interface.tx_pid_toggle.eq(1) + # If our SETUP packet indicates we'll have a data stage (wLength > 0) # move to the DATA stage. Otherwise, move directly to the status stage [8.5.3]. with m.If(setup_decoder.packet.length): @@ -245,6 +247,9 @@ class USBControlEndpoint(Elaboratable): # Notify the request handler to prepare a response. m.d.comb += request_handler.data_requested.eq(1) + with m.If(request_handler.tx.valid & request_handler.tx.ready & request_handler.tx.last): + m.d.usb += interface.tx_pid_toggle[0].eq(~interface.tx_pid_toggle[0]) + # Once we get an OUT token, we should move on to the STATUS stage. [USB2, 8.5.3] with m.If(endpoint_targeted & interface.tokenizer.new_token & interface.tokenizer.is_out): m.next = 'STATUS_OUT'