summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/chisel3/util/Valid.scala67
1 files changed, 59 insertions, 8 deletions
diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala
index 67a1a362..ab7ec00f 100644
--- a/src/main/scala/chisel3/util/Valid.scala
+++ b/src/main/scala/chisel3/util/Valid.scala
@@ -10,17 +10,70 @@ import chisel3.core.CompileOptions
import chisel3.experimental.DataMirror
import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order
-/** An Bundle containing data and a signal determining if it is valid */
-class Valid[+T <: Data](gen: T) extends Bundle
-{
+/** A [[Bundle]] that adds a `valid` bit to some data. This indicates that the user expects a "valid" interface between
+ * a producer and a consumer. Here, the producer asserts the `valid` bit when data on the `bits` line contains valid
+ * data. This differs from [[DecoupledIO]] or [[IrrevocableIO]] as there is no `ready` line that the consumer can use
+ * to put back pressure on the producer.
+ *
+ * In most scenarios, the `Valid` class will ''not'' be used directly. Instead, users will create `Valid` interfaces
+ * using the [[Valid$ Valid factory]].
+ * @tparam T the type of the data
+ * @param gen some data
+ * @see [[Valid$ Valid factory]] for concrete examples.
+ */
+class Valid[+T <: Data](gen: T) extends Bundle {
+ /** A bit that will be asserted when `bits` is valid */
val valid = Output(Bool())
+
+ /** Some data */
val bits = Output(gen)
+
+ /** True when `valid` is asserted
+ * @return a Chisel [[Bool]] true if `valid` is asserted
+ */
def fire(dummy: Int = 0): Bool = valid
+
override def cloneType: this.type = Valid(gen).asInstanceOf[this.type]
}
-/** Adds a valid protocol to any interface */
+/** Factory for generating "valid" interfaces. A "valid" interface is a data-communicating interface between a producer
+ * and a consumer where the producer does not wait for the consumer. Concretely, this means that one additional bit is
+ * added to the data indicating its validity.
+ *
+ * As an example, consider the following [[Bundle]], `MyBundle`:
+ * {{{
+ * class MyBundle extends Bundle {
+ * val foo = Output(UInt(8.W))
+ * }
+ * }}}
+ *
+ * To convert this to a "valid" interface, you wrap it with a call to the [[Valid$.apply `Valid` companion object's
+ * apply method]]:
+ * {{{
+ * val bar = Valid(new MyBundle)
+ * }}}
+ *
+ * The resulting interface is ''structurally'' equivalent to the following:
+ * {{{
+ * class MyValidBundle extends Bundle {
+ * val valid = Output(Bool())
+ * val bits = Output(new MyBundle)
+ * }
+ * }}}
+ *
+ * In addition to adding the `valid` bit, a [[Valid.fire]] method is also added that returns the `valid` bit. This
+ * provides a similarly named interface to [[DecoupledIO.fire]].
+ *
+ * @see [[Decoupled$ DecoupledIO Factory]]
+ * @see [[Irrevocable$ IrrevocableIO Factory]]
+ */
object Valid {
+
+ /** Wrap some [[Data]] in a valid interface
+ * @tparam T the type of the data to wrap
+ * @param gen the data to wrap
+ * @return the wrapped input data
+ */
def apply[T <: Data](gen: T): Valid[T] = new Valid(gen)
}
@@ -35,8 +88,7 @@ object Valid {
* consumer.io.in <> pipe.io.deq
* }}}
*/
-object Pipe
-{
+object Pipe {
@chiselName
def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int)(implicit compileOptions: CompileOptions): Valid[T] = {
if (latency == 0) {
@@ -58,8 +110,7 @@ object Pipe
}
}
-class Pipe[T <: Data](gen: T, latency: Int = 1)(implicit compileOptions: CompileOptions) extends Module
-{
+class Pipe[T <: Data](gen: T, latency: Int = 1)(implicit compileOptions: CompileOptions) extends Module {
class PipeIO extends Bundle {
val enq = Input(Valid(gen))
val deq = Output(Valid(gen))