Is it possible to avoid specifying a default in order to get an X in Chisel?

548 views Asked by At

The following Chisel code works as expected.

class Memo extends Module {                                                                                                                                                                                                                    
  val io = new Bundle {
    val wen     = Bool(INPUT)
    val wrAddr  = UInt(INPUT,  8)
    val wrData  = UInt(INPUT,  8)
    val ren     = Bool(INPUT)
    val rdAddr  = UInt(INPUT,  8)
    val rdData  = UInt(OUTPUT, 8)
  }
  val mem = Mem(UInt(width = 8), 256)
  when (io.wen) { mem(io.wrAddr) := io.wrData }                                                                                                                                                                                                
  io.rdData := UInt(0)
  when (io.ren) { io.rdData := mem(io.rdAddr) }                                                                                                                                                                                                
}

However, it's a compile-time error if I don't specify io.rdData := UInt(0), because defaults are required. Is there a way to either explicitly specify X or to have modules without defaults output X, erm, by default?

Some reasons you might want to do this are that nothing should rely on the output if ren isn't asserted, and Xs let you specify it, and specifying an X can tell the synthesis tool that it's a don't care, for optimization purposes.

2

There are 2 answers

0
Chris On BEST ANSWER

Chisel does not support X.

This is probably what you want:

io.rdData := mem(io.rdAddr)

(this prevents muxing between zero and mem's readout data).

If, for example, one is trying to infer a single-ported SRAM, the Chisel tutorial/manual describes how to do so (https://chisel.eecs.berkeley.edu/latest/chisel-tutorial.pdf):

val ram1p =
  Mem(UInt(width = 32), 1024, seqRead = true)
  val reg_raddr = Reg(UInt())
  when (wen) { ram1p(waddr) := wdata }
  .elsewhen (ren) { reg_raddr := raddr }
  val rdata = ram1p(reg_raddr)

In short, the read address needs to be registered (since we're dealing with synchronous memory in this example), and the enable signal on this register dictates that the read-out data only changes with that enable is true. Thus, the backend understands this a read-enable signal exists on the read port, and in this example, the write port and the read port are one and the same (since only one is ever accessed at a time). Or if you want 1w/1r (as per your example), you can change the "elsewhen (ren)" to a "when (ren)".

2
Garrett On

From the Chisel 2.0 Tutorial paper, only binary logic is supported at the moment:

2 Hardware expressible in Chisel

This version of Chisel also only supports binary logic, and does not support tri-state signals.

We focus on binary logic designs as they constitute the vast majority of designs in practice. We omit support for tri-state logic in the current Chisel language as this is in any case poorly supported by industry flows, and difficult to use reliably outside of controlled hard macros.