尝试跨时钟域QSPI,失败
This commit is contained in:
199
src/main/scala/backBoard/shin/ASpiInterface.scala
Normal file
199
src/main/scala/backBoard/shin/ASpiInterface.scala
Normal file
@@ -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
|
||||
@@ -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 }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user