Files
eb001/src/main/scala/backBoard/shin/SpiInterface.scala
2025-10-01 08:41:43 +08:00

240 lines
7.3 KiB
Scala
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package BACK
import chisel3._
import chisel3.util._
class QSPIInterfaceIO extends Bundle{
val sck = Input(Bool())
val mosi = Input(UInt(4.W))
val miso = Output(UInt(4.W))
val isDirIn = Output(Bool())
val csn = Input(Bool())
}
class SSPIInterfaceIO extends Bundle{
val sck = Input(Bool())
val mosi = Input(Bool())
val miso = Output(Bool())
val csn = Input(Bool())
}
class RegAccessInterfaceIO extends Bundle{
val addrw = Output(UInt(16.W))
val addrr = Output(UInt(16.W))
val dataw = Output( UInt(8.W) )
val datar = Input( UInt(8.W) )
val isEnW = Output(Bool())
val isEnR = Output(Bool())
}
abstract class SpiInterfaceBase extends Module with RequireAsyncReset{
val io = IO(new RegAccessInterfaceIO)
val sck = Wire(Bool())
val csn = Wire(Bool())
//数据信号相对SCK的稳定应该由外部主机保证因此认为SCK采样时刻数据都是稳定正确的
val shiftSCK = ShiftRegisters(sck, 3, false.B, true.B)
val shiftCSn = ShiftRegisters(csn, 3, true.B, true.B)
val isSckPosedge = ~shiftSCK(2) & shiftSCK(1)
val isSckNegedge = shiftSCK(2) & ~shiftSCK(1)
val isSckPosedgeNext = ShiftRegisters(isSckPosedge, 2, false.B, true.B)
val exRego = RegInit(0.U(8.W))
val exRegi = RegInit(0.U(8.W))
val addrw = RegInit(0.U(16.W))
val addrr = RegInit(0.U(16.W))
val spiCmd = RegInit(0.U(1.W))
val isSpiWrite = spiCmd === 0.U
val isSpiRead = spiCmd === 1.U
val bitSel = RegInit(0.U(3.W))
val bitSelNext = RegNext(bitSel, 0.U(3.W))
val byteSel = RegInit(0.U(12.W))
val byteSelNext = RegNext(byteSel, 0.U(12.W))
io.isEnW := isSckPosedgeNext(0) & ~shiftCSn(2) & bitSelNext.andR & isSpiWrite & byteSelNext >= 3.U
io.dataw := exRegi
io.addrr := addrr
io.addrw := addrw
when( shiftCSn(2) & ~shiftCSn(1) ){
byteSel := 0.U
} .elsewhen( isSckPosedge & ~shiftCSn(1) ){
when( bitSel.andR ){
byteSel := byteSel + 1.U
}
}
}
class SSpiInterface extends SpiInterfaceBase{
val spi = IO(new SSPIInterfaceIO)
val shiftMOSI = ShiftRegisters(spi.mosi, 3, false.B, true.B)
sck := spi.sck
csn := spi.csn
io.isEnR :=
(isSckPosedge & ~shiftCSn(1) & bitSel === 0.U & shiftMOSI(1) === 1.U & byteSel === 2.U ) |
(isSckPosedge & ~shiftCSn(1) & bitSel === 0.U & isSpiRead & byteSel >= 3.U )
when( shiftCSn(2) & ~shiftCSn(1) || (~shiftCSn(2) & shiftCSn(1)) ){ //CS下跳或上跳
spiCmd := 0.U
} .elsewhen( isSckPosedge & ~shiftCSn(1) & byteSel === 2.U & bitSel === 0.U ){ //CS为低且SCK上跳的第0byte
spiCmd := shiftMOSI(1)
}
spi.miso := exRego.extract(7)
when( shiftCSn(2) & ~shiftCSn(1) ){
bitSel := 0.U
} .elsewhen( isSckPosedge & ~shiftCSn(1) ){
bitSel := bitSel + 1.U
}
//输入看SCK上升沿
when( isSckPosedge & ~shiftCSn(1) ){
when( bitSel === 0.U ){
exRegi := Cat( 0.U, shiftMOSI(1) )
}.otherwise{
exRegi := Cat( exRegi(6,0), shiftMOSI(1) )
}
}
//输出在SCK上升沿准备数据
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
exRego := 0.U //第一个byte 地址0
} .elsewhen( isSckPosedge & ~shiftCSn(1) ){
when( bitSel.andR ){
when((byteSel === 0.U || byteSel === 1.U) ){
exRego := 0.U //地址1cmd
} .elsewhen( isSpiRead ){
exRego := io.datar
}
}.otherwise{
exRego := exRego << 1
}
}
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
addrr := 0.U
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 0.U){ //CS为低且SCK上跳的第0byte
addrr := Cat( exRegi(6,0), shiftMOSI(1) )
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 1.U) {//CS为低且SCK上跳的第0byte
addrr := Cat(addrr(7,0), exRegi(6,0), shiftMOSI(1))
} .otherwise{ // byteSel > 1.U
when( isSckPosedge & byteSel >= 2.U & bitSel === 0.U ){
addrr := addrr + 1.U
}
}
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
addrw := 0.U
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 0.U){ //CS为低且SCK上跳的第0byte
addrw := Cat( exRegi(6,0), shiftMOSI(1) )
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 1.U) {//CS为低且SCK上跳的第0byte
addrw := Cat(addrw(7,0), exRegi(6,0), shiftMOSI(1) )
} .otherwise{ // byteSel > 1.U
when( isSckPosedgeNext(0) & byteSelNext >= 3.U & bitSelNext.andR ){
addrw := addrw + 1.U
}
}
}
class QSpiInterface(edge: Boolean) extends SpiInterfaceBase{
val qspi = IO(new QSPIInterfaceIO)
val shiftMOSI = ShiftRegisters(qspi.mosi, 3, 0.U(4.W), true.B)
sck := qspi.sck
csn := qspi.csn
qspi.miso := exRego(7, 4)
qspi.isDirIn := ~isSpiRead
io.isEnR :=
(isSckPosedge & ~shiftCSn(1) & bitSel === 0.U & shiftMOSI(1) === "b1000".U & byteSel === 2.U ) |
(isSckPosedge & ~shiftCSn(1) & bitSel === 0.U & isSpiRead & byteSel >= 3.U)
when( (shiftCSn(2) & ~shiftCSn(1)) || (~shiftCSn(2) & shiftCSn(1)) ){ //CS下跳或上跳
spiCmd := 0.U
} .elsewhen( isSckPosedge & ~shiftCSn(1) & byteSel === 2.U & bitSel === 0.U ){ //CS为低且SCK上跳的第0byte
spiCmd := shiftMOSI(1).extract(3)
}
when( shiftCSn(2) & ~shiftCSn(1) ){
bitSel := 0.U
} .elsewhen( isSckPosedge & ~shiftCSn(1) ){
bitSel := ~bitSel
}
//输入看SCK上升沿
when( isSckPosedge & ~shiftCSn(1) ){
when( bitSel === 0.U ){
exRegi := Cat( 0.U, shiftMOSI(1) )
}.otherwise{
exRegi := Cat( exRegi(3,0), shiftMOSI(1) )
}
}
//输出在SCK XX沿准备数据
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
exRego := 0.U //第一个byte 地址0
} .elsewhen(
(if( edge ) {isSckPosedge} else {isSckNegedge})
& ~shiftCSn(1)
){
when( (if( edge ) { bitSel.andR } else { bitSel === 0.U }) ){
when( byteSel === 0.U || byteSel === 1.U || ( if( edge ) { false.B } else { byteSel === 2.U } ) ){
exRego := 0.U //地址1cmd
} .elsewhen( isSpiRead ){
exRego := io.datar
}
}.otherwise{
exRego := exRego << 4
}
}
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
addrr := 0.U
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 0.U){ //CS为低且SCK上跳的第0byte
addrr := Cat( exRegi(3,0), shiftMOSI(1) )
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 1.U) {//CS为低且SCK上跳的第0byte
addrr := Cat(addrr(7,0), exRegi(3,0), shiftMOSI(1))
} .otherwise{ // byteSel > 1.U
when( isSckPosedge & byteSel >= 2.U & bitSel === 0.U ){
addrr := addrr + 1.U
}
}
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
addrw := 0.U
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 0.U){ //CS为低且SCK上跳的第0byte
addrw := Cat( exRegi(3,0), shiftMOSI(1) )
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 1.U) {//CS为低且SCK上跳的第0byte
addrw := Cat(addrw(7,0), exRegi(3,0), shiftMOSI(1) )
} .otherwise{ // byteSel > 1.U
when( isSckPosedgeNext(0) & byteSelNext >= 3.U & bitSelNext.andR ){
addrw := addrw + 1.U
}
}
}