Source code for usbcore.tx.bitstuff

#!/usr/bin/env python3

import unittest

from migen import *

from migen.fhdl.decorators import CEInserter, ResetInserter

from .tester import module_tester
from ..test.common import BaseUsbTestCase


[docs]@ResetInserter() class TxBitstuffer(Module): """ Bitstuff Insertion Long sequences of 1's would cause the receiver to lose it's lock on the transmitter's clock. USB solves this with bitstuffing. A '0' is stuffed after every 6 consecutive 1's. The TxBitstuffer is the only component in the transmit pipeline that can delay transmission of serial data. It is therefore responsible for generating the bit_strobe signal that keeps the pipe moving forward. https://www.pjrc.com/teensy/beta/usb20.pdf, USB2 Spec, 7.1.9 https://en.wikipedia.org/wiki/Bit_stuffing Clock Domain ------------ usb_12 : 48MHz Input Ports ------------ i_data : Signal(1) Data bit to be transmitted on USB. Output Ports ------------ o_data : Signal(1) Data bit to be transmitted on USB. o_stall : Signal(1) Used to apply backpressure on the tx pipeline. """ def __init__(self): self.i_data = Signal() self.o_stall = Signal(1) self.o_will_stall = Signal(1) self.o_data = Signal(1) self.submodules.stuff = stuff = FSM() stuff_bit = Signal(1) for i in range(5): stuff.act("D%d" % i, If(self.i_data, # Receiving '1' increments the bitstuff counter. NextState("D%d" % (i + 1)) ).Else( # Receiving '0' resets the bitstuff counter. NextState("D0") ) ) stuff.act("D5", If(self.i_data, # There's a '1', so indicate we might stall on the next loop. self.o_will_stall.eq(1), # Receiving '1' increments the bitstuff counter. NextState("D6") ).Else( # Receiving '0' resets the bitstuff counter. NextState("D0") ) ) stuff.act("D6", # stuff a bit stuff_bit.eq(1), # Reset the bitstuff counter NextState("D0") ) self.comb += [ self.o_stall.eq(stuff_bit) ] # flop outputs self.sync += [ If(stuff_bit, self.o_data.eq(0), ).Else( self.o_data.eq(self.i_data), ), ]