package BACK import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ abstract class BackModule(implicit val p: Parameters) extends Module with HasBackParameters { def io: Record } abstract class BackBundle(implicit val p: Parameters) extends Bundle with HasBackParameters case object BackParamsKey extends Field[BackSetting] case class BackSetting( ){ } trait HasBackParameters { implicit val p: Parameters val backSetting = p(BackParamsKey) } class BackCfg extends Config((_, _, _) => { case BackParamsKey => BackSetting() }) abstract class TL2CDRBase(val edge: TLEdgeIn)(implicit p: Parameters) extends BackModule { class TLCDRIO extends Bundle{ val overCLK = Input(Bool()) val dDatIn = Input(Bool()) val dDatOut = Output(Bool()) val uDatIn = Input(Bool()) val uDatOut = Output(Bool()) val tla = Flipped(new DecoupledIO(new TLBundleA(edge.bundle))) val tld = new DecoupledIO(new TLBundleD(edge.bundle)) val interrupt = Output(Vec(8, Bool())) val isOnline = Output(Bool()) val isLast = Input(Bool()) } val io: TLCDRIO = IO(new TLCDRIO) val CDRIn = for( i <- 0 until 2 ) yield { Module(new CDRIn) } CDRIn(0).io.serDat := io.dDatIn CDRIn(1).io.serDat := io.uDatIn CDRIn(0).io.overCLK := io.overCLK CDRIn(1).io.overCLK := io.overCLK val CDROut = for( i <- 0 until 2 ) yield { Module(new CDROut) } io.dDatOut := CDROut(0).io.serDat io.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()) } //io.tla.fire & io.tla.bits.address(5,0) === "h10".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) val isTLReadStatus = Wire( Bool() ) //io.tla.fire & io.tla.bits.address(5,0) === "h0".U & ( io.tla.bits.opcode === 4.U ) } trait TL2CDRTx{ this: TL2CDRBase => val isTLWriteTxLen = for( i <- 0 until 2 ) yield { Wire( Bool()) }//io.tla.fire & io.tla.bits.address(5,0) === "h4".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) val isTLWriteTxFifo = for( i <- 0 until 2 ) yield { Wire( Bool()) }//io.tla.fire & io.tla.bits.address(5,0) === "h8".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) 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 = ShiftRegister( CDROut.io.axis.fire & CDROut.io.axis.bits.tlast, 5, false.B, true.B) // println("Warning, TxEnd no confident\n") 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) := io.tla.bits.data } .elsewhen( CDROut(i).io.axis.fire ){ txLen(i) := txLen(i) - 1.U } txFifo(i).io.enq.bits := io.tla.bits.data txFifo(i).io.enq.valid := isTLWriteTxFifo(i) & txLen(i) =/= 0.U } } trait TL2CDRRx{ this: TL2CDRBase => val isTLReadRxLen = for( i <- 0 until 2 ) yield { Wire(Bool()) }//io.tla.fire & io.tla.bits.address(5,0) === "h18".U & ( io.tla.bits.opcode === 4.U ) val isTLReadRxFifo = for( i <- 0 until 2 ) yield { Wire(Bool()) }//io.tla.fire & io.tla.bits.address(5,0) === "h1c".U & ( io.tla.bits.opcode === 4.U ) val rxLen = for( i <- 0 until 2 ) yield { RegInit(0.U(12.W)) } val isRxValid = for( i <- 0 until 2 ) yield { rxFifo(i).io.enq.fire } 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 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") } } } trait TL2CDRIsLast{ this: TL2CDRBase => io.isOnline := false.B val isReadIsLast = Wire(Bool())//io.tla.fire & io.tla.bits.address(5,0) === "h20".U & io.tla.bits.opcode === 4.U } trait TL2CDRUserCRC{ this: TL2CDRBase => val isTLWriteTxFifo: Seq[Bool] val isTLReadRxFifo: Seq[Bool] val isTLReadTxCrc = for( i <- 0 until 2 ) yield { Wire(Bool()) } //io.tla.fire & io.tla.bits.address(5,0) === "h24".U & io.tla.bits.opcode === 4.U val isTLReadRxCrc = for( i <- 0 until 2 ) yield { Wire(Bool()) } //io.tla.fire & io.tla.bits.address(5,0) === "h28".U & io.tla.bits.opcode === 4.U 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 := io.tla.bits.data 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 TL2CDRLimitTimmer{ this: TL2CDRBase => val intRxStart: Seq[Bool] val isTLWriteSoftReset: Seq[Bool] val isTxFifoRelease: Seq[Bool] val isTLWriteLimitTimerAim = for( i <- 0 until 2 ) yield { Wire(Bool()) } //io.tla.fire & io.tla.bits.address(5,0) === "h2c".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) 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) := io.tla.bits.data } 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) := io.tla.bits.data } isTxFifoRelease(i) := ( 0 until 2).map{ lmt => ((txPairSel(lmt) =/= i.U) | (limitTimerCnt(lmt) === limitTimerAim(lmt))) }.reduce(_&_) } } class TL2CDR(edge: TLEdgeIn)(implicit p: Parameters) extends TL2CDRBase(edge) with TL2CDRTx with TL2CDRRx with TL2CDRIsLast with TL2CDRUserCRC with TL2CDRLimitTimmer { isTLWriteSoftReset(0) := io.tla.fire & io.tla.bits.address(5,0) === "h00".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLWriteTxLen(0) := io.tla.fire & io.tla.bits.address(5,0) === "h04".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLWriteTxFifo(0) := io.tla.fire & io.tla.bits.address(5,0) === "h08".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLReadTxCrc(0) := io.tla.fire & io.tla.bits.address(5,0) === "h0c".U & io.tla.bits.opcode === 4.U isTLWriteSoftReset(1) := io.tla.fire & io.tla.bits.address(5,0) === "h10".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLWriteTxLen(1) := io.tla.fire & io.tla.bits.address(5,0) === "h14".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLWriteTxFifo(1) := io.tla.fire & io.tla.bits.address(5,0) === "h18".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLReadTxCrc(1) := io.tla.fire & io.tla.bits.address(5,0) === "h1c".U & io.tla.bits.opcode === 4.U isTLWriteSoftReset(2) := io.tla.fire & io.tla.bits.address(5,0) === "h20".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLReadRxLen(0) := io.tla.fire & io.tla.bits.address(5,0) === "h24".U & ( io.tla.bits.opcode === 4.U ) isTLReadRxFifo(0) := io.tla.fire & io.tla.bits.address(5,0) === "h28".U & ( io.tla.bits.opcode === 4.U ) isTLReadRxCrc(0) := io.tla.fire & io.tla.bits.address(5,0) === "h2c".U & io.tla.bits.opcode === 4.U isTLWriteLimitTimerAim(0) := io.tla.fire & io.tla.bits.address(5,0) === "h30".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLWriteLimitTxPair(0) := io.tla.fire & io.tla.bits.address(5,0) === "h34".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLWriteSoftReset(3) := io.tla.fire & io.tla.bits.address(5,0) === "h40".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLReadRxLen(1) := io.tla.fire & io.tla.bits.address(5,0) === "h44".U & ( io.tla.bits.opcode === 4.U ) isTLReadRxFifo(1) := io.tla.fire & io.tla.bits.address(5,0) === "h48".U & ( io.tla.bits.opcode === 4.U ) isTLReadRxCrc(1) := io.tla.fire & io.tla.bits.address(5,0) === "h4c".U & io.tla.bits.opcode === 4.U isTLWriteLimitTimerAim(1) := io.tla.fire & io.tla.bits.address(5,0) === "h50".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLWriteLimitTxPair(1) := io.tla.fire & io.tla.bits.address(5,0) === "h54".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) isTLReadStatus := io.tla.fire & io.tla.bits.address(5,0) === "h58".U & ( io.tla.bits.opcode === 4.U ) isReadIsLast := io.tla.fire & io.tla.bits.address(5,0) === "h5c".U & ( io.tla.bits.opcode === 4.U ) io.interrupt(0) := intTxFinish(0) io.interrupt(1) := intTxFinish(1) io.interrupt(2) := intRxError(0) io.interrupt(3) := intRxError(1) io.interrupt(4) := intRxStart(0) io.interrupt(5) := intRxStart(1) io.interrupt(6) := intRxEnd(0) io.interrupt(7) := intRxEnd(1) val tlaInfo = Reg(new TLBundleA(edge.bundle)) val rdata = Reg(UInt(32.W)) val tlAReady = RegInit(true.B) val tlDValid = RegInit(false.B) val isRead = tlaInfo.opcode === 4.U io.tla.ready := tlAReady & MuxCase( true.B, Array( ( io.tla.bits.address(5,0) === "h08".U ) -> txFifo(0).io.enq.ready, ( io.tla.bits.address(5,0) === "h18".U ) -> txFifo(1).io.enq.ready, ( io.tla.bits.address(7,0) === "h28".U ) -> rxFifo(0).io.deq.valid, ( io.tla.bits.address(7,0) === "h48".U ) -> rxFifo(1).io.deq.valid, )) io.tld.valid := tlDValid when( io.tla.fire ) { tlaInfo := io.tla.bits } when( io.tla.fire ){ tlAReady := false.B tlDValid := true.B } .elsewhen( io.tld.fire ) { tlAReady := true.B tlDValid := false.B } when(isRead) { io.tld.bits := edge.AccessAck(tlaInfo, rdata) } .otherwise { io.tld.bits := edge.AccessAck(tlaInfo) } when( isTLReadStatus ){ rdata := Cat( isRxValid(1), isRxValid(0), isRxError(1), isRxError(0), isTxBusy(1), isTxBusy(0), isTxFull(1), isTxFull(0) ) } .elsewhen(isTLReadRxLen(0) ){ rdata := rxLen(0) } .elsewhen(isTLReadRxLen(1) ){ rdata := rxLen(1) } .elsewhen(isTLReadRxFifo(0) ){ rdata := rxFifo(0).io.deq.bits } .elsewhen(isTLReadRxFifo(1) ){ rdata := rxFifo(1).io.deq.bits } .elsewhen(isReadIsLast){ rdata := io.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 } }