From 5ccf101648a060d30ce4af71a510bac054e9c3ce Mon Sep 17 00:00:00 2001 From: RuigeLee Date: Tue, 9 Sep 2025 17:48:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E8=B7=A8=E6=97=B6=E9=92=9F?= =?UTF-8?q?=E5=9F=9FQSPI=EF=BC=8C=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scala/backBoard/shin/ASpiInterface.scala | 199 ++++++++++++++++++ .../backBoard/shin/NSpiInterface.scala.bk | 147 ------------- 2 files changed, 199 insertions(+), 147 deletions(-) create mode 100644 src/main/scala/backBoard/shin/ASpiInterface.scala delete mode 100644 src/main/scala/backBoard/shin/NSpiInterface.scala.bk diff --git a/src/main/scala/backBoard/shin/ASpiInterface.scala b/src/main/scala/backBoard/shin/ASpiInterface.scala new file mode 100644 index 0000000..36a85d9 --- /dev/null +++ b/src/main/scala/backBoard/shin/ASpiInterface.scala @@ -0,0 +1,199 @@ +package BACK + +import chisel3._ +import chisel3.util._ + +import freechips.rocketchip.util + +abstract class AsyncSpiInterfaceBase extends Module with RequireAsyncReset{ + val io = IO(new RegAccessInterfaceIO) + val qspi = IO(new QSPIInterfaceIO) + + val rxFifo = Module(new AsyncQueue( UInt(4.W), params = AsyncQueueParams( + depth = 8, + sync = 2)) + ) + // qspi.isDirIn := ~isSpiRead + + rxFifo.io.enq_clock := qspi.sck + rxFifo.io.enq_reset := qspi.csn | reset.asBool + rxFifo.io.enq.valid := true.B + rxFifo.io.enq.bits := qspi.mosi + when( rxFifo.io.enq.valid & ~rxFifo.io.enq.ready ){ + printf("Warning, Async QSPI rxfifo overflow!\n") + } + + rxFifo.io.deq_clock := clock.asBool + rxFifo.io.deq_reset := qspi.csn | reset.asBool + rxFifo.io.deq = Decoupled(gen) + + val txFifo = Module(new AsyncQueue( UInt(4.W), params = AsyncQueueParams( + depth = 8, + sync = 2)) + ) + + txFifo.io.enq_clock := clock.asBool + txFifo.io.enq_reset := qspi.csn | reset.asBool + txFifo.io.enq = Flipped(Decoupled(gen)) + + txFifo.io.deq_clock := qspi.sck + txFifo.io.deq_reset := qspi.csn | reset.asBool + qspi.miso := txFifo.io.deq.bits + + when( ~txFifo.io.deq.valid & txFifo.io.deq.ready ){ + printf("Warning, Async QSPI txfifo underflow!\n") + } + + + + + + +} + +trait AsyncQSpiInterfaceAsync extends AsyncSpiInterfaceBase{ + + val bitSel_Async = withClockAndReset( clock = qspi.sck, reset = qspi.csn ) { RegInit(0.U(3.W)) } + val byteSel_Async = withClockAndReset( clock = qspi.sck, reset = qspi.csn ) { RegInit(0.U(12.W)) } + // val exRego = RegInit(0.U(8.W)) + val exRegi_Async = withClockAndReset( clock = qspi.sck, reset = qspi.csn ) { RegInit(0.U(8.W)) } + val isDirIn = withClockAndReset( clock = qspi.sck, reset = qspi.csn ) { RegInit(true.B) } + qspi.isDirIn := isDirIn + + + when( bitSel_Async.andR ){ + byteSe_Asyncl := byteSel_Async + 1.U + } + + when( true.B ){ + bitSel_Async := ~bitSel_Async + } + + when( bitSel === 0.U ){ + exRegi_Async := Cat( 0.U, qspi.mosi ) + }.otherwise{ + exRegi_Async := Cat( exRegi(3,0), qspi.mosi ) + } + + when( byteSel_Async === 2.U & bitSel_Async === 0.U ){ //CS为低,且SCK上跳的第0byte + isDirIn := qspi.mosi === "b1000".U + } + +} + +trait AsyncQSpiInterfaceSync extends AsyncSpiInterfaceBase{ + + val shiftCSn = ShiftRegisters(qspi.csn, 3, true.B, true.B) + val bitSel = RegInit(0.U(3.W)) + val byteSel = RegInit(0.U(12.W)) + val exRego = RegInit(0.U(8.W)) + val exRegi = RegInit(0.U(8.W)) + + val bitSelNext = RegNext(bitSel, 0.U(3.W)) + val byteSelNext = RegNext(byteSel, 0.U(12.W)) + + when( shiftCSn(2) & ~shiftCSn(1) ){ + byteSel := 0.U + } .elsewhen( rxFifo.io.deq.fire ){ + when( bitSel.andR ){ + byteSel := byteSel + 1.U + } + } + + when( shiftCSn(2) & ~shiftCSn(1) ){ + bitSel := 0.U + } .elsewhen( rxFifo.io.deq.fire ){ + bitSel := ~bitSel + } + + + + //输入看SCK上升沿 + when( rxFifo.io.deq.fire ){ + when( bitSel === 0.U ){ + exRegi := Cat( 0.U, rxFifo.io.deq.bits ) + }.otherwise{ + exRegi := Cat( exRegi(3,0), rxFifo.io.deq.bits ) + } + } + rxFifo.io.deq.ready := true.B + + //输出在SCK上升沿准备数据 + when( rxFifo.io.deq.fire ){ + when( bitSel.andR ){ + when((byteSel === 0.U || byteSel === 1.U) ){ + exRego := 0.U //地址1,cmd + } .elsewhen( isSpiRead ){ //byteSel >= 2 + exRego := io.datar + } + }.otherwise{ + exRego := exRego << 4 + } + } + + + txFifo.io.enq.valid := rxFifo.io.deq.fire & isSpiRead & byteSel >= 2.U + txFifo.io.enq.bits := exRego(7, 4) + + when( txFifo.io.enq.valid & ~txFifo.io.enq.ready ){ + printf("Warning, Async QSPI txfifo overflow!\n") + } + + when( rxFifo.io.deq.fire ){ + when( bitSel.andR & byteSel === 0.U){ //CS为低,且SCK上跳的第0byte + addrr := Cat( exRegi(3,0), rxFifo.io.deq.bits ) + } .elsewhen( bitSel.andR & byteSel === 1.U) {//CS为低,且SCK上跳的第0byte + addrr := Cat(addrr(7,0), exRegi(3,0), rxFifo.io.deq.bits) + } .otherwise{ // byteSel > 1.U + when( byteSel >= 2.U & bitSel === 0.U ){ + addrr := addrr + 1.U + } + } + } + + when( rxFifo.io.deq.fire ){ + when( bitSel.andR & byteSel === 0.U){ //CS为低,且SCK上跳的第0byte + addrw := Cat( exRegi(3,0), rxFifo.io.deq.bits ) + } .elsewhen( bitSel.andR & byteSel === 1.U) {//CS为低,且SCK上跳的第0byte + addrw := Cat(addrw(7,0), exRegi(3,0), rxFifo.io.deq.bits ) + } .otherwise{ // byteSel > 1.U + when( byteSelNext >= 3.U & bitSelNext.andR ){ + addrw := addrw + 1.U + } + } + } + + + + + val isEnW = RegInit(false.B); io.isEnW := isEnW + val isEnR = RegInit(false.B); io.isEnR := isEnR + + when( ~shiftCSn(2) & bitSelNext.andR & isSpiWrite & byteSelNext >= 3.U ){ + isEnW := true.B + } .otherwise{ + isEnW := false.B + } + + when( ~shiftCSn(1) & ( + (bitSel === 0.U & rxFifo.io.deq.bits === "b1000".U & byteSel === 2.U ) || + (bitSel === 0.U & isSpiRead & byteSel >= 3.U) + )){ + io.isEnR := true.B + } .otherwise{ + io.isEnR := false.B + } + + + when( (shiftCSn(2) & ~shiftCSn(1)) || (~shiftCSn(2) & shiftCSn(1)) ){ //CS下跳或上跳 + spiCmd := 0.U + } .elsewhen( ~shiftCSn(1) & byteSel === 2.U & bitSel === 0.U ){ //CS为低,且SCK上跳的第0byte + spiCmd := rxFifo.io.deq.bits.extract(3) + } + + +} + +class AsyncQSpiInterface extends AsyncSpiInterfaceBase +with AsyncQSpiInterfaceAsync +with AsyncQSpiInterfaceSync diff --git a/src/main/scala/backBoard/shin/NSpiInterface.scala.bk b/src/main/scala/backBoard/shin/NSpiInterface.scala.bk deleted file mode 100644 index 207d97b..0000000 --- a/src/main/scala/backBoard/shin/NSpiInterface.scala.bk +++ /dev/null @@ -1,147 +0,0 @@ -package BACK - -import chisel3._ -import chisel3.util._ - - - -abstract class SyncSpiInterfaceBase extends Module with RequireAsyncReset{ - val io = IO(new RegAccessInterfaceIO) - -} - -class SyncSSpiInterface extends SyncSpiInterfaceBase{ - val spi = IO(new SSPIInterfaceIO) - - // withClockAndReset(sck.asClock, reset.asBool){ - - - - spi.miso := exRego.extract(7) - - val bitSel = withClockAndReset(spi.sck.asClock, spi.csn){RegInit(0.U(3.W)) } - val byteSel = withClockAndReset(spi.sck.asClock, spi.csn){RegInit(0.U(12.W))} - val exRego = withClockAndReset(spi.sck.asClock, spi.csn){RegInit(0.U(8.W))} - val exRegi = withClockAndReset(spi.sck.asClock, spi.csn){RegInit(0.U(8.W))} - - - - when( true.B ){ - bitSel := bitSel + 1.U - } - - when( bitSel.andR ){ - byteSel := byteSel + 1.U - } - - when( true.B ){ - exRegi := Cat( exRegi(6 ,0), spi.mosi ) - } - - - when( bitSel === 0.U ){ - when((byteSel === 1.U || byteSel === 2.U) ){ - exRego := 0.U //地址1,cmd - } .elsewhen( isSpiRead ){ - exRego := datar_async - } - }.otherwise{ - exRego := exRego << 1 - } - - val addrw_async = withClockAndReset(spi.sck.asClock, spi.csn){ RegInit(0.U(16.W)) } - val addrr_async = withClockAndReset(spi.sck.asClock, spi.csn){ RegInit(0.U(16.W)) } - val dataw_async = withClockAndReset(spi.sck.asClock, spi.csn){ RegInit(0.U(8.W)) } - val datar_async = withClockAndReset(spi.sck.asClock, spi.csn){ RegInit(0.U(8.W)) } - val spiCmd = withClockAndReset(spi.sck.asClock, spi.csn){ RegInit(false.B) } - val isSpiWrite = ~spiCmd - val isSpiRead = spiCmd - - when( bitSel === 0.U ){ - when( byteSel === 1.U ){ - addrw_async := exRegi - } .elsewhen( byteSel === 2.U ) { - addrw_async := Cat(addrw_async(7,0), exRegi) - } .elsewhen( byteSel > 3.U ){ - addrw_async := addrw_async + 1.U - } - } - - when( bitSel === 0.U ){ - when( byteSel === 1.U ){ - addrr_async := exRegi - } .elsewhen( byteSel === 2.U ) { - addrr_async := Cat(addrr_async(7,0), exRegi) - } .elsewhen( byteSel > 2.U ){ - addrr_async := addrr_async + 1.U - } - } - - when( byteSel === 2.U & bitSel === 0.U ){ //CS为低,且SCK上跳的第0byte - spiCmd := spi.mosi - } - - - - when( bitSel === 0.U ){ - when( byteSel > 3.U & isSpiWrite ){ - dataw_async := exRegi - } - } - - - - io.dataw := exRegi - io.addrr := Mux( isSpiRead, addrr + 1.U, addrr ) - - // io.addrSel := - // Mux( isSpiRead, addrSel + 1.U, addrSel )//覆盖三种情况 - // val readData = RegEnable(io.datar, io.isEnR) - - - isEnW_async - isEnR_async - addrw_async - addrr_async - datar_async - dataw_async - - - // isEnR_async := bitSel === 1.U & (byteSel >= 2.U) & isSpiRead - // isEnW_async := bitSel === 0.U & (byteSel >= 4.U) & isSpiWrite - - val isEnWSet_async = withClockAndReset(spi.sck.asClock, spi.csn){ RegInit(false.B) } - val isEnWSet_sync = ShiftRegisters(isEnWSet_async, 3, false.B, true.B) - val isEnWReset_async = withClockAndReset(spi.sck.asClock, spi.csn){ ShiftRegister(isEnWSet_sync(1), 2, false.B, true.B) } - - when( bitSel === 0.U & (byteSel >= 4.U) & isSpiWrite ){ - assert( ~isEnWSet_async, "Assert Failed @spi!\n" ) - isEnWSet_async := true.B - } .elsewhen(isEnWReSet_async){ - isEnWSet_async := false.B - } - - io.isEnW := ~isEnWSet_async(2) & isEnWSet_async(1) - io.addrw := addrw_async - io.dataw := dataw_async - - - val isEnRSet_async = withClockAndReset(spi.sck.asClock, spi.csn){ RegInit(false.B) } - val isEnRSet_sync = ShiftRegisters(isEnRSet_async, 3, false.B, true.B) - val isEnRReset_async = withClockAndReset(spi.sck.asClock, spi.csn){ ShiftRegister(isEnRSet_sync(1), 2, false.B, true.B) } - - when( bitSel === 1.U & (byteSel >= 2.U) & isSpiRead ){ - assert( ~isEnRSet_async, "Assert Failed @spi!\n" ) - isEnRSet_async := true.B - } .elsewhen(isEnRReSet_async){ - isEnRSet_async := false.B - } - - io.isEnR := ~isEnRSet_async(2) & isEnRSet_async(1) - io.addrr := addrr_async - datar_async := withClockAndReset(spi.sck.asClock, spi.csn){ RegEnable(io.datar, 0.U, isEnRReSet_async } - - -} - -