From 21ffc1b58d297d42844a7c08d7b4a5e88619dc1f Mon Sep 17 00:00:00 2001 From: RuigeLee Date: Tue, 16 Sep 2025 18:01:14 +0800 Subject: [PATCH] =?UTF-8?q?spi=E8=B7=A8=E6=97=B6=E9=92=9F=E5=9F=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scala/backBoard/shin/NSpiInterface.scala | 233 ++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 src/main/scala/backBoard/shin/NSpiInterface.scala diff --git a/src/main/scala/backBoard/shin/NSpiInterface.scala b/src/main/scala/backBoard/shin/NSpiInterface.scala new file mode 100644 index 0000000..dfe1cd7 --- /dev/null +++ b/src/main/scala/backBoard/shin/NSpiInterface.scala @@ -0,0 +1,233 @@ +package BACK + +import chisel3._ +import chisel3.util._ + + + +abstract class SyncSpiInterfaceBase extends Module with RequireAsyncReset{ + val io = IO(new RegAccessInterfaceIO) + val qspi = IO(new QSPIInterfaceIO) +} + +trait SyncSpiAsync{ this: SyncSpiInterfaceBase => + + val bitSel = withClockAndReset(~qspi.sck.asClock, qspi.csn){RegInit(0.U(3.W)) } + val byteSel = withClockAndReset(~qspi.sck.asClock, qspi.csn){RegInit(0.U(12.W))} + val exRego = withClockAndReset(~qspi.sck.asClock, qspi.csn){RegInit(0.U(8.W))} + val exRegi = withClockAndReset(~qspi.sck.asClock, qspi.csn){RegInit(0.U(8.W))} + + qspi.miso := exRego(7, 4) + qspi.isDirIn := ~isSpiRead + + when( true.B ){ + bitSel := ~bitSel + } + + when( bitSel.andR ){ + byteSel := byteSel + 1.U + } + + when( bitSel === 0.U ){ + exRegi := Cat( 0.U, qspi.mosi ) + }.otherwise{ + exRegi := Cat( exRegi(3,0), qspi.mosi ) + } + + when( bitSel === 0.U ){ + when((byteSel === 1.U || byteSel === 2.U || byteSel === 3.U ) ){ + exRego := 0.U //地址1,cmd + } .elsewhen( isSpiRead ){ + when( ~isPing_async ){ //取巧 + exRego := datar_sync(0) + } .otherwise{ + exRego := datar_sync(1) + } + } + } .otherwise{ + exRego := exRego << 4 + } + + + val addrw_async = for( _ <- 0 until 2 ) yield { withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(0.U(16.W)) } } + val addrr_async = for( _ <- 0 until 2 ) yield { withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(0.U(16.W)) } } + val dataw_async = for( _ <- 0 until 2 ) yield { withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(0.U(8.W)) } } + val isEnR_async = for( _ <- 0 until 2 ) yield { withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(false.B) } } + val isEnW_async = for( _ <- 0 until 2 ) yield { withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(false.B) } } + + val spiLen = withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(2.U(12.W)) } + val spiCnt = withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(0.U(12.W)) } + val isSpiWrite = withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(false.B) } + val isSpiRead = withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(false.B) } + val isPing_async = withClockAndReset(~qspi.sck.asClock, qspi.csn){ RegInit(false.B) } + + when( isEnR_async(0) | isEnW_async(0) | isEnR_async(1) | isEnW_async(1) ){ + spiCnt := spiCnt + 1.U + } + + when( byteSel === 4.U & bitSel === 0.U ){ + spiLen := Cat( exRegi, 0.U(8.W) ) + } .elsewhen( byteSel === 4.U & bitSel.andR ){ + spiLen := Cat( spiLen(11, 8), exRegi, 0.U(4.W) ) + } .elsewhen( byteSel === 5.U & bitSel === 0.U ){ + spiLen := Cat( spiLen(11, 4), exRegi ) + } + +} + +trait SyncSpiSync{ this: SyncSpiInterfaceBase => + +} + +class SyncQSpiInterface extends SyncSpiInterfaceBase +with SyncSpiAsync +with SyncSpiSync{ + + + + + + + + + + + + + when( bitSel === 0.U ){ + when( byteSel === 1.U ){ + addrw_async(0) := exRegi + addrw_async(1) := exRegi + } .elsewhen( byteSel === 2.U ) { + addrw_async(0) := Cat(addrw_async(7,0), exRegi) + addrw_async(1) := Cat(addrw_async(7,0), exRegi) + } .elsewhen( byteSel >= 5.U ){ + when( ~isPing_async ){ + addrw_async(0) := addrw_async(0) + 2.U + } .otherwise{ + addrw_async(1) := addrw_async(1) + 2.U + } + } + } + + when( bitSel === 0.U ){ + when( byteSel === 1.U ){ + addrr_async(0) := exRegi + addrr_async(1) := exRegi + } .elsewhen( byteSel === 2.U ) { + addrr_async(0) := Cat(addrr_async(7,0), exRegi) + addrr_async(1) := Cat(addrr_async(7,0), exRegi) + } + } .otherwise{ + when( byteSel >= 2.U ){ + when( ~isPing_async ){ + addrr_async(0) := addrr_async(0) + 2.U + } .otherwise{ + addrr_async(1) := addrr_async(1) + 2.U + } + } + } + + + + when( byteSel === 2.U & bitSel === 0.U ){ //CS为低,且SCK上跳的第0byte + when( qspi.mosi.extract(3) ){ + isSpiRead := true.B + } .otherwise{ + isSpiWrite := true.B + } + } + + when( bitSel === 0.U ){ + when( byteSel > 3.U & isSpiWrite ){ + when( ~isPing_async ){ + dataw_async(0) := exRegi + } .otherwise{ + dataw_async(1) := exRegi + } + + } + } + + when( byteSel >= 2.U & bitSel.andR & (spiCnt < spiLen) & isSpiRead ){ + when( ~isPing_async ){ + isEnR_async(0) := true.B + } .otherwise{ + isEnR_async(1) := true.B + } + } .elsewhen( bitSel === 0.U ){ + isEnR_async(0) := false.B + isEnR_async(1) := false.B + } + + when( byteSel >= 5.U & bitSel === 0.U & (spiCnt < spiLen) & isSpiWrite ){ + when( ~isPing_async ){ + isEnW_async(0) := true.B + } .otherwise{ + isEnW_async(1) := true.B + } + } .elsewhen( bitSel.andR ){ + isEnW_async(0) := false.B + isEnW_async(1) := false.B + } + + + when( isEnR_async(0) | isEnW_async(0) ){ + assert( ~isPing_async ) + isPing_async := true.B + } .elsewhen( isEnR_async(1) | isEnW_async(1) ){ + assert( isPing_async ) + isPing_async := false.B + } + + val isPong_sync = RegInit(false.B) + + val isEnW_sync = for( _ <- 0 until 2 ) yield { ShiftRegisters( isEnW_async(i), 3, false.B, true.B ) } + val isEnR_sync = for( _ <- 0 until 2 ) yield { ShiftRegisters( isEnR_async(i), 3, false.B, true.B ) } + + val datar_sync = for( _ <- 0 until 2 ) yield { RegInit(0.U(8.W)) } + + val isEnW = for( _ <- 0 until 2 ) yield { ~isEnW_sync(i)(2) & isEnW_sync(i)(1) } + val isEnR = for( _ <- 0 until 2 ) yield { ~isEnR_sync(i)(2) & isEnR_sync(i)(1) } + + io.isEnW := + ( ~isPong_sync & isEnW(0) ) | + ( isPong_sync & isEnW(1) ) + + io.isEnR := + ( ~isPong_sync & isEnR(0) ) | + ( isPong_sync & isEnR(1) ) + + + io.addrw := Mux1H(Seq( + ~isPong_sync -> addrw_async(0), + isPong_sync -> addrw_async(1), + )) + + io.addrr := Mux1H(Seq( + ~isPong_sync -> addrr_async(0), + isPong_sync -> addrr_async(1), + )) + + io.dataw := Mux1H(Seq( + ~isPong_sync -> dataw_async(0), + isPong_sync -> dataw_async(1), + )) + + + when( io.isEnR ){ + when( RegNext(~isPong_sync, false.B) ){ + datar_sync(0) := io.datar + } .otherwise{ + datar_sync(1) := io.datar + } + } + + when( io.isEnR | io.isEnW ){ + isPong_sync := ~isPong_sync + } + + +} + +