diff --git a/src/main/scala/util/CRC.scala b/src/main/scala/util/CRC.scala new file mode 100644 index 00000000..8dc2ab21 --- /dev/null +++ b/src/main/scala/util/CRC.scala @@ -0,0 +1,35 @@ +// See LICENSE.SiFive for license details. + +package util + +import Chisel._ + +object CRC +{ + // A divisor of 0x1d5 is interpretted to be x^8 + x^7 + x^6 + x^4 + x^2 + 1 + // Let n be the highest term in the divisor; n=8 in 0x1d5. + // Then, this function calculates c mod d, returning an n-bit UInt. + // coefficient.width must be <= width + def apply(divisor: BigInt, coefficient: UInt, width: Integer): UInt = { + require (divisor > 0 && divisor.testBit(0)) + require (width > 0) + assert (coefficient >> width === UInt(0)) + val n = log2Floor(divisor) + val m = width + if (m <= n) return coefficient + + // Initialize the reduction matrix + val array = Array.tabulate(m) { BigInt(1) << _ } + // Reduce the matrix of terms larger than n + for { + i <- (n until m).reverse + j <- 0 to n + if divisor.testBit(j) + } array(i-(n-j)) ^= array(i) + // Construct the circuit + Cat(Seq.tabulate(n) { i => (UInt(array(i)) & coefficient).xorR } .reverse) + } + + // Find more great CRC polynomials here: https://users.ece.cmu.edu/~koopman/crc/ + val CRC_16F_4_2 = BigInt(0x1a2eb) // HD=4 for <32751 bits and HD=6 for <93 bits +}