Source code for usbcore.rx.detect

#!/usr/bin/env python3

from migen import *
from migen.genlib import cdc

from migen.fhdl.decorators import ResetInserter

from ..test.common import BaseUsbTestCase
import unittest


[docs]@ResetInserter() class RxPacketDetect(Module): """Packet Detection Full Speed packets begin with the following sequence: KJKJKJKK This raw sequence corresponds to the following data: 00000001 The bus idle condition is signaled with the J state: JJJJJJJJ This translates to a series of '1's since there are no transitions. Given this information, it is easy to detect the beginning of a packet by looking for 00000001. The end of a packet is even easier to detect. The end of a packet is signaled with two SE0 and one J. We can just look for the first SE0 to detect the end of the packet. Packet detection can occur in parallel with bitstuff removal. https://www.pjrc.com/teensy/beta/usb20.pdf, USB2 Spec, 7.1.10 Input Ports ------------ i_valid : Signal(1) Qualifier for all of the input signals. Indicates one bit of valid data is present on the inputs. i_data : Signal(1) Decoded data bit from USB bus. Qualified by valid. i_se0 : Signal(1) Indicator for SE0 from USB bus. Qualified by valid. Output Ports ------------ o_pkt_start : Signal(1) Asserted for one clock on the last bit of the sync. o_pkt_active : Signal(1) Asserted while in the middle of a packet. o_pkt_end : Signal(1) Asserted for one clock after the last data bit of a packet was received. """ def __init__(self): self.i_valid = Signal() self.i_data = Signal() self.i_se0 = Signal() self.submodules.pkt = pkt = FSM() pkt_start = Signal() pkt_active = Signal() pkt_end = Signal() for i in range(5): pkt.act("D%d" % i, If(self.i_valid, If(self.i_data | self.i_se0, # Receiving '1' or SE0 early resets the packet start counter. NextState("D0") ).Else( # Receiving '0' increments the packet start counter. NextState("D%d" % (i + 1)) ) ) ) pkt.act("D5", If(self.i_valid, If(self.i_se0, NextState("D0") # once we get a '1', the packet is active ).Elif(self.i_data, pkt_start.eq(1), NextState("PKT_ACTIVE") ) ) ) pkt.act("PKT_ACTIVE", pkt_active.eq(1), If(self.i_valid & self.i_se0, NextState("D0"), pkt_active.eq(0), pkt_end.eq(1) ) ) # pass all of the outputs through a pipe stage self.o_pkt_start = Signal() self.o_pkt_active = Signal() self.o_pkt_end = Signal() self.comb += [ self.o_pkt_start.eq(pkt_start), self.o_pkt_active.eq(pkt_active), self.o_pkt_end.eq(pkt_end), ]