-
Notifications
You must be signed in to change notification settings - Fork 650
Expand file tree
/
Copy pathReadyValidIO.scala
More file actions
86 lines (71 loc) · 2.61 KB
/
ReadyValidIO.scala
File metadata and controls
86 lines (71 loc) · 2.61 KB
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
// SPDX-License-Identifier: Apache-2.0
package chisel3.util
import chisel3._
import chisel3.experimental.{requireIsChiselType, Direction}
import chisel3.reflect.DataMirror
import chisel3.util.simpleClassName
/** An I/O Bundle containing 'valid' and 'ready' signals that handshake
* the transfer of data stored in the 'bits' subfield.
* The base protocol implied by the directionality is that
* the producer uses the interface as-is (outputs bits)
* while the consumer uses the flipped interface (inputs bits).
* The actual semantics of ready/valid are enforced via the use of concrete subclasses.
* @param gen the type of data to be wrapped in Ready/Valid
* @groupdesc Signals The actual hardware fields of the Bundle
*/
abstract class ReadyValidIO[+T <: Data](gen: () => T) extends Bundle {
@deprecated("Use constructor that takes () => T if extending ReadyValidIO.", "Chisel 7.9.0")
def this(gen: T) = this(() => gen)
/** Indicates that the consumer is ready to accept the data this cycle
* @group Signals
*/
val ready = Input(Bool())
/** Indicates that the producer has put valid data in 'bits'
* @group Signals
*/
val valid = Output(Bool())
/** The data to be transferred when ready and valid are asserted at the same cycle
* @group Signals
*/
val bits = Output(gen())
/** A stable typeName for this `ReadyValidIO` and any of its implementations
* using the supplied `Data` generator's `typeName`
*/
override def typeName = s"${simpleClassName(this.getClass)}_${bits.typeName}"
}
object ReadyValidIO {
implicit class AddMethodsToReadyValid[T <: Data](target: ReadyValidIO[T]) {
/** Indicates if IO is both ready and valid
*/
def fire: Bool = target.ready && target.valid
/** Push dat onto the output bits of this interface to let the consumer know it has happened.
* @param dat the values to assign to bits.
* @return dat.
*/
def enq(dat: T): T = {
target.valid := true.B
target.bits := dat
dat
}
/** Indicate no enqueue occurs. Valid is set to false, and bits are
* connected to an uninitialized wire.
*/
def noenq(): Unit = {
target.valid := false.B
target.bits := DontCare
}
/** Assert ready on this port and return the associated data bits.
* This is typically used when valid has been asserted by the producer side.
* @return The data bits.
*/
def deq(): T = {
target.ready := true.B
target.bits
}
/** Indicate no dequeue occurs. Ready is set to false.
*/
def nodeq(): Unit = {
target.ready := false.B
}
}
}