1

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.

Enea Dume
  • 3,014
  • 3
  • 21
  • 36
FabienM
  • 3,421
  • 23
  • 45
  • It's very useful to have access to your repo but it's hard for me to repeat the error. Perhaps you could make a branch in your repo specifically demonstrating the error. – Chick Markley Sep 17 '19 at 17:28
  • 1
    There's nothing wrong with putting as much logic and state as you want in a RawModule. Just as a dumb sanity check, you have outputs that the memory is used to drive, correct? Otherwise it might be removed by DeadCodeElimination. If it's not something simple like that, a runnable example would be helpful to debug. – Jack Koenig Sep 17 '19 at 18:46

1 Answers1

1

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.

FabienM
  • 3,421
  • 23
  • 45