2025-02-13 18:14:26 +08:00
|
|
|
package BACK
|
|
|
|
|
|
|
|
|
|
import chisel3._
|
|
|
|
|
import chisel3.util._
|
|
|
|
|
|
|
|
|
|
import org.chipsalliance.cde.config._
|
|
|
|
|
import freechips.rocketchip.diplomacy._
|
|
|
|
|
import freechips.rocketchip.tilelink._
|
|
|
|
|
import freechips.rocketchip.interrupts._
|
|
|
|
|
|
|
|
|
|
import freechips.rocketchip.tile._
|
|
|
|
|
|
|
|
|
|
class RocCC2CDRInIO extends Bundle{
|
|
|
|
|
val overCLK = Bool()
|
|
|
|
|
val dDatIn = Bool()
|
|
|
|
|
val uDatIn = Bool()
|
|
|
|
|
|
|
|
|
|
val isLast = Bool()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class RocCC2CDROutIO extends Bundle{
|
|
|
|
|
val dDatOut = Bool()
|
|
|
|
|
val uDatOut = Bool()
|
|
|
|
|
|
|
|
|
|
val isOnline = Bool()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class RoCC2CDRIO extends Bundle{
|
|
|
|
|
val overCLK = Input(Bool())
|
|
|
|
|
val dDatIn = Input(Bool())
|
|
|
|
|
val dDatOut = Output(Bool())
|
|
|
|
|
val uDatIn = Input(Bool())
|
|
|
|
|
val uDatOut = Output(Bool())
|
|
|
|
|
|
|
|
|
|
val isOnline = Output(Bool())
|
|
|
|
|
val isLast = Input(Bool())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RoCC2CDR()(implicit p: Parameters) extends LazyModule {
|
|
|
|
|
val opcodes: OpcodeSet = OpcodeSet.custom0
|
|
|
|
|
val roccCSRs: Seq[CustomCSR] = Nil
|
|
|
|
|
lazy val module: RoCC2CDRImpl = new RoCC2CDRImpl(this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
abstract class RoCC2CDRImplBase(outer: RoCC2CDR)(implicit p: Parameters) extends LazyModuleImp(outer) {
|
|
|
|
|
val io = IO(new RoCCIO(0, 0))
|
|
|
|
|
|
|
|
|
|
// val cdrio: RoCC2CDRIO = IO(new RoCC2CDRIO)
|
|
|
|
|
val cdrInio = IO(Input(new RocCC2CDRInIO))
|
|
|
|
|
val cdrOutio = IO(Output(new RocCC2CDROutIO))
|
|
|
|
|
|
|
|
|
|
val CDRIn = for( i <- 0 until 2 ) yield { Module(new CDRIn) }
|
2025-07-22 09:35:06 +08:00
|
|
|
when(true.B){
|
|
|
|
|
print("Warning!!! New Code has not been reviewed!\n")
|
|
|
|
|
}
|
2025-02-13 18:14:26 +08:00
|
|
|
|
|
|
|
|
CDRIn(0).io.serDat := cdrInio.dDatIn
|
|
|
|
|
CDRIn(1).io.serDat := cdrInio.uDatIn
|
|
|
|
|
|
2025-07-22 09:35:06 +08:00
|
|
|
CDRIn(0).overCLK := cdrInio.overCLK
|
|
|
|
|
CDRIn(1).overCLK := cdrInio.overCLK
|
|
|
|
|
|
|
|
|
|
|
2025-02-13 18:14:26 +08:00
|
|
|
|
|
|
|
|
val CDROut = for( i <- 0 until 2 ) yield { Module(new CDROut) }
|
|
|
|
|
|
|
|
|
|
cdrOutio.dDatOut := CDROut(0).io.serDat
|
|
|
|
|
cdrOutio.uDatOut := CDROut(1).io.serDat
|
|
|
|
|
|
|
|
|
|
val txFifo = for( i <- 0 until 2 ) yield { Module(new Queue(UInt(32.W), 16)) }
|
|
|
|
|
val rxFifo = for( i <- 0 until 2 ) yield { Module(new Queue(UInt(32.W), 16)) }
|
|
|
|
|
|
|
|
|
|
val isTLWriteSoftReset = for( i <- 0 until 4 ) yield { Wire(Bool()) }
|
|
|
|
|
val isTLReadStatus = Wire( Bool() )
|
|
|
|
|
|
|
|
|
|
val txLeft = for( i <- 0 until 2 ) yield { RegInit(0.U(5.W)) }
|
|
|
|
|
val rxLeft = for( i <- 0 until 2 ) yield { RegInit(0.U(5.W)) }
|
|
|
|
|
|
|
|
|
|
val wdata = Wire(UInt(32.W))
|
|
|
|
|
|
2025-03-04 12:01:47 +08:00
|
|
|
val isTLReadRxFifoBypassTx = for( i <- 0 until 4 ) yield { Wire(Bool()) } //0 rx0->tx0, 1 rx0->tx1, 2 rx1 -> tx0, 3 rx1 ->tx1
|
2025-02-13 18:14:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trait RoCC2CDRImplTx{ this: RoCC2CDRImplBase =>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val isTLWriteTxLen = for( i <- 0 until 2 ) yield { Wire( Bool()) }
|
|
|
|
|
val isTLWriteTxFifo = for( i <- 0 until 2 ) yield { Wire( Bool()) }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val isTxFifoRelease = for( i <- 0 until 2 ) yield { Wire( Bool()) }
|
|
|
|
|
val txLen = for( i <- 0 until 2 ) yield { RegInit(0.U(12.W)) }
|
|
|
|
|
val isTxBusy = for( i <- 0 until 2 ) yield { RegInit(false.B) }
|
|
|
|
|
val isTxFull = for( i <- 0 until 2 ) yield { ~txFifo(i).io.enq.ready }
|
|
|
|
|
val intTxFifoFull = for( i <- 0 until 2 ) yield { ~RegNext(isTxFull(i), false.B) & isTxFull(i) }
|
|
|
|
|
val intTxFinish = for( i <- 0 until 2 ) yield { CDROut(i).io.axis.fire & CDROut(i).io.axis.bits.tlast }
|
|
|
|
|
val intTxEnd = for( i <- 0 until 2 ) yield { ShiftRegister( intTxFinish(i), 6, false.B, true.B) }
|
|
|
|
|
|
|
|
|
|
val intTxFifoDeq = for( i <- 0 until 2 ) yield { txFifo(i).io.deq.fire }
|
|
|
|
|
|
|
|
|
|
val txCnt = for( i <- 0 until 2 ) yield { Reg(UInt(2.W)) }
|
|
|
|
|
val txData = for( i <- 0 until 2 ) yield { Reg(UInt(32.W)) }
|
|
|
|
|
|
|
|
|
|
for( i <- 0 until 2 ) {
|
|
|
|
|
when( txFifo(i).io.deq.fire ){ //txCnt(i) === 3.U
|
|
|
|
|
txData(i) := txFifo(i).io.deq.bits
|
|
|
|
|
when( isTxBusy(i) ){
|
|
|
|
|
assert(CDROut(i).io.axis.fire)
|
|
|
|
|
}
|
|
|
|
|
} .elsewhen( CDROut(i).io.axis.fire ){
|
|
|
|
|
txData(i) := txData(i) << 8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
txFifo(i).io.deq.ready :=
|
|
|
|
|
isTxFifoRelease(i) & Mux( isTxBusy(i), CDROut(i).io.axis.fire & txCnt(i) === 3.U, true.B )
|
|
|
|
|
|
|
|
|
|
txFifo(i).reset := reset.asBool | isTLWriteSoftReset(0+i)
|
|
|
|
|
CDROut(i).reset := reset.asBool | isTLWriteSoftReset(0+i)
|
|
|
|
|
|
|
|
|
|
CDROut(i).io.axis.bits.tdata := txData(i).head(8)
|
|
|
|
|
CDROut(i).io.axis.bits.tlast := ~txFifo(i).io.deq.valid & txCnt(i) === 3.U
|
|
|
|
|
CDROut(i).io.axis.bits.tuser := false.B
|
|
|
|
|
CDROut(i).io.axis.valid := isTxBusy(i)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(i) ){
|
|
|
|
|
isTxBusy(i) := false.B
|
|
|
|
|
}.elsewhen( txFifo(i).io.deq.fire & ~isTxBusy(i) ){
|
|
|
|
|
isTxBusy(i) := true.B
|
|
|
|
|
} .elsewhen( CDROut(i).io.axis.fire & CDROut(i).io.axis.bits.tlast ){
|
|
|
|
|
isTxBusy(i) := false.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(0+i) ){
|
|
|
|
|
txCnt(i) := 0.U
|
|
|
|
|
} .elsewhen( CDROut(i).io.axis.fire ){
|
|
|
|
|
txCnt(i) := txCnt(i) + 1.U
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when( isTLWriteTxLen(i) ){
|
|
|
|
|
txLen(i) := wdata
|
|
|
|
|
} .elsewhen( CDROut(i).io.axis.fire ){
|
|
|
|
|
txLen(i) := txLen(i) - 1.U
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-04 12:01:47 +08:00
|
|
|
txFifo(i).io.enq.bits := Mux1H(Seq(
|
|
|
|
|
isTLWriteTxFifo(i) -> wdata,
|
|
|
|
|
isTLReadRxFifoBypassTx(0+i) -> rxFifo(0).io.deq.bits,
|
|
|
|
|
isTLReadRxFifoBypassTx(2+i) -> rxFifo(1).io.deq.bits,
|
|
|
|
|
))
|
|
|
|
|
|
2025-02-13 18:14:26 +08:00
|
|
|
|
2025-03-04 12:01:47 +08:00
|
|
|
|
|
|
|
|
//0 rx0->tx0, 1 rx0->tx1, 2 rx1 -> tx0, 3 rx1 ->tx1
|
|
|
|
|
|
|
|
|
|
txFifo(i).io.enq.valid :=
|
|
|
|
|
txLen(i) =/= 0.U & (
|
|
|
|
|
isTLWriteTxFifo(i) |
|
|
|
|
|
isTLReadRxFifoBypassTx(0+i) |
|
|
|
|
|
isTLReadRxFifoBypassTx(2+i)
|
|
|
|
|
)
|
|
|
|
|
|
2025-02-13 18:14:26 +08:00
|
|
|
when( isTLWriteSoftReset(0+i) ){
|
|
|
|
|
txLeft(i) := 0.U
|
|
|
|
|
} .elsewhen( txFifo(i).io.enq.fire & txFifo(i).io.deq.fire ){
|
|
|
|
|
txLeft(i) := txLeft(i)
|
|
|
|
|
} .elsewhen( txFifo(i).io.enq.fire ){
|
|
|
|
|
txLeft(i) := txLeft(i) + 1.U
|
|
|
|
|
} .elsewhen( txFifo(i).io.deq.fire ){
|
|
|
|
|
txLeft(i) := txLeft(i) - 1.U
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trait RoCC2CDRImplRx{ this: RoCC2CDRImplBase =>
|
|
|
|
|
|
|
|
|
|
val isTLReadRxLen = for( i <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
val isTLReadRxFifo = for( i <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
|
|
|
|
|
val rxLen = for( i <- 0 until 2 ) yield { RegInit(0.U(12.W)) }
|
|
|
|
|
val isRxValid = for( i <- 0 until 2 ) yield { rxFifo(i).io.deq.valid }
|
|
|
|
|
val isRxError = for( i <- 0 until 2 ) yield { RegInit(false.B) }
|
|
|
|
|
val isAxisEnd = for( i <- 0 until 2 ) yield { RegInit(false.B) }
|
|
|
|
|
val isRxEnd = for( i <- 0 until 2 ) yield { isAxisEnd(i) & ~rxFifo(i).io.deq.valid }
|
|
|
|
|
val intRxError = for( i <- 0 until 2 ) yield { ~RegNext(isRxError(i), false.B) & isRxError(i) }
|
|
|
|
|
val intRxStart = for( i <- 0 until 2 ) yield { rxLen(i) === 0.U & CDRIn(i).io.axis.fire }
|
|
|
|
|
val intRxEnd = for( i <- 0 until 2 ) yield { ~RegNext(isRxEnd(i), false.B) & isRxEnd(i) }
|
|
|
|
|
val intRxFifoEnq = for( i <- 0 until 2 ) yield { rxFifo(i).io.enq.fire }
|
|
|
|
|
val rxCnt = for( i <- 0 until 2 ) yield { RegInit(0.U(2.W)) }
|
|
|
|
|
val rxData = for( i <- 0 until 2 ) yield { Reg(UInt(24.W)) }
|
|
|
|
|
|
|
|
|
|
for( i <- 0 until 2 ) {
|
|
|
|
|
when( isTLWriteSoftReset(2+i) ){
|
|
|
|
|
isAxisEnd(i) := false.B
|
|
|
|
|
} .elsewhen( CDRIn(i).io.axis.fire & CDRIn(i).io.axis.bits.tlast ){
|
|
|
|
|
isAxisEnd(i) := true.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(2+i) ){
|
|
|
|
|
rxCnt(i) := 0.U
|
|
|
|
|
} .elsewhen( CDRIn(i).io.axis.fire ){
|
|
|
|
|
rxCnt(i) := rxCnt(i) + 1.U
|
|
|
|
|
rxData(i) := Cat( rxData(i), CDRIn(i).io.axis.bits.tdata )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(2+i) ){
|
|
|
|
|
rxLen(i) := 0.U
|
|
|
|
|
} .elsewhen( CDRIn(i).io.axis.fire ){
|
|
|
|
|
rxLen(i) := rxLen(i) + 1.U
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rxFifo(i).io.enq.valid := CDRIn(i).io.axis.fire & rxCnt(i) === 3.U
|
|
|
|
|
rxFifo(i).io.enq.bits := Cat( rxData(i)(23, 0) , CDRIn(i).io.axis.bits.tdata )
|
|
|
|
|
|
|
|
|
|
assert( ~(( CDRIn(i).io.axis.fire & CDRIn(i).io.axis.bits.tlast) & rxCnt(i) =/= 3.U), "Assert Failed! Rx must 4-byte Align!" )
|
|
|
|
|
|
|
|
|
|
CDRIn(i).io.axis.ready := true.B
|
|
|
|
|
|
|
|
|
|
rxFifo(i).reset := reset.asBool | isTLWriteSoftReset(2+i)
|
|
|
|
|
CDRIn(i).reset := reset.asBool | isTLWriteSoftReset(2+i)
|
|
|
|
|
|
|
|
|
|
rxFifo(i).io.deq.ready := isTLReadRxFifo(i)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(2+i) ){
|
|
|
|
|
isRxError(i) := false.B
|
|
|
|
|
} .elsewhen( rxFifo(i).io.enq.valid & ~rxFifo(i).io.enq.ready ){
|
|
|
|
|
isRxError(i) := true.B
|
|
|
|
|
printf(s"Warning, RxFifo$i Overflow!\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(2+i) ){
|
|
|
|
|
rxLeft(i) := 0.U
|
|
|
|
|
} .elsewhen( rxFifo(i).io.enq.fire & rxFifo(i).io.deq.fire ){
|
|
|
|
|
rxLeft(i) := rxLeft(i)
|
|
|
|
|
} .elsewhen( rxFifo(i).io.enq.fire ){
|
|
|
|
|
rxLeft(i) := rxLeft(i) + 1.U
|
|
|
|
|
} .elsewhen( rxFifo(i).io.deq.fire ){
|
|
|
|
|
rxLeft(i) := rxLeft(i) - 1.U
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait RoCC2CDRImplIsLast{ this: RoCC2CDRImplBase =>
|
|
|
|
|
cdrOutio.isOnline := false.B
|
|
|
|
|
val isReadIsLast = Wire(Bool())
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait RoCC2CDRImplUserCRC{ this: RoCC2CDRImplBase =>
|
|
|
|
|
val isTLWriteTxFifo: Seq[Bool]
|
|
|
|
|
val isTLReadRxFifo: Seq[Bool]
|
|
|
|
|
|
|
|
|
|
val isTLReadTxCrc = for( i <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
val isTLReadRxCrc = for( i <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val txCrc = for( i <- 0 until 2 ) yield { Module(new crc32_32) }
|
|
|
|
|
val rxCrc = for( i <- 0 until 2 ) yield { Module(new crc32_32) }
|
|
|
|
|
|
|
|
|
|
for( i <- 0 until 2 ) {
|
|
|
|
|
txCrc(i).io.enq.valid := isTLWriteTxFifo(i)
|
|
|
|
|
txCrc(i).io.enq.bits := wdata
|
|
|
|
|
|
|
|
|
|
rxCrc(i).io.enq.valid := isTLReadRxFifo(i)
|
|
|
|
|
rxCrc(i).io.enq.bits := rxFifo(i).io.deq.bits
|
|
|
|
|
|
|
|
|
|
txCrc(i).reset := reset.asBool | isTLWriteSoftReset(0+i)
|
|
|
|
|
rxCrc(i).reset := reset.asBool | isTLWriteSoftReset(2+i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait RoCC2CDRImplLimitTimmer{ this: RoCC2CDRImplBase =>
|
|
|
|
|
val intRxStart: Seq[Bool]
|
|
|
|
|
val isTLWriteSoftReset: Seq[Bool]
|
|
|
|
|
val isTxFifoRelease: Seq[Bool]
|
|
|
|
|
|
|
|
|
|
val isTLWriteLimitTimerAim = for( i <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
val isTLWriteLimitTxPair = for( i <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
|
|
|
|
|
val limitTimerCnt = for( i <- 0 until 2 ) yield { RegInit(0.U(16.W)) }
|
|
|
|
|
val limitTimerAim = for( i <- 0 until 2 ) yield { RegInit(0.U(16.W)) }
|
|
|
|
|
val isLimitTimerTrigger = for( i <- 0 until 2 ) yield { RegInit(false.B) }
|
|
|
|
|
val txPairSel = for( i <- 0 until 2 ) yield { RegInit((i.U)(2.W)) }
|
|
|
|
|
|
|
|
|
|
for( i <- 0 until 2 ){
|
|
|
|
|
when( isTLWriteSoftReset(0+i) | isTLWriteSoftReset(2+i) ){
|
|
|
|
|
limitTimerCnt(i) := 0.U
|
|
|
|
|
} .elsewhen( limitTimerCnt(i) =/= limitTimerAim(i) ){
|
|
|
|
|
when( isLimitTimerTrigger(i) ){
|
|
|
|
|
limitTimerCnt(i) := limitTimerCnt(i) + 1.U
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteLimitTimerAim(i) ){
|
|
|
|
|
limitTimerAim(i) := wdata
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(0+i) | isTLWriteSoftReset(2+i) ){
|
|
|
|
|
isLimitTimerTrigger(i) := false.B
|
|
|
|
|
} .elsewhen( intRxStart(i) ){
|
|
|
|
|
isLimitTimerTrigger(i) := true.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(0+i) | isTLWriteSoftReset(2+i) ){
|
|
|
|
|
txPairSel(i) := i.U
|
|
|
|
|
} .elsewhen( isTLWriteLimitTxPair(i) ){
|
|
|
|
|
txPairSel(i) := wdata
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isTxFifoRelease(i) := ( 0 until 2).map{ lmt =>
|
|
|
|
|
((txPairSel(lmt) =/= i.U) | (limitTimerCnt(lmt) === limitTimerAim(lmt)))
|
|
|
|
|
}.reduce(_&_)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-20 19:04:30 +08:00
|
|
|
trait RoCC2CDRImplOutTimmer{ this: RoCC2CDRImplBase =>
|
|
|
|
|
val isTxBusy: Seq[Bool]
|
2025-02-13 18:14:26 +08:00
|
|
|
|
2025-02-20 19:04:30 +08:00
|
|
|
val timeOutCnt = for( _ <- 0 until 2 ) yield { RegInit(0.U(32.W)) }
|
|
|
|
|
val isTLClearTimeOut = for( _ <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
val isTLReadTimeOut = for( _ <- 0 until 2 ) yield { Wire(Bool()) }
|
|
|
|
|
|
|
|
|
|
val isTxClearTimeOut = for( i <- 0 until 2 ) yield { ~RegNext(isTxBusy(i)) & isTxBusy(i) }
|
|
|
|
|
|
|
|
|
|
for( i <- 0 until 2 ) {
|
|
|
|
|
when( isTLClearTimeOut(i) | isTxClearTimeOut(i) ){
|
|
|
|
|
timeOutCnt(i) := 0.U
|
|
|
|
|
} .otherwise{
|
|
|
|
|
timeOutCnt(i) := timeOutCnt(i) + 1.U
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-02-13 18:14:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RoCC2CDRImpl(outer: RoCC2CDR)(implicit p: Parameters) extends RoCC2CDRImplBase(outer)
|
|
|
|
|
with RoCC2CDRImplTx with RoCC2CDRImplRx
|
|
|
|
|
with RoCC2CDRImplIsLast
|
|
|
|
|
with RoCC2CDRImplUserCRC
|
2025-02-20 19:04:30 +08:00
|
|
|
with RoCC2CDRImplLimitTimmer with RoCC2CDRImplOutTimmer
|
2025-02-13 18:14:26 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
io.mem.req.valid := false.B
|
|
|
|
|
io.mem.req.bits := DontCare
|
|
|
|
|
io.mem.s1_kill := false.B
|
|
|
|
|
io.mem.s1_data := DontCare
|
|
|
|
|
io.mem.s2_kill := false.B
|
|
|
|
|
io.mem.keep_clock_enabled := false.B
|
|
|
|
|
|
|
|
|
|
io.fpu_req.valid := false.B
|
|
|
|
|
io.fpu_req.bits := DontCare
|
|
|
|
|
io.fpu_resp.ready := true.B
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isTLWriteSoftReset(0) := io.cmd.fire & io.cmd.bits.inst.funct === 0.U
|
|
|
|
|
isTLWriteTxLen(0) := io.cmd.fire & io.cmd.bits.inst.funct === 1.U
|
|
|
|
|
isTLWriteTxFifo(0) := io.cmd.fire & io.cmd.bits.inst.funct === 2.U
|
|
|
|
|
isTLReadTxCrc(0) := io.cmd.fire & io.cmd.bits.inst.funct === 3.U
|
2025-02-20 19:04:30 +08:00
|
|
|
isTLClearTimeOut(0) := io.cmd.fire & io.cmd.bits.inst.funct === 4.U & io.cmd.bits.inst.xs1
|
|
|
|
|
isTLReadTimeOut(0) := io.cmd.fire & io.cmd.bits.inst.funct === 4.U & io.cmd.bits.inst.xd
|
|
|
|
|
|
|
|
|
|
isTLWriteSoftReset(1) := io.cmd.fire & io.cmd.bits.inst.funct === 5.U
|
|
|
|
|
isTLWriteTxLen(1) := io.cmd.fire & io.cmd.bits.inst.funct === 6.U
|
|
|
|
|
isTLWriteTxFifo(1) := io.cmd.fire & io.cmd.bits.inst.funct === 7.U
|
|
|
|
|
isTLReadTxCrc(1) := io.cmd.fire & io.cmd.bits.inst.funct === 8.U
|
|
|
|
|
isTLClearTimeOut(1) := io.cmd.fire & io.cmd.bits.inst.funct === 9.U & io.cmd.bits.inst.xs1
|
|
|
|
|
isTLReadTimeOut(1) := io.cmd.fire & io.cmd.bits.inst.funct === 9.U & io.cmd.bits.inst.xd
|
|
|
|
|
|
2025-03-04 12:01:47 +08:00
|
|
|
//0 rx0->tx0, 1 rx0->tx1, 2 rx1 -> tx0, 3 rx1 ->tx1
|
2025-02-20 19:04:30 +08:00
|
|
|
isTLWriteSoftReset(2) := io.cmd.fire & io.cmd.bits.inst.funct === 10.U
|
|
|
|
|
isTLReadRxLen(0) := io.cmd.fire & io.cmd.bits.inst.funct === 11.U
|
|
|
|
|
isTLReadRxFifo(0) := io.cmd.fire & io.cmd.bits.inst.funct === 12.U
|
2025-03-04 12:01:47 +08:00
|
|
|
isTLReadRxFifoBypassTx(0) := io.cmd.fire & io.cmd.bits.inst.funct === 13.U
|
|
|
|
|
isTLReadRxFifoBypassTx(1) := io.cmd.fire & io.cmd.bits.inst.funct === 14.U
|
|
|
|
|
isTLReadRxCrc(0) := io.cmd.fire & io.cmd.bits.inst.funct === 15.U
|
|
|
|
|
isTLWriteLimitTimerAim(0) := io.cmd.fire & io.cmd.bits.inst.funct === 16.U
|
|
|
|
|
isTLWriteLimitTxPair(0) := io.cmd.fire & io.cmd.bits.inst.funct === 17.U
|
2025-02-13 18:14:26 +08:00
|
|
|
|
2025-03-04 12:01:47 +08:00
|
|
|
isTLWriteSoftReset(3) := io.cmd.fire & io.cmd.bits.inst.funct === 18.U
|
|
|
|
|
isTLReadRxLen(1) := io.cmd.fire & io.cmd.bits.inst.funct === 19.U
|
|
|
|
|
isTLReadRxFifo(1) := io.cmd.fire & io.cmd.bits.inst.funct === 20.U
|
|
|
|
|
isTLReadRxFifoBypassTx(2) := io.cmd.fire & io.cmd.bits.inst.funct === 21.U
|
|
|
|
|
isTLReadRxFifoBypassTx(3) := io.cmd.fire & io.cmd.bits.inst.funct === 22.U
|
|
|
|
|
isTLReadRxCrc(1) := io.cmd.fire & io.cmd.bits.inst.funct === 23.U
|
|
|
|
|
isTLWriteLimitTimerAim(1) := io.cmd.fire & io.cmd.bits.inst.funct === 24.U
|
|
|
|
|
isTLWriteLimitTxPair(1) := io.cmd.fire & io.cmd.bits.inst.funct === 25.U
|
2025-02-13 18:14:26 +08:00
|
|
|
|
2025-03-04 12:01:47 +08:00
|
|
|
isTLReadStatus := io.cmd.fire & io.cmd.bits.inst.funct === 26.U
|
|
|
|
|
val isTLReadInterrupt = io.cmd.fire & io.cmd.bits.inst.funct === 27.U & io.cmd.bits.inst.xd
|
2025-03-04 14:45:31 +08:00
|
|
|
val isTLClearInterrupt = io.cmd.fire & io.cmd.bits.inst.funct === 27.U & io.cmd.bits.inst.xs1
|
|
|
|
|
val isTLWriteIntMask = io.cmd.fire & io.cmd.bits.inst.funct === 28.U
|
|
|
|
|
isReadIsLast := io.cmd.fire & io.cmd.bits.inst.funct === 29.U
|
2025-03-04 12:01:47 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val interruptReg = RegInit(0.U(32.W))
|
|
|
|
|
val interruptMask = RegEnable(wdata, 0.U(32.W), isTLWriteIntMask)
|
|
|
|
|
|
|
|
|
|
val statusRxStart = for( i <- 0 until 2 ) yield { RegInit(false.B) }
|
|
|
|
|
val statusRxEnd = for( i <- 0 until 2 ) yield { RegInit(false.B) }
|
|
|
|
|
val statusTxEnd = for( i <- 0 until 2 ) yield { RegInit(false.B) }
|
|
|
|
|
|
|
|
|
|
for( i <- 0 until 2 ){
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(2+i) ){
|
|
|
|
|
statusRxStart(i) := false.B
|
|
|
|
|
} .elsewhen( intRxStart(i) ){
|
|
|
|
|
statusRxStart(i) := true.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(2+i) ){
|
|
|
|
|
statusRxEnd(i) := false.B
|
|
|
|
|
} .elsewhen( intRxEnd(i) ){
|
|
|
|
|
statusRxEnd(i) := true.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( isTLWriteSoftReset(0+i) ){
|
|
|
|
|
statusTxEnd(i) := false.B
|
|
|
|
|
} .elsewhen( intTxEnd(i) ){
|
|
|
|
|
statusTxEnd(i) := true.B
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-20 19:04:30 +08:00
|
|
|
|
|
|
|
|
|
2025-02-27 17:27:15 +08:00
|
|
|
when(true.B){
|
2025-03-04 12:01:47 +08:00
|
|
|
interruptReg :=
|
|
|
|
|
(
|
|
|
|
|
(interruptReg & Mux( isTLClearInterrupt, ~wdata, "hFFFFFFFF".U)) | Cat(
|
|
|
|
|
intTxEnd(1), intTxEnd(0),
|
|
|
|
|
intRxError(1), intRxError(0),
|
|
|
|
|
intRxStart(1), intRxStart(0),
|
|
|
|
|
intRxEnd(1), intRxEnd(0),
|
|
|
|
|
intTxFifoDeq(1), intTxFifoDeq(0),
|
|
|
|
|
intRxFifoEnq(1), intRxFifoEnq(0)
|
|
|
|
|
)
|
|
|
|
|
) & interruptMask
|
2025-02-20 19:04:30 +08:00
|
|
|
}
|
2025-02-13 18:14:26 +08:00
|
|
|
|
|
|
|
|
|
2025-02-27 17:27:15 +08:00
|
|
|
|
|
|
|
|
|
2025-02-13 18:14:26 +08:00
|
|
|
io.interrupt :=
|
2025-03-04 12:01:47 +08:00
|
|
|
( intTxEnd(1) & interruptMask.extract(11) ) |
|
|
|
|
|
( intTxEnd(0) & interruptMask.extract(10) ) |
|
|
|
|
|
( intRxError(1) & interruptMask.extract( 9) ) |
|
|
|
|
|
( intRxError(0) & interruptMask.extract( 8) ) |
|
|
|
|
|
( intRxStart(1) & interruptMask.extract( 7) ) |
|
|
|
|
|
( intRxStart(0) & interruptMask.extract( 6) ) |
|
|
|
|
|
( intRxEnd(1) & interruptMask.extract( 5) ) |
|
|
|
|
|
( intRxEnd(0) & interruptMask.extract( 4) ) |
|
|
|
|
|
( intTxFifoDeq(1) & interruptMask.extract( 3) ) |
|
|
|
|
|
( intTxFifoDeq(0) & interruptMask.extract( 2) ) |
|
|
|
|
|
( intRxFifoEnq(1) & interruptMask.extract( 1) ) |
|
|
|
|
|
( intRxFifoEnq(0) & interruptMask.extract( 0) )
|
2025-02-13 18:14:26 +08:00
|
|
|
|
|
|
|
|
wdata := io.cmd.bits.rs1
|
|
|
|
|
|
|
|
|
|
val cmdInfo = RegEnable(io.cmd.bits, io.cmd.fire)
|
|
|
|
|
val rdata = Reg(UInt(32.W))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// val cmdReady = RegInit(true.B)
|
|
|
|
|
val respValid = RegInit(false.B)
|
|
|
|
|
|
|
|
|
|
io.busy := respValid
|
|
|
|
|
io.cmd.ready := ~respValid
|
|
|
|
|
|
|
|
|
|
io.resp.valid := respValid
|
|
|
|
|
io.resp.bits.rd := cmdInfo.inst.rd
|
|
|
|
|
|
|
|
|
|
io.resp.bits.data := rdata
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("Warning, no protection on tx rx fifo!\n")
|
|
|
|
|
// MuxCase( true.B, Array(
|
|
|
|
|
// ( io.cmd.bits.inst.funct === 2.U ) -> txFifo(0).io.enq.ready,
|
|
|
|
|
// ( io.cmd.bits.inst.funct === 6.U ) -> txFifo(1).io.enq.ready,
|
|
|
|
|
// ( bus.a.bits.address(7,0) === "h28".U ) -> rxFifo(0).io.deq.valid,
|
|
|
|
|
// ( bus.a.bits.address(7,0) === "h48".U ) -> rxFifo(1).io.deq.valid,
|
|
|
|
|
// ))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-03-04 12:01:47 +08:00
|
|
|
|
2025-02-13 18:14:26 +08:00
|
|
|
|
|
|
|
|
when( isTLReadStatus ){
|
2025-03-04 12:01:47 +08:00
|
|
|
rdata := Cat(
|
|
|
|
|
txLeft(1), txLeft(0), rxLeft(1), rxLeft(0),
|
|
|
|
|
isRxValid(1), isRxValid(0), isRxError(1), isRxError(0),
|
|
|
|
|
statusRxStart(1), statusRxStart(0), statusRxEnd(1), statusRxEnd(0), statusTxEnd(1), statusTxEnd(0)
|
|
|
|
|
)
|
|
|
|
|
} .elsewhen(isTLReadRxLen(0) ){
|
2025-02-13 18:14:26 +08:00
|
|
|
rdata := rxLen(0)
|
2025-03-04 12:01:47 +08:00
|
|
|
} .elsewhen(isTLReadRxLen(1) ){
|
2025-02-13 18:14:26 +08:00
|
|
|
rdata := rxLen(1)
|
2025-03-04 12:01:47 +08:00
|
|
|
} .elsewhen(isTLReadRxFifo(0) | isTLReadRxFifoBypassTx(0) | isTLReadRxFifoBypassTx(1) ){
|
2025-02-13 18:14:26 +08:00
|
|
|
rdata := rxFifo(0).io.deq.bits
|
2025-03-04 12:01:47 +08:00
|
|
|
} .elsewhen(isTLReadRxFifo(1) | isTLReadRxFifoBypassTx(2) | isTLReadRxFifoBypassTx(3) ){
|
2025-02-13 18:14:26 +08:00
|
|
|
rdata := rxFifo(1).io.deq.bits
|
|
|
|
|
} .elsewhen(isReadIsLast){
|
|
|
|
|
rdata := cdrInio.isLast
|
|
|
|
|
} .elsewhen(isTLReadTxCrc(0)){
|
|
|
|
|
rdata := txCrc(0).io.crc
|
|
|
|
|
} .elsewhen(isTLReadTxCrc(1)){
|
|
|
|
|
rdata := txCrc(1).io.crc
|
|
|
|
|
} .elsewhen(isTLReadRxCrc(0)){
|
|
|
|
|
rdata := rxCrc(0).io.crc
|
|
|
|
|
} .elsewhen(isTLReadRxCrc(1)){
|
|
|
|
|
rdata := rxCrc(1).io.crc
|
2025-02-20 19:04:30 +08:00
|
|
|
} .elsewhen(isTLReadInterrupt){
|
|
|
|
|
rdata := interruptReg
|
|
|
|
|
} .elsewhen(isTLReadTimeOut(0)){
|
|
|
|
|
rdata := timeOutCnt(0)
|
|
|
|
|
} .elsewhen(isTLReadTimeOut(1)){
|
|
|
|
|
rdata := timeOutCnt(1)
|
2025-02-13 18:14:26 +08:00
|
|
|
}
|
|
|
|
|
|
2025-02-20 19:04:30 +08:00
|
|
|
|
2025-02-13 18:14:26 +08:00
|
|
|
when( io.resp.fire ){ //允许连续触发
|
|
|
|
|
respValid := false.B
|
|
|
|
|
} .elsewhen( isTLReadStatus ){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadRxLen(0) ){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadRxLen(1) ){
|
|
|
|
|
respValid := true.B
|
2025-03-04 12:01:47 +08:00
|
|
|
} .elsewhen(isTLReadRxFifo(0) | isTLReadRxFifoBypassTx(0) | isTLReadRxFifoBypassTx(1) ){
|
2025-02-13 18:14:26 +08:00
|
|
|
respValid := true.B
|
2025-03-04 12:01:47 +08:00
|
|
|
} .elsewhen(isTLReadRxFifo(1) | isTLReadRxFifoBypassTx(2) | isTLReadRxFifoBypassTx(3) ){
|
2025-02-13 18:14:26 +08:00
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isReadIsLast){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadTxCrc(0)){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadTxCrc(1)){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadRxCrc(0)){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadRxCrc(1)){
|
|
|
|
|
respValid := true.B
|
2025-02-20 19:04:30 +08:00
|
|
|
} .elsewhen(isTLReadInterrupt){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadTimeOut(0)){
|
|
|
|
|
respValid := true.B
|
|
|
|
|
} .elsewhen(isTLReadTimeOut(1)){
|
|
|
|
|
respValid := true.B
|
2025-02-13 18:14:26 +08:00
|
|
|
}
|
2025-02-20 19:04:30 +08:00
|
|
|
|
2025-02-13 18:14:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trait HasLazyRoCC2CDR { this: BaseTile =>
|
|
|
|
|
val roccs = LazyModule(new RoCC2CDR())
|
|
|
|
|
|
|
|
|
|
val roccCSRs = Seq(roccs.roccCSRs) // the set of custom CSRs requested by all roccs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait HasLazyRoCC2CDRModule extends HasCoreParameters { this: RocketTileModuleImp with HasFpuOpt =>
|
|
|
|
|
|
|
|
|
|
// val (respArb, cmdRouter) = {
|
|
|
|
|
// val respArb = Module(new RRArbiter(new RoCCResponse()(outer.p), outer.roccs.size))
|
|
|
|
|
val cmdRouter = Module(new Queue( new RoCCCommand, 2, false, true ))//Module(new RoccCommandRouter( Seq(outer.roccs.opcodes) )(outer.p))
|
|
|
|
|
|
|
|
|
|
// outer.roccs.module.io.ptw ++=: ptwPorts
|
|
|
|
|
outer.roccs.module.io.cmd <> cmdRouter.io.deq
|
|
|
|
|
// val dcIF = Module(new SimpleHellaCacheIF()(outer.p))
|
|
|
|
|
// dcIF.io.requestor <> outer.roccs.module.io.mem
|
|
|
|
|
// dcachePorts += dcIF.io.cache
|
|
|
|
|
//respArb.io.in(0) <> Queue(outer.roccs.module.io.resp)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fpuOpt foreach { fpu =>
|
|
|
|
|
fpu.io.cp_req.valid := false.B
|
|
|
|
|
fpu.io.cp_resp.ready := false.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// (Some(respArb), Some(cmdRouter))
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// val roccCSRIOs = Seq(outer.roccs.module.io.csrs)
|
|
|
|
|
|
|
|
|
|
// (core.io.rocc.csrs zip roccCSRIOs.flatten).foreach { t => t._2 := t._1 }
|
|
|
|
|
|
|
|
|
|
val cdrInio = IO(Input(new RocCC2CDRInIO))
|
|
|
|
|
val cdrOutio = IO(Output(new RocCC2CDROutIO))
|
|
|
|
|
|
|
|
|
|
// val cdrio: RoCC2CDRIO = IO(new RoCC2CDRIO)
|
|
|
|
|
// dontTouch(cdrio)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cdrInio <> outer.roccs.module.cdrInio
|
|
|
|
|
cdrOutio <> outer.roccs.module.cdrOutio
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|