summaryrefslogtreecommitdiff
path: root/docs/src/explanations/reset.md
blob: a99a39e361376aa0291dc92a0d767229074e3f4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
---
layout: docs
title:  "Reset"
section: "chisel3"
---

# Reset

```scala mdoc:invisible
import chisel3._

class Submodule extends Module
```

As of Chisel 3.2.0, Chisel 3 supports both synchronous and asynchronous reset,
meaning that it can natively emit both synchronous and asynchronously reset registers.

The type of register that is emitted is based on the type of the reset signal associated
with the register.

There are three types of reset that implement a common trait `Reset`:
* `Bool` - constructed with `Bool()`. Also known as "synchronous reset".
* `AsyncReset` - constructed with `AsyncReset()`. Also known as "asynchronous reset".
* `Reset` - constructed with `Reset()`. Also known as "abstract reset".

For implementation reasons, the concrete Scala type is `ResetType`. Stylistically we avoid `ResetType`, instead using the common trait `Reset`.

Registers with reset signals of type `Bool` are emitted as synchronous reset flops.
Registers with reset signals of type `AsyncReset` are emitted as asynchronouly reset flops.
Registers with reset signals of type `Reset` will have their reset type _inferred_ during FIRRTL compilation.

### Reset Inference

FIRRTL will infer a concrete type for any signals of type abstract `Reset`.
The rules are as follows:
1. An abstract `Reset` with only signals of type `AsyncReset`, abstract `Reset`, and `DontCare`
in both its fan-in and fan-out will infer to be of type `AsyncReset`
2. An abstract `Reset` with signals of both types `Bool` and `AsyncReset` in its fan-in and fan-out
is an error.
3. Otherwise, an abstract `Reset` will infer to type `Bool`.

You can think about (3) as the mirror of (1) replacing `AsyncReset` with `Bool` with the additional
rule that abstract `Reset`s with neither `AsyncReset` nor `Bool` in their fan-in and fan-out will
default to type `Bool`.
This "default" case is uncommon and implies that reset signal is ultimately driven by a `DontCare`.

### Implicit Reset

A `Module`'s `reset` is of type abstract `Reset`.
Prior to Chisel 3.2.0, the type of this field was `Bool`.
For backwards compatability, if the top-level module has an implicit reset, its type will default to `Bool`.

#### Setting Implicit Reset Type

_New in Chisel 3.3.0_

If you would like to set the reset type from within a Module (including the top-level `Module`),
rather than relying on _Reset Inference_, you can mixin one of the following traits:
* `RequireSyncReset` - sets the type of `reset` to `Bool`
* `RequireAsyncReset` - sets the type of `reset` to `AsyncReset`

For example:

```scala mdoc:silent
class MyAlwaysSyncResetModule extends Module with RequireSyncReset {
  val mySyncResetReg = RegInit(false.B) // reset is of type Bool
}
```

```scala mdoc:silent
class MyAlwaysAsyncResetModule extends Module with RequireAsyncReset {
  val myAsyncResetReg = RegInit(false.B) // reset is of type AsyncReset
}
```

**Note:** This sets the concrete type, but the Scala type will remain `Reset`, so casting may still be necessary.
This comes up most often when using a reset of type `Bool` in logic.


### Reset-Agnostic Code

The purpose of abstract `Reset` is to make it possible to design hardware that is agnostic to the
reset discipline used.
This enables code reuse for utilities and designs where the reset discipline does not matter to
the functionality of the block.

Consider the two example modules below which are agnostic to the type of reset used within them:

```scala mdoc:silent
class ResetAgnosticModule extends Module {
  val io = IO(new Bundle {
    val out = UInt(4.W)
  })
  val resetAgnosticReg = RegInit(0.U(4.W))
  resetAgnosticReg := resetAgnosticReg + 1.U
  io.out := resetAgnosticReg
}

class ResetAgnosticRawModule extends RawModule {
  val clk = IO(Input(Clock()))
  val rst = IO(Input(Reset()))
  val out = IO(Output(UInt(8.W)))

  val resetAgnosticReg = withClockAndReset(clk, rst)(RegInit(0.U(8.W)))
  resetAgnosticReg := resetAgnosticReg + 1.U
  out := resetAgnosticReg
}
```

These modules can be used in both synchronous and asynchronous reset domains.
Their reset types will be inferred based on the context within which they are used.

### Forcing Reset Type

You can set the type of a Module's implicit reset as described [above](#setting-implicit-reset-type).

You can also cast to force the concrete type of reset.
* `.asBool` will reinterpret a `Reset` as `Bool`
* `.asAsyncReset` will reinterpret a `Reset` as `AsyncReset`.

You can then use `withReset` to use a cast reset as the implicit reset.
See ["Multiple Clock Domains"](../explanations/multi-clock) for more information about `withReset`.


The following will make `myReg` as well as both `resetAgnosticReg`s synchronously reset:

```scala mdoc:silent
class ForcedSyncReset extends Module {
  // withReset's argument becomes the implicit reset in its scope
  withReset (reset.asBool) {
    val myReg = RegInit(0.U)
    val myModule = Module(new ResetAgnosticModule)

    // RawModules do not have implicit resets so withReset has no effect
    val myRawModule = Module(new ResetAgnosticRawModule)
    // We must drive the reset port manually
    myRawModule.rst := Module.reset // Module.reset grabs the current implicit reset
  }
}
```

The following will make `myReg` as well as both `resetAgnosticReg`s asynchronously reset:

```scala mdoc:silent
class ForcedAysncReset extends Module {
  // withReset's argument becomes the implicit reset in its scope
  withReset (reset.asAsyncReset){
    val myReg = RegInit(0.U)
    val myModule = Module(new ResetAgnosticModule) // myModule.reset is connected implicitly

    // RawModules do not have implicit resets so withReset has no effect
    val myRawModule = Module(new ResetAgnosticRawModule)
    // We must drive the reset port manually
    myRawModule.rst := Module.reset // Module.reset grabs the current implicit reset
  }
}
```

**Note:** such casts (`asBool` and `asAsyncReset`) are not checked by FIRRTL.
In doing such a cast, you as the designer are effectively telling the compiler
that you know what you are doing and to force the type as cast.

### Last-Connect Semantics

It is **not** legal to override the reset type using last-connect semantics
unless you are overriding a `DontCare`:

```scala mdoc:silent
class MyModule extends Module {
  val resetBool = Wire(Reset())
  resetBool := DontCare
  resetBool := false.B // this is fine
  withReset(resetBool) {
    val mySubmodule = Module(new Submodule())
  }
  resetBool := true.B // this is fine
  resetBool := false.B.asAsyncReset // this will error in FIRRTL
}
```