Search code examples
scalaverilogfpgachisel

Cannot use Bool in class parametrization to reverse reset polarity


I just started out with Chisel and wrote a simple counter to blink an led. The FPGA board (Lattice iCEstick) has an inverted reset signal, and instead of changing the polarity in the generated verilog, I want to set it in Chisel.

I found that Module has a _reset parameter of type Chisel.Bool that can be set to false which inverts the reset signal. Here is an example of where it is used by someone else. However I'm getting an error which I can't seem to fix. First, the code:

import Chisel._

class Blink( rstPol: Bool = null ) extends Module( _reset = rstPol ) {
  val io = new Bundle {
    val led = UInt( OUTPUT, 1 )
  }

  val cnt_next = UInt()
  val counter  = Reg( init = UInt( 0, 24 ), next = cnt_next )

  cnt_next := counter + UInt( 1 )

  io.led := counter( 23 )
}

object blinkmain {
  def main( args: Array[ String ] ): Unit = {
    chiselMain( Array( "--backend", "v" ),
      () => Module( new Blink( Bool( false ) ) )
    )
  }
}

And the error I get:

[error] Blink.scala:19 < /*??*/ Chisel.Bool(OUTPUT, width=1, connect to 0 inputs: ()) > doesn't have its component,yet. in class blinkmain$$anonfun$main$1$$anonfun$apply$1

If I don't supply the Bool( false ) parameter, then I get no errors, but my reset polarity of course remains positve.

I have tried rstPol: Bool = Bool( false ) and Module( _reset = Bool( false ) ) but I get the same error on line 3. It seems like it's trying to assign the Bool to something that doesn't have a width, but I have no idea how that's possible.

I checked which version of Chisel I'm using and it's 2.2.33. Here is my build.sbt file in case it's important:

scalaVersion := "2.11.7"

libraryDependencies += "edu.berkeley.cs" %% "chisel" $ "latest.version"

scalacOptions ++= Seq("-deprecation", "-feature", "-unchecked", "-language:reflectiveCalls")

Solution

  • Since I'm new to Scala and Chisel, I wrongly assumed that the _reset parameter of Module was a Bool to indicate whether a positive or negative reset signal would be generated. You can connect a Bool INPUT to _reset however, contrary to a Bool OUTPUT as the error message mentions.

    This is how I fixed it (I did expand it with a counter width parameter swidth, but that's irrelevant):

    import Chisel._
    
    class Blink( swidth: Int, rst: Bool = null ) extends Module( _reset = rst ) {
      val io = new Bundle {
        val led = UInt( OUTPUT, 5 )
      }
    
      val counter = Reg( init = UInt( 0, width = swidth ) )
    
      counter := counter + UInt( 1 )
    
      io.led := counter( swidth - 1, swidth - 5 )
    }
    
    class Top extends Module {
      val io = new Bundle {
        val led  = UInt( OUTPUT, 5 )
        val rstn = Bool( INPUT )
      }
    
      val rst   = Reg( next = Reg( next = !io.rstn ) )
      val blink = Module( new Blink( 27, rst ) )
    
      blink.io.led <> io.led
    }
    
    object BlinkMain {
      def main( args: Array[ String ] ): Unit = {
        chiselMain( Array( "--backend", "v", "--targetDir", "verilog" ),
          () => Module( new Top() )
        )
      }
    }
    

    So I created a Top module that instantiates the Blink, which takes the inverted reset input (rstn), inverts it, and assigns that to _reset. For good measure, I also route rstn through two flip-flops to sync it up with the input clock signal.