Search code examples
hdlchisel

Is RawModule only for Top connections?


I'm writing a SPI to Wishbone component with Chisel3, and for testing it on FPGA/real world I have to change the polarity of the reset (rstn).

To manage it I used RawModule for my Top module. And I used withClockAndReset() to change the reset polarity :

class TopSpi2Wb extends RawModule {
  val clock = IO(Input(Clock()))
  val rstn  = IO(Input(Bool()))
  // ...
   withClockAndReset(clock, !rstn) {
    val spi2Wb = Module(new Spi2Wb(dwidth, awidth))
    // module connections IO
  }

It seem's to works since I tryied to instanciate a Sync memory on the wishbone port. with this kind of code:

class TopSpi2Wb extends RawModule {
  val clock = IO(Input(Clock()))
  val rstn  = IO(Input(Bool()))
  // ...
   withClockAndReset(clock, !rstn) {
    val spi2Wb = Module(new Spi2Wb(dwidth, awidth))
    val wmem = SyncReadMem(1 << awidth, UInt(dwidth.W)) 
    val ackReg = RegInit(false.B)
    val datReg = RegInit(0.U(dwidth.W))

    ackReg := false.B
    datReg := 0.U(dwidth.W)
    when(spi2Wb.io.wbm.stb_o && spi2Wb.io.wbm.cyc_o) {
      when(spi2Wb.io.wbm.we_o){
        wmem.write(spi2Wb.io.wbm.adr_o, spi2Wb.io.wbm.dat_o)
        datReg := DontCare
      }.otherwise{
        datReg := wmem.read(spi2Wb.io.wbm.adr_o, spi2Wb.io.wbm.stb_o &
                            spi2Wb.io.wbm.cyc_o & !spi2Wb.io.wbm.we_o)
      }
  // ...

That compile without error, but I can't manage to read/write on memory correctly (with icarus). Verilog emitted seems to drop memory instantiation.

Maybe it's discouraged to write chisel code like Register, memories, ... and just instantiate one top module in RawModule no ?

Well, if I'm wrapping a top module in the RawModule, that works really better:

// Testing Spi2Wb with a memory connexion
// and reset inverted
class TopSpi2Wb extends RawModule {
  // Clock & Reset
  val clock = IO(Input(Clock()))
  val rstn  = IO(Input(Bool()))

  // Simple blink
  val blink = IO(Output(Bool()))

  // SPI
  val mosi = IO(Input(Bool()))
  val miso = IO(Output(Bool()))
  val sclk = IO(Input(Bool()))
  val csn  = IO(Input(Bool()))

  val dwidth = 8
  val awidth = 7

  withClockAndReset(clock, !rstn) {
    val spi2Wb = Module(new Spi2WbMem(dwidth, awidth))
    blink := spi2Wb.io.blink
    spi2Wb.io.mosi := mosi
    miso := spi2Wb.io.miso
    spi2Wb.io.sclk := sclk
    spi2Wb.io.csn := csn
  }
}

With the code above, all connection and register instantiation for Wishbone memory are done in Spi2WbMem() standard module.


Solution

  • As jkoenig asked I re-written the module to reproduce the bug and ... fixed it ! Sorry for the inconvenience.

    I had some difficulties to find the bug because Icarus didn't dump the content of memory and I thought it was not generated.

    I think that my initial module wrapping fixed the bug without my realizing it.