diff options
Diffstat (limited to 'core/src/main/scala/chisel3/Reg.scala')
| -rw-r--r-- | core/src/main/scala/chisel3/Reg.scala | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/core/src/main/scala/chisel3/Reg.scala b/core/src/main/scala/chisel3/Reg.scala new file mode 100644 index 00000000..7129c389 --- /dev/null +++ b/core/src/main/scala/chisel3/Reg.scala @@ -0,0 +1,195 @@ +// See LICENSE for license details. + +package chisel3 + +import scala.language.experimental.macros + +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.SourceInfo + +/** Utility for constructing hardware registers + * + * The width of a `Reg` (inferred or not) is copied from the type template + * {{{ + * val r0 = Reg(UInt()) // width is inferred + * val r1 = Reg(UInt(8.W)) // width is set to 8 + * + * val r2 = Reg(Vec(4, UInt())) // width is inferred + * val r3 = Reg(Vec(4, UInt(8.W))) // width of each element is set to 8 + * + * class MyBundle { + * val unknown = UInt() + * val known = UInt(8.W) + * } + * val r4 = Reg(new MyBundle) + * // Width of r4.unknown is inferred + * // Width of r4.known is set to 8 + * }}} + * + */ +object Reg { + /** Construct a [[Reg]] from a type template with no initialization value (reset is ignored). + * Value will not change unless the [[Reg]] is given a connection. + * @param t The template from which to construct this wire + */ + def apply[T <: Data](t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + if (compileOptions.declaredTypeMustBeUnbound) { + requireIsChiselType(t, "reg type") + } + val reg = t.cloneTypeFull + val clock = Node(Builder.forcedClock) + + reg.bind(RegBinding(Builder.forcedUserModule)) + pushCommand(DefReg(sourceInfo, reg, clock)) + reg + } + +} + +/** Utility for constructing one-cycle delayed versions of signals + * + * ''The width of a `RegNext` is not set based on the `next` or `init` connections'' for [[Element]] types. In the + * following example, the width of `bar` will not be set and will be inferred by the FIRRTL compiler. + * {{{ + * val foo = Reg(UInt(4.W)) // width is 4 + * val bar = RegNext(foo) // width is unset + * }}} + * + * If you desire an explicit width, do not use `RegNext` and instead use a register with a specified width: + * {{{ + * val foo = Reg(UInt(4.W)) // width is 4 + * val bar = Reg(chiselTypeOf(foo)) // width is 4 + * bar := foo + * }}} + * + * Also note that a `RegNext` of a [[Bundle]] ''will have it's width set'' for [[Aggregate]] types. + * {{{ + * class MyBundle extends Bundle { + * val x = UInt(4.W) + * } + * val foo = Wire(new MyBundle) // the width of foo.x is 4 + * val bar = RegNext(foo) // the width of bar.x is 4 + * }}} + */ +object RegNext { + /** Returns a register ''with an unset width'' connected to the signal `next` and with no reset value. */ + def apply[T <: Data](next: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + val model = (next match { + case next: Bits => next.cloneTypeWidth(Width()) + case next => next.cloneTypeFull + }).asInstanceOf[T] + val reg = Reg(model) + + requireIsHardware(next, "reg next") + reg := next + + reg + } + + /** Returns a register ''with an unset width'' connected to the signal `next` and with the reset value `init`. */ + def apply[T <: Data](next: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + val model = (next match { + case next: Bits => next.cloneTypeWidth(Width()) + case next => next.cloneTypeFull + }).asInstanceOf[T] + val reg = RegInit(model, init) // TODO: this makes NO sense + + requireIsHardware(next, "reg next") + reg := next + + reg + } +} + +/** Utility for constructing hardware registers with an initialization value. + * + * The register is set to the initialization value when the current implicit `reset` is high + * + * The two forms of `RegInit` differ in how the type and width of the resulting [[Reg]] are + * specified. + * + * ==Single Argument== + * The single argument form uses the argument to specify both the type and reset value. For + * non-literal [[Bits]], the width of the [[Reg]] will be inferred. For literal [[Bits]] and all + * non-Bits arguments, the type will be copied from the argument. See the following examples for + * more details: + * + * 1. Literal [[Bits]] initializer: width will be set to match + * {{{ + * val r1 = RegInit(1.U) // width will be inferred to be 1 + * val r2 = RegInit(1.U(8.W)) // width is set to 8 + * }}} + * + * 2. Non-Literal [[Element]] initializer - width will be inferred + * {{{ + * val x = Wire(UInt()) + * val y = Wire(UInt(8.W)) + * val r1 = RegInit(x) // width will be inferred + * val r2 = RegInit(y) // width is set to 8 + * }}} + * + * 3. [[Aggregate]] initializer - width will be set to match the aggregate + * + * {{{ + * class MyBundle extends Bundle { + * val unknown = UInt() + * val known = UInt(8.W) + * } + * val w1 = Reg(new MyBundle) + * val w2 = RegInit(w1) + * // Width of w2.unknown is inferred + * // Width of w2.known is set to 8 + * }}} + * + * ==Double Argument== + * The double argument form allows the type of the [[Reg]] and the default connection to be + * specified independently. + * + * The width inference semantics for `RegInit` with two arguments match those of [[Reg]]. The + * first argument to `RegInit` is the type template which defines the width of the `Reg` in + * exactly the same way as the only argument to [[Wire]]. + * + * More explicitly, you can reason about `RegInit` with multiple arguments as if it were defined + * as: + * {{{ + * def RegInit[T <: Data](t: T, init: T): T = { + * val x = Reg(t) + * x := init + * x + * } + * }}} + */ +object RegInit { + /** Construct a [[Reg]] from a type template initialized to the specified value on reset + * @param t The type template used to construct this [[Reg]] + * @param init The value the [[Reg]] is initialized to on reset + */ + def apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + if (compileOptions.declaredTypeMustBeUnbound) { + requireIsChiselType(t, "reg type") + } + val reg = t.cloneTypeFull + val clock = Builder.forcedClock + val reset = Builder.forcedReset + + reg.bind(RegBinding(Builder.forcedUserModule)) + requireIsHardware(init, "reg initializer") + pushCommand(DefRegInit(sourceInfo, reg, clock.ref, reset.ref, init.ref)) + reg + } + + /** Construct a [[Reg]] initialized on reset to the specified value. + * @param init Initial value that serves as a type template and reset value + */ + def apply[T <: Data](init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + val model = (init match { + // If init is a literal without forced width OR any non-literal, let width be inferred + case init: Bits if !init.litIsForcedWidth.getOrElse(false) => init.cloneTypeWidth(Width()) + case init => init.cloneTypeFull + }).asInstanceOf[T] + RegInit(model, init) + } + +} |
