summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Koenig2019-08-13 15:06:58 +0530
committerGitHub2019-08-13 15:06:58 +0530
commit24dddea6dccea5a570cece78324a5db624c7303a (patch)
treeb03fa616d0b8796548604a3d2b564fd17cf4e2d8
parentfddb5943b1d36925a5435d327c3312572e98ca58 (diff)
Add support for asynchronous reset (#1011)
Adds new AsyncReset and "abstract" Reset types. Reset is inferred in FIRRTL to be either AsyncReset or Bool. The "reset type" of a register is set by the type of its reset signal: val asyncReset: AsyncReset = IO(Input(AsyncReset())) val syncReset: Bool = IO(Input(Bool())) val abstractReset: Reset = IO(Input(Reset())) val asyncReg = withReset(asyncReset) { RegInit(0.U) } val syncReg = withReset(syncReset) { RegInit(0.U) } val inferredReg = withReset(abstractReset) { RegInit(0.U) } AsyncReset can be cast to and from Bool. Whereas synchronous reset is equivalent to a mux in front of a flip-flop and thus can be driven by logic, asynchronous reset requires that the reset value is a constant. This is checked in FIRRTL. Inference of the concrete type of a Reset occurs based on the type the Reset's drivers. This inference is very simple, it is simple forward propagation of the type, but it allows for writing blocks and modules that are agnostic to the reset type. In particular, the implicit `reset` value in MultiIOModule and thus Module is now concretely an instance of Reset and thus will be inferred in FIRRTL.
-rw-r--r--chiselFrontend/src/main/scala/chisel3/Bits.scala105
-rw-r--r--chiselFrontend/src/main/scala/chisel3/CompileOptions.scala12
-rw-r--r--chiselFrontend/src/main/scala/chisel3/RawModule.scala17
-rw-r--r--chiselFrontend/src/main/scala/chisel3/Reg.scala6
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala4
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala2
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala1
-rw-r--r--src/main/scala/chisel3/internal/firrtl/Emitter.scala4
-rw-r--r--src/test/scala/chiselTests/AsyncResetSpec.scala172
-rw-r--r--src/test/scala/chiselTests/CloneModuleSpec.scala4
-rw-r--r--src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala46
-rw-r--r--src/test/scala/chiselTests/ResetSpec.scala50
-rw-r--r--src/test/scala/examples/SimpleVendingMachine.scala2
13 files changed, 404 insertions, 21 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/Bits.scala b/chiselFrontend/src/main/scala/chisel3/Bits.scala
index f50512f0..5a6db7c1 100644
--- a/chiselFrontend/src/main/scala/chisel3/Bits.scala
+++ b/chiselFrontend/src/main/scala/chisel3/Bits.scala
@@ -1183,7 +1183,106 @@ trait SIntFactory {
object SInt extends SIntFactory
-sealed trait Reset extends Element with ToBoolable
+sealed trait Reset extends Element with ToBoolable {
+ /** Casts this $coll to an [[AsyncReset]] */
+ final def asAsyncReset(): AsyncReset = macro SourceInfoWhiteboxTransform.noArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_asAsyncReset(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): AsyncReset
+}
+
+object Reset {
+ def apply(): Reset = new ResetType
+}
+
+/** "Abstract" Reset Type inferred in FIRRTL to either [[AsyncReset]] or [[Bool]]
+ *
+ * @note This shares a common interface with [[AsyncReset]] and [[Bool]] but is not their actual
+ * super type due to Bool inheriting from abstract class UInt
+ */
+final class ResetType(private[chisel3] val width: Width = Width(1)) extends Element with Reset {
+ override def toString: String = s"Reset$bindingToString"
+
+ def cloneType: this.type = Reset().asInstanceOf[this.type]
+
+ private[chisel3] def typeEquivalent(that: Data): Boolean =
+ this.getClass == that.getClass
+
+ override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match {
+ case _: Reset => super.connect(that)(sourceInfo, connectCompileOptions)
+ case _ => super.badConnect(that)(sourceInfo)
+ }
+
+ override def litOption = None
+
+ /** Not really supported */
+ def toPrintable: Printable = PString("Reset")
+
+ override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
+
+ private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
+ compileOptions: CompileOptions): Unit = {
+ this := that
+ }
+
+ /** @group SourceInfoTransformMacro */
+ def do_asAsyncReset(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): AsyncReset =
+ pushOp(DefPrim(sourceInfo, AsyncReset(), AsAsyncResetOp, ref))
+
+ /** @group SourceInfoTransformMacro */
+ def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
+ pushOp(DefPrim(sourceInfo, Bool(), AsUIntOp, ref))
+
+ /** @group SourceInfoTransformMacro */
+ def do_toBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = do_asBool
+}
+
+object AsyncReset {
+ def apply(): AsyncReset = new AsyncReset
+}
+
+/** Data type representing asynchronous reset signals
+ *
+ * These signals are similar to [[Clock]]s in that they must be glitch-free for proper circuit
+ * operation. [[Reg]]s defined with the implicit reset being an [[AsyncReset]] will be
+ * asychronously reset registers.
+ */
+sealed class AsyncReset(private[chisel3] val width: Width = Width(1)) extends Element with Reset {
+ override def toString: String = s"AsyncReset$bindingToString"
+
+ def cloneType: this.type = AsyncReset().asInstanceOf[this.type]
+
+ private[chisel3] def typeEquivalent(that: Data): Boolean =
+ this.getClass == that.getClass
+
+ override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match {
+ case _: AsyncReset => super.connect(that)(sourceInfo, connectCompileOptions)
+ case _ => super.badConnect(that)(sourceInfo)
+ }
+
+ override def litOption = None
+
+ /** Not really supported */
+ def toPrintable: Printable = PString("AsyncReset")
+
+ override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
+
+ // TODO Is this right?
+ private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo,
+ compileOptions: CompileOptions): Unit = {
+ this := that.asBool.asAsyncReset
+ }
+
+ /** @group SourceInfoTransformMacro */
+ def do_asAsyncReset(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): AsyncReset = this
+
+ /** @group SourceInfoTransformMacro */
+ def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool =
+ pushOp(DefPrim(sourceInfo, Bool(), AsUIntOp, ref))
+
+ /** @group SourceInfoTransformMacro */
+ def do_toBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = do_asBool
+}
// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth
// operations on a Bool make sense?
@@ -1286,6 +1385,10 @@ sealed class Bool() extends UInt(1.W) with Reset {
/** @group SourceInfoTransformMacro */
def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref))
+
+ /** @group SourceInfoTransformMacro */
+ def do_asAsyncReset(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): AsyncReset =
+ pushOp(DefPrim(sourceInfo, AsyncReset(), AsAsyncResetOp, ref))
}
trait BoolFactory {
diff --git a/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala
index 33a41b72..ed410c6e 100644
--- a/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala
+++ b/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala
@@ -20,6 +20,8 @@ trait CompileOptions {
val checkSynthesizable: Boolean
// Require explicit assignment of DontCare to generate "x is invalid"
val explicitInvalidate: Boolean
+ // Should the reset type of Module be a Bool or a Reset
+ val inferModuleReset: Boolean
}
object CompileOptions {
@@ -48,7 +50,9 @@ object ExplicitCompileOptions {
// Check that referenced Data have actually been declared.
val checkSynthesizable: Boolean,
// Require an explicit DontCare assignment to generate a firrtl DefInvalid
- val explicitInvalidate: Boolean
+ val explicitInvalidate: Boolean,
+ // Should the reset type of Module be a Bool or a Reset
+ val inferModuleReset: Boolean
) extends CompileOptions
// Collection of "not strict" connection compile options.
@@ -59,7 +63,8 @@ object ExplicitCompileOptions {
dontTryConnectionsSwapped = false,
dontAssumeDirectionality = false,
checkSynthesizable = false,
- explicitInvalidate = false
+ explicitInvalidate = false,
+ inferModuleReset = false
)
// Collection of "strict" connection compile options, preferred for new code.
@@ -69,6 +74,7 @@ object ExplicitCompileOptions {
dontTryConnectionsSwapped = true,
dontAssumeDirectionality = true,
checkSynthesizable = true,
- explicitInvalidate = true
+ explicitInvalidate = true,
+ inferModuleReset = true
)
}
diff --git a/chiselFrontend/src/main/scala/chisel3/RawModule.scala b/chiselFrontend/src/main/scala/chisel3/RawModule.scala
index 6d316074..8f201ce6 100644
--- a/chiselFrontend/src/main/scala/chisel3/RawModule.scala
+++ b/chiselFrontend/src/main/scala/chisel3/RawModule.scala
@@ -143,7 +143,11 @@ abstract class MultiIOModule(implicit moduleCompileOptions: CompileOptions)
extends RawModule {
// Implicit clock and reset pins
val clock: Clock = IO(Input(Clock()))
- val reset: Reset = IO(Input(Bool()))
+ val reset: Reset = {
+ // Top module and compatibility mode use Bool for reset
+ val inferReset = _parent.isDefined && moduleCompileOptions.inferModuleReset
+ IO(Input(if (inferReset) Reset() else Bool()))
+ }
// Setup ClockAndReset
Builder.currentClock = Some(clock)
@@ -219,14 +223,7 @@ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions)
pushCommand(DefInvalid(sourceInfo, io.ref))
}
- override_clock match {
- case Some(override_clock) => clock := override_clock
- case _ => clock := Builder.forcedClock
- }
-
- override_reset match {
- case Some(override_reset) => reset := override_reset
- case _ => reset := Builder.forcedReset
- }
+ clock := override_clock.getOrElse(Builder.forcedClock)
+ reset := override_reset.getOrElse(Builder.forcedReset)
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/Reg.scala b/chiselFrontend/src/main/scala/chisel3/Reg.scala
index 8d3a915d..51c59bdb 100644
--- a/chiselFrontend/src/main/scala/chisel3/Reg.scala
+++ b/chiselFrontend/src/main/scala/chisel3/Reg.scala
@@ -152,12 +152,12 @@ object RegInit {
requireIsChiselType(t, "reg type")
}
val reg = t.cloneTypeFull
- val clock = Builder.forcedClock.ref
- val reset = Builder.forcedReset.ref
+ val clock = Builder.forcedClock
+ val reset = Builder.forcedReset
reg.bind(RegBinding(Builder.forcedUserModule))
requireIsHardware(init, "reg initializer")
- pushCommand(DefRegInit(sourceInfo, reg, clock, reset, init.ref))
+ pushCommand(DefRegInit(sourceInfo, reg, clock.ref, reset.ref, init.ref))
reg
}
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala
index e07f980d..ace7be20 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala
@@ -87,6 +87,10 @@ private[chisel3] object MonoConnect {
elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
case (sink_e: Clock, source_e: Clock) =>
elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
+ case (sink_e: AsyncReset, source_e: AsyncReset) =>
+ elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
+ case (sink_e: ResetType, source_e: Reset) =>
+ elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
case (sink_e: EnumType, source_e: UnsafeEnum) =>
elemConnect(sourceInfo, connectCompileOptions, sink_e, source_e, context_mod)
case (sink_e: EnumType, source_e: EnumType) if sink_e.typeEquivalent(source_e) =>
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala
index cdc55b59..5309609b 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/Converter.scala
@@ -214,6 +214,8 @@ private[chisel3] object Converter {
def extractType(data: Data, clearDir: Boolean = false): fir.Type = data match { // scalastyle:ignore cyclomatic.complexity line.size.limit
case _: Clock => fir.ClockType
+ case _: AsyncReset => fir.AsyncResetType
+ case _: ResetType => fir.ResetType
case d: EnumType => fir.UIntType(convert(d.width))
case d: UInt => fir.UIntType(convert(d.width))
case d: SInt => fir.SIntType(convert(d.width))
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
index 2cb4d092..e4b660dd 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
@@ -47,6 +47,7 @@ object PrimOp {
val AsFixedPointOp = PrimOp("asFixedPoint")
val SetBinaryPoint = PrimOp("bpset")
val AsClockOp = PrimOp("asClock")
+ val AsAsyncResetOp = PrimOp("asAsyncReset")
}
abstract class Arg {
diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
index 2f1b75b0..3d10670e 100644
--- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala
+++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
@@ -27,7 +27,9 @@ private class Emitter(circuit: Circuit) {
private def emitType(d: Data, clearDir: Boolean = false): String = d match { // scalastyle:ignore cyclomatic.complexity line.size.limit
case d: Clock => "Clock"
- case d: EnumType => s"UInt${d.width}"
+ case _: AsyncReset => "AsyncReset"
+ case _: ResetType => "Reset"
+ case d: chisel3.core.EnumType => s"UInt${d.width}"
case d: UInt => s"UInt${d.width}"
case d: SInt => s"SInt${d.width}"
case d: FixedPoint => s"Fixed${d.width}${d.binaryPoint}"
diff --git a/src/test/scala/chiselTests/AsyncResetSpec.scala b/src/test/scala/chiselTests/AsyncResetSpec.scala
new file mode 100644
index 00000000..78a29e99
--- /dev/null
+++ b/src/test/scala/chiselTests/AsyncResetSpec.scala
@@ -0,0 +1,172 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import chisel3._
+import chisel3.util.{Counter, Queue}
+import chisel3.testers.BasicTester
+import firrtl.checks.CheckResets.NonLiteralAsyncResetValueException
+
+class AsyncResetTester extends BasicTester {
+ val (_, cDiv) = Counter(true.B, 4)
+ // First rising edge when count === 3
+ val slowClk = cDiv.asClock
+
+ val (count, done) = Counter(true.B, 16)
+
+ val asyncResetNext = RegInit(false.B)
+ asyncResetNext := count === 4.U
+ val asyncReset = asyncResetNext.asAsyncReset
+
+ val reg = withClockAndReset(slowClk, asyncReset) {
+ RegInit(123.U(8.W))
+ }
+ reg := 5.U // Normal connection
+
+ when (count === 3.U) {
+ assert(reg === 5.U)
+ }
+ when (count >= 5.U && count < 7.U) {
+ assert(reg === 123.U)
+ } .elsewhen (count >= 7.U) {
+ assert(reg === 5.U)
+ }
+
+ when (done) {
+ stop()
+ }
+}
+
+class AsyncResetAggregateTester extends BasicTester {
+ class MyBundle extends Bundle {
+ val x = UInt(8.W)
+ val y = UInt(8.W)
+ }
+ val (_, cDiv) = Counter(true.B, 4)
+ // First rising edge when count === 3
+ val slowClk = cDiv.asClock
+
+ val (count, done) = Counter(true.B, 16)
+
+ val asyncResetNext = RegInit(false.B)
+ asyncResetNext := count === 4.U
+ val asyncReset = asyncResetNext.asAsyncReset
+
+ val reg = withClockAndReset(slowClk, asyncReset) {
+ val init = Wire(Vec(2, new MyBundle))
+ init(0).x := 0.U
+ init(0).y := 0.U
+ init(1).x := 0.U
+ init(1).y := 0.U
+ RegInit(init)
+ }
+ reg(0).x := 5.U // Normal connections
+ reg(0).y := 6.U
+ reg(1).x := 7.U
+ reg(1).y := 8.U
+
+ when (count === 3.U) {
+ assert(reg(0).x === 5.U)
+ assert(reg(0).y === 6.U)
+ assert(reg(1).x === 7.U)
+ assert(reg(1).y === 8.U)
+ }
+ when (count >= 5.U && count < 7.U) {
+ assert(reg(0).x === 0.U)
+ assert(reg(0).y === 0.U)
+ assert(reg(1).x === 0.U)
+ assert(reg(1).y === 0.U)
+ } .elsewhen (count >= 7.U) {
+ assert(reg(0).x === 5.U)
+ assert(reg(0).y === 6.U)
+ assert(reg(1).x === 7.U)
+ assert(reg(1).y === 8.U)
+ }
+
+ when (done) {
+ stop()
+ }
+}
+
+class AsyncResetQueueTester extends BasicTester {
+ val (_, cDiv) = Counter(true.B, 4)
+ val slowClk = cDiv.asClock
+
+ val (count, done) = Counter(true.B, 16)
+
+ val asyncResetNext = RegNext(false.B, false.B)
+ val asyncReset = asyncResetNext.asAsyncReset
+
+ val queue = withClockAndReset (slowClk, asyncReset) {
+ Module(new Queue(UInt(8.W), 4))
+ }
+ queue.io.enq.valid := true.B
+ queue.io.enq.bits := count
+
+ queue.io.deq.ready := false.B
+
+ val doCheck = RegNext(false.B, false.B)
+ when (queue.io.count === 3.U) {
+ asyncResetNext := true.B
+ doCheck := true.B
+ }
+ when (doCheck) {
+ assert(queue.io.count === 0.U)
+ }
+
+ when (done) {
+ stop()
+ }
+}
+
+class AsyncResetSpec extends ChiselFlatSpec {
+
+ behavior of "AsyncReset"
+
+ it should "be allowed with literal reset values" in {
+ elaborate(new BasicTester {
+ withReset(reset.asAsyncReset)(RegInit(123.U))
+ })
+ }
+
+ it should "NOT be allowed with non-literal reset values" in {
+ a [NonLiteralAsyncResetValueException] shouldBe thrownBy {
+ compile(new BasicTester {
+ val x = WireInit(123.U + 456.U)
+ withReset(reset.asAsyncReset)(RegInit(x))
+ })
+ }
+ }
+
+ it should "NOT be allowed to connect directly to a Bool" in {
+ a [ChiselException] shouldBe thrownBy {
+ elaborate(new BasicTester {
+ val bool = Wire(Bool())
+ val areset = reset.asAsyncReset
+ bool := areset
+ })
+ }
+ }
+
+ it should "simulate correctly" in {
+ assertTesterPasses(new AsyncResetTester)
+ }
+
+ it should "simulate correctly with aggregates" in {
+ assertTesterPasses(new AsyncResetAggregateTester)
+ }
+
+ it should "allow casting to and from Bool" in {
+ elaborate(new BasicTester {
+ val r: Reset = reset
+ val a: AsyncReset = WireInit(r.asAsyncReset)
+ val b: Bool = a.asBool
+ val c: AsyncReset = b.asAsyncReset
+ })
+ }
+
+ it should "allow changing the reset type of whole modules like Queue" in {
+ assertTesterPasses(new AsyncResetQueueTester)
+ }
+
+}
diff --git a/src/test/scala/chiselTests/CloneModuleSpec.scala b/src/test/scala/chiselTests/CloneModuleSpec.scala
index 59ba2eb5..ca8bd007 100644
--- a/src/test/scala/chiselTests/CloneModuleSpec.scala
+++ b/src/test/scala/chiselTests/CloneModuleSpec.scala
@@ -9,7 +9,7 @@ import chisel3.testers.BasicTester
class MultiIOQueue[T <: Data](gen: T, val entries: Int) extends MultiIOModule {
val clk = IO(Input(Clock()))
- val rst = IO(Input(Bool()))
+ val rst = IO(Input(Reset()))
val enq = IO(Flipped(EnqIO(gen)))
val deq = IO(Flipped(DeqIO(gen)))
val count = IO(Output(UInt(log2Ceil(entries + 1).W)))
@@ -28,7 +28,7 @@ class QueueClone(multiIO: Boolean = false) extends Module {
q1.rst := reset
q1.enq <> io.enq
q2_io("clk").asInstanceOf[Clock] := clock
- q2_io("rst").asInstanceOf[Bool] := reset
+ q2_io("rst").asInstanceOf[Reset] := reset
q2_io("enq").asInstanceOf[q1.enq.type] <> q1.deq
io.deq <> q2_io("deq").asInstanceOf[q1.deq.type]
io.count := q1.count + q2_io("count").asInstanceOf[q1.count.type]
diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala
index 861b3fdd..4ca7dcda 100644
--- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala
+++ b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala
@@ -243,5 +243,51 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec {
}
}
}
+
+ "Compatibility Modules" should "have Bool as their reset type" in {
+ compile {
+ import Chisel._
+ class Intf extends Bundle {
+ val in = Bool(INPUT)
+ val en = Bool(INPUT)
+ val out = Bool(OUTPUT)
+ }
+ class Child extends Module {
+ val io = new Intf
+ io.out := Mux(io.en, io.in, reset)
+ }
+ new Module {
+ val io = new Intf
+ val child = Module(new Child)
+ io <> child.io
+ }
+ }
+ }
+
+ "Compatibility Modules" should "be instantiable inside chisel3 Modules" in {
+ compile {
+ object Compat {
+ import Chisel._
+ class Intf extends Bundle {
+ val in = Input(UInt(8.W))
+ val out = Output(UInt(8.W))
+ }
+ class OldMod extends Module {
+ val io = IO(new Intf)
+ io.out := Reg(next = io.in)
+ }
+ }
+ import chisel3._
+ import Compat._
+ new Module {
+ val io = IO(new Intf)
+ io <> Module(new Module {
+ val io = IO(new Intf)
+ val inst = Module(new OldMod)
+ io <> inst.io
+ }).io
+ }
+ }
+ }
}
diff --git a/src/test/scala/chiselTests/ResetSpec.scala b/src/test/scala/chiselTests/ResetSpec.scala
new file mode 100644
index 00000000..297c5516
--- /dev/null
+++ b/src/test/scala/chiselTests/ResetSpec.scala
@@ -0,0 +1,50 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import chisel3._
+import chisel3.experimental.{IO, RawModule}
+import chisel3.util.{Counter, Queue}
+import chisel3.testers.BasicTester
+
+class ResetAgnosticModule extends RawModule {
+ val clk = IO(Input(Clock()))
+ val rst = IO(Input(Reset()))
+ val out = IO(Output(UInt(8.W)))
+
+ val reg = withClockAndReset(clk, rst)(RegInit(0.U(8.W)))
+ reg := reg + 1.U
+ out := reg
+}
+
+
+class ResetSpec extends ChiselFlatSpec {
+
+ behavior of "Reset"
+
+ it should "allow writing modules that are reset agnostic" in {
+ val sync = compile(new Module {
+ val io = IO(new Bundle {
+ val out = Output(UInt(8.W))
+ })
+ val inst = Module(new ResetAgnosticModule)
+ inst.clk := clock
+ inst.rst := reset
+ assert(inst.rst.isInstanceOf[chisel3.ResetType])
+ io.out := inst.out
+ })
+ sync should include ("always @(posedge clk)")
+
+ val async = compile(new Module {
+ val io = IO(new Bundle {
+ val out = Output(UInt(8.W))
+ })
+ val inst = Module(new ResetAgnosticModule)
+ inst.clk := clock
+ inst.rst := reset.asTypeOf(AsyncReset())
+ assert(inst.rst.isInstanceOf[chisel3.ResetType])
+ io.out := inst.out
+ })
+ async should include ("always @(posedge clk or posedge rst)")
+ }
+}
diff --git a/src/test/scala/examples/SimpleVendingMachine.scala b/src/test/scala/examples/SimpleVendingMachine.scala
index 4bb6027a..2021ece8 100644
--- a/src/test/scala/examples/SimpleVendingMachine.scala
+++ b/src/test/scala/examples/SimpleVendingMachine.scala
@@ -52,7 +52,7 @@ class VerilogVendingMachine extends BlackBox {
// Because this is a blackbox, we must explicity add clock and reset
val io = IO(new SimpleVendingMachineIO {
val clock = Input(Clock())
- val reset = Input(Bool())
+ val reset = Input(Reset())
})
}