Skip to content

Register Widths #10

@seldridge

Description

@seldridge

The asymmetry of how Reg, RegNext, and RegInit set their widths can lead to unexpected behavior.

h/t @antonblanchard

Type of issue: bug report | feature request | other enhancement

Impact: API modification

Development Phase: request

Other information

There's an old PR referencing and documenting some of this behavior: chipsalliance/chisel#455

If the current behavior is a bug, please provide the steps to reproduce the problem:

Consider the following example. While foo, bar, and baz have almost identical construction, foo has an unset width, bar was a width of 8, and baz is a bundle with an internal signal of width 8.

package examples

import chisel3._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
import chisel3.internal.sourceinfo.UnlocatableSourceInfo

object NoInfo {
  implicit val noInfo = UnlocatableSourceInfo
}

import NoInfo._

class DelayedBundle extends Bundle {
  val in = UInt(8.W)
}

class Delayed extends MultiIOModule {
  val in = IO(Input(UInt(8.W)))
  val bundle = IO(Input(new DelayedBundle))

  /** The width of foo is unset */
  val foo = RegNext(in)

  /** The width of bar is set to 8.W */
  val bar = Reg(chiselTypeOf(in))
  bar := in
  
  /** The width of baz is set to 8.W */
  val baz = RegNext(bundle)

  Seq(foo, bar, baz).foreach(a => println(a.widthOption))

}

object Delayed extends App {
  (new ChiselStage).execute(Array.empty, Seq(ChiselGeneratorAnnotation(() => new Delayed)))
}

This results in the following FIRRTL:

circuit Delayed : 
  module Delayed : 
    input clock : Clock
    input reset : UInt<1>
    input in : UInt<8>
    input bundle : {in : UInt<8>}
    
    reg foo : UInt, clock
    foo <= in
    reg bar : UInt<8>, clock
    bar <= in
    reg baz : {in : UInt<8>}, clock
    baz.in <= bundle.in

To be very concrete, I have implicit classes for doing automatic conversion to bits, words, etc. (i.e., (Bits) => Vec[UInt]). These rely on having widths known. Using these methods on foo will cause the implicit class methods to error out complaining that they can't be used on something that has an unknown width. However, they work with bar. This is unintuitive behavior as it would seem that foo and bar are identical constructions.

I do realize that RegNext(0.U) is probably the reason why this exists the way it does.

What is the current behavior?

The width of a RegNext is always unset when given a subtype of Bits.

What is the expected behavior?

The width of a RegNext should be set to the type of whatever is next.

Please tell us about your environment:

What is the use case for changing the behavior?

This clarifies unintuitive behavior and unifies behavior for RegNext when given different types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions