Source code for usbcore.rx.crc

#!/usr/bin/env python3

from migen import *
from migen.fhdl.decorators import ResetInserter

from ..test.common import BaseUsbTestCase
import unittest


[docs]@ResetInserter() class RxCrcChecker(Module): """CRC Checker Checks the CRC of a serial stream of data. https://www.pjrc.com/teensy/beta/usb20.pdf, USB2 Spec, 8.3.5 https://en.wikipedia.org/wiki/Cyclic_redundancy_check Parameters ---------- Parameters are passed in via the constructor. width : int Width of the CRC. polynomial : int CRC polynomial in integer form. initial : int Initial value of the CRC register before data starts shifting in. residual : int Value of the CRC register if all the shifted in data is valid. Input Ports ------------ i_data : Signal(1) Decoded data bit from USB bus. Qualified by valid. i_reset : Signal(1) Resets the CRC calculation back to the initial state. i_valid : Signal(1) Indicate that i_data is valid and a CRC should be calculated Output Ports ------------ o_crc_good : Signal() CRC value is good. """ def __init__(self, width, polynomial, initial, residual): self.i_data = Signal() self.i_reset = Signal() self.i_valid = Signal() crc = Signal(width) crc_good = Signal(1) crc_invert = Signal(1) self.comb += [ crc_good.eq(crc == residual), crc_invert.eq(self.i_data ^ crc[width - 1]) ] for i in range(width): rhs = None if i == 0: rhs = crc_invert else: if (polynomial >> i) & 1: rhs = crc[i - 1] ^ crc_invert else: rhs = crc[i - 1] self.sync += [ If(self.i_reset, crc[i].eq((initial >> i) & 1) ).Elif(self.i_valid, crc[i].eq(rhs) ) ] # flop all outputs self.o_crc_good = Signal(1) self.sync += [ self.o_crc_good.eq(crc_good) ]