Files
eb001/src/main/scala/backBoard/shin/SpiInterface.scala
2026-02-09 16:32:02 +08:00

287 lines
8.2 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{
def SLOW : Boolean
def FAST : Boolean
def OPER444 : Boolean
def OPER114 : Boolean
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 shiftMOSI = Wire(Bool())
val shiftDat = Wire(UInt(4.W))
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))
val spiLen = RegInit(2.U(12.W))
val spiLenTemp = RegInit(2.U(12.W))
val spiCnt = RegInit(0.U(12.W))
io.isEnW := isSckPosedgeNext(0) & ~shiftCSn(2) & bitSelNext.andR & isSpiWrite & byteSelNext >= 4.U & (spiCnt < spiLen)
io.isEnR := (isSckPosedge & ~shiftCSn(1) & bitSel === 0.U & isSpiRead & byteSel >= 3.U ) & (spiCnt <= spiLen)
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
}
}
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
spiCnt := 0.U
} .elsewhen( io.isEnR | io.isEnW ){
spiCnt := spiCnt + 1.U
}
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
spiLenTemp := 0.U
spiLen := 2.U
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 2.U){ //CS为低且SCK上跳的第0byte
if( OPER444 ){
spiLenTemp := Cat( shiftDat, 0.U(8.W) )
} else if( OPER114 ){
spiLenTemp := Cat( exRegi(2,0), shiftMOSI, 0.U(8.W) )
}
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 3.U) {//CS为低且SCK上跳的第0byte
if( OPER444 ){
spiLenTemp := Cat(spiLenTemp(11,8), exRegi(3,0), shiftDat)
spiLen := Cat(spiLenTemp(11,8), exRegi(3,0), shiftDat)
} else if( OPER114 ){
spiLenTemp := Cat(spiLenTemp(11,8), exRegi(6,0), shiftMOSI)
spiLen := Cat(spiLenTemp(11,8), exRegi(6,0), shiftMOSI)
}
}
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
addrr := 0.U
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 0.U){ //CS为低且SCK上跳的第0byte
if( OPER444 ){
addrr := Cat( exRegi(3,0), shiftDat )
} else if( OPER114 ){
addrr := Cat( exRegi(6,0), shiftMOSI )
}
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 1.U) {//CS为低且SCK上跳的第0byte
if( OPER444 ){
addrr := Cat(addrr(7,0), exRegi(3,0), shiftDat)
} else if( OPER114 ){
addrr := Cat(addrr(7,0), exRegi(6,0), shiftMOSI)
}
} .otherwise{ // byteSel > 1.U
when( isSckPosedge & byteSel >= 3.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
if( OPER444 ){
addrw := Cat( exRegi(3,0), shiftDat )
} else if( OPER114 ){
addrw := Cat( exRegi(6,0), shiftMOSI )
}
} .elsewhen(isSckPosedge & ~shiftCSn(1) & bitSel.andR & byteSel === 1.U) {//CS为低且SCK上跳的第0byte
if( OPER444 ){
addrw := Cat(addrw(7,0), exRegi(3,0), shiftDat )
} else if( OPER114 ){
addrw := Cat(addrw(7,0), exRegi(6,0), shiftMOSI )
}
} .otherwise{ // byteSel > 1.U
when( isSckPosedgeNext(0) & byteSelNext >= 4.U & bitSelNext.andR ){
addrw := addrw + 1.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 := (if( OPER114 ) {shiftMOSI} else { shiftDat.extract(3) })
}
}
class SSpiInterface extends SpiInterfaceBase{
def SLOW = true
def FAST = false
def OPER444 = false
def OPER114 = true
val spi = IO(new SSPIInterfaceIO)
shiftMOSI := ShiftRegister(spi.mosi, 2, false.B, true.B)
shiftDat := DontCare
sck := spi.sck
csn := spi.csn
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 )
}.otherwise{
exRegi := Cat( exRegi(6,0), shiftMOSI )
}
}
//输出在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 || byteSel === 2.U ) ){ //第3byte准备第4byte开始发送
exRego := 0.U //地址1cmd
} .elsewhen( isSpiRead ){
exRego := io.datar
}
}.otherwise{
exRego := exRego << 1
}
}
}
class QSpiInterface(mode: Int) extends SpiInterfaceBase{
def SLOW_444 = 0
def SLOW_114 = 1
def FAST_444 = 2
def FAST_114 = 3
def SLOW = if ( mode == 0 || mode == 1 ) {true} else {false}
def FAST = if ( mode == 2 || mode == 3 ) {true} else {false}
def OPER444 = if ( mode == 0 || mode == 2 ) {true} else {false}
def OPER114 = if ( mode == 1 || mode == 3 ) {true} else {false}
val qspi = IO(new QSPIInterfaceIO)
shiftDat := ShiftRegister(qspi.mosi, 2, 0.U(4.W), true.B)
shiftMOSI := shiftDat.extract(0)
sck := qspi.sck
csn := qspi.csn
qspi.miso := exRego(7, 4)
qspi.isDirIn := isSpiWrite || byteSel < 4.U
when( shiftCSn(2) & ~shiftCSn(1) ){
bitSel := 0.U
} .elsewhen( isSckPosedge & ~shiftCSn(1) ){
when( (if( OPER114 ) {byteSel <= 3.U} else {false.B}) ){
bitSel := bitSel + 1.U
} .otherwise{
bitSel := ~bitSel
}
}
//输入看SCK上升沿
when( isSckPosedge & ~shiftCSn(1) ){
when( (if( OPER114 ) {byteSel <= 3.U} else {false.B}) ){
when( bitSel === 0.U ){
exRegi := Cat( 0.U, shiftMOSI )
}.otherwise{
exRegi := Cat( exRegi(6,0), shiftMOSI )
}
} .otherwise{
when( bitSel === 0.U ){
exRegi := Cat( 0.U, shiftDat )
}.otherwise{
exRegi := Cat( exRegi(3,0), shiftDat )
}
}
}
//输出在SCK XX沿准备数据
when( shiftCSn(2) & ~shiftCSn(1) ){ //CS下跳
exRego := 0.U //第一个byte 地址0
} .elsewhen(
(if( FAST ) {isSckPosedge} else {isSckNegedge})
& ~shiftCSn(1)
){
when( (if( FAST ) { bitSel.andR } else { bitSel === 0.U }) ){
when( byteSel === 0.U || byteSel === 1.U || byteSel === 2.U || ( if( FAST ) { false.B } else { byteSel === 3.U } ) ){
exRego := 0.U //地址1cmd
} .elsewhen( isSpiRead ){
exRego := io.datar
}
}.otherwise{
exRego := exRego << 4
}
}
}