diff options
Diffstat (limited to 'src/main/scala/chisel3/util/random/FibonacciLFSR.scala')
| -rw-r--r-- | src/main/scala/chisel3/util/random/FibonacciLFSR.scala | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/main/scala/chisel3/util/random/FibonacciLFSR.scala b/src/main/scala/chisel3/util/random/FibonacciLFSR.scala new file mode 100644 index 00000000..53a42320 --- /dev/null +++ b/src/main/scala/chisel3/util/random/FibonacciLFSR.scala @@ -0,0 +1,108 @@ +// See LICENSE for license details. + +package chisel3.util.random + +import chisel3._ + +/** Fibonacci Linear Feedback Shift Register (LFSR) generator. + * + * A Fibonacci LFSR can be generated by defining a width and a set of tap points (corresponding to a polynomial). An + * optional initial seed and a reduction operation ([[XOR]], the default, or [[XNOR]]) can be used to augment the + * generated hardware. The resulting hardware has support for a run-time programmable seed (via [[PRNGIO.seed]]) and + * conditional increment (via [[PRNGIO.increment]]). + * + * $seedExplanation + * + * In the example below, a 4-bit Fibonacci LFSR is constructed. Tap points are defined as four and three (using LFSR + * convention of indexing from one). This results in the hardware configuration shown in the diagram. + * + * {{{ + * val lfsr4 = Module(new FibonacciLFSR(4, Set(4, 3)) + * // +---+ + * // +-------------->|XOR|-------------------------------------------------------+ + * // | +---+ | + * // | +-------+ ^ +-------+ +-------+ +-------+ | + * // | | | | | | | | | | | + * // +---+ x^4 |<----+-----| x^3 |<----------| x^2 |<----------| x^1 |<--+ + * // | | | | | | | | + * // +-------+ +-------+ +-------+ +-------+ + * }}} + * + * If you require a maximal period Fibonacci LFSR of a specific width, you can use [[MaxPeriodFibonacciLFSR]]. If you + * only require a pseudorandom [[UInt]] you can use the [[FibonacciLFSR$ FibonacciLFSR companion + * object]]. + * @see [[https://en.wikipedia.org/wiki/Linear-feedback_shift_register#Fibonacci_LFSRs]] + * $paramWidth + * $paramTaps + * $paramSeed + * $paramReduction + * $paramStep + * $paramUpdateSeed + */ +class FibonacciLFSR( + width: Int, + taps: Set[Int], + seed: Option[BigInt] = Some(1), + val reduction: LFSRReduce = XOR, + step: Int = 1, + updateSeed: Boolean = false) extends PRNG(width, seed, step, updateSeed) with LFSR { + + def delta(s: UInt): UInt = s(width-2,0) ## taps.map{ case i => s(i - 1) }.reduce(reduction) + +} + +/** A maximal period Fibonacci Linear Feedback Shift Register (LFSR) generator. The maximal period taps are sourced from + * [[LFSR.tapsMaxPeriod LFSR.tapsMaxPeriod]]. + * {{{ + * val lfsr8 = Module(new MaxPeriodFibonacciLFSR(8)) + * }}} + * $paramWidth + * $paramSeed + * $paramReduction + */ +class MaxPeriodFibonacciLFSR(width: Int, seed: Option[BigInt] = Some(1), reduction: LFSRReduce = XOR) + extends FibonacciLFSR(width, LFSR.tapsMaxPeriod.getOrElse(width, LFSR.badWidth(width)).head, seed, reduction) + +/** Utility for generating a pseudorandom [[UInt]] from a [[FibonacciLFSR]]. + * + * For example, to generate a pseudorandom 8-bit [[UInt]] that changes every cycle, you can use: + * {{{ + * val pseudoRandomNumber = FibonacciLFSR.maxPeriod(8) + * }}} + * + * @define paramWidth @param width of pseudorandom output + * @define paramTaps @param taps a set of tap points to use when constructing the LFSR + * @define paramIncrement @param increment when asserted, a new random value will be generated + * @define paramSeed @param seed an initial value for internal LFSR state + * @define paramReduction @param reduction the reduction operation (either [[XOR]] or + * [[XNOR]]) + */ +object FibonacciLFSR { + + /** Return a pseudorandom [[UInt]] generated from a [[FibonacciLFSR]]. + * $paramWidth + * $paramTaps + * $paramIncrement + * $paramSeed + * $paramReduction + */ + def apply( + width: Int, + taps: Set[Int], + increment: Bool = true.B, + seed: Option[BigInt] = Some(1), + reduction: LFSRReduce = XOR): UInt = PRNG(new FibonacciLFSR(width, taps, seed, reduction), increment) + + /** Return a pseudorandom [[UInt]] generated using a maximal period [[FibonacciLFSR]] + * $paramWidth + * $paramIncrement + * $paramSeed + * $paramReduction + */ + def maxPeriod( + width: Int, + increment: Bool = true.B, + seed: Option[BigInt] = Some(1), + reduction: LFSRReduce = XOR): UInt = PRNG(new MaxPeriodFibonacciLFSR(width, seed, reduction), increment) + +} |
