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(4, Bool())) val isOnline = Output(Bool()) val isLast = Input(Bool()) } val io: TLCDRIO = IO(new TLCDRIO) val dirSel = RegInit(false.B) val CDRIn = Module(new CDRIn) CDRIn.io.serDat := Mux( ~dirSel, io.dDatIn, io.uDatIn ) CDRIn.io.overCLK := io.overCLK val CDROut = Module(new CDROut) io.dDatOut := ~dirSel & CDROut.io.serDat io.uDatOut := dirSel & CDROut.io.serDat val txFifo = Module(new Queue(UInt(32.W), 16)) val rxFifo = Module(new Queue(UInt(32.W), 16)) // val isTLWriteSoftReset = io.mem.fire & io.mem.addr(4,0) === "h10".U & ( (io.mem.wstrb =/= 0.U) ) val isTLWriteSoftReset = io.tla.fire & io.tla.bits.address(4,0) === "h10".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) } trait TL2CDRTx{ this: TL2CDRBase => // val isTLReadStatus = io.mem.fire & io.mem.addr(4,0) === "h0".U & ( io.mem.wstrb === 0.U ) // val isTLWriteTxLen = io.mem.fire & io.mem.addr(4,0) === "h4".U & ( io.mem.wstrb =/= 0.U ) // val isTLWriteTxFifo = io.mem.fire & io.mem.addr(4,0) === "h8".U & ( io.mem.wstrb =/= 0.U ) val isTLReadStatus = io.tla.fire & io.tla.bits.address(4,0) === "h0".U & ( io.tla.bits.opcode === 4.U ) val isTLWriteTxLen = io.tla.fire & io.tla.bits.address(4,0) === "h4".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) val isTLWriteTxFifo = io.tla.fire & io.tla.bits.address(4,0) === "h8".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) val txLen = RegInit(0.U(12.W)) val isTxBusy = RegInit(false.B) val isTxFull = ~txFifo.io.enq.ready val intTxEnd = ShiftRegister( CDROut.io.axis.fire & CDROut.io.axis.bits.tlast, 5, false.B, true.B) println("Warning, TxEnd no confident\n") val intTxFifoFull = ~RegNext(isTxFull, false.B) & isTxFull val intTxFinish = CDROut.io.axis.fire & CDROut.io.axis.bits.tlast val txCnt = Reg(UInt(2.W)) val txData = Reg(UInt(32.W)) when( txFifo.io.deq.fire ){ //txCnt === 3.U txData := txFifo.io.deq.bits when( isTxBusy ){ assert(CDROut.io.axis.fire) } } .elsewhen( CDROut.io.axis.fire ){ txData := txData << 8 } txFifo.io.deq.ready := Mux( isTxBusy, CDROut.io.axis.fire & txCnt === 3.U, true.B ) txFifo.reset := reset.asBool | isTLWriteTxLen | isTLWriteSoftReset CDROut.reset := reset.asBool | isTLWriteTxLen | isTLWriteSoftReset CDROut.io.axis.bits.tdata := txData.head(8) // PriorityMux(Seq( // (txCnt === 0.U) -> txData(31, 24), // (txCnt === 1.U) -> txData(23, 16), // (txCnt === 2.U) -> txData(15, 8), // (txCnt === 3.U) -> txData( 7, 0), // )) CDROut.io.axis.bits.tlast := ~txFifo.io.deq.valid & txCnt === 3.U CDROut.io.axis.bits.tuser := false.B CDROut.io.axis.valid := isTxBusy when( isTLWriteTxLen | isTLWriteSoftReset ){ isTxBusy := false.B }.elsewhen( txFifo.io.deq.fire & ~isTxBusy ){ isTxBusy := true.B } .elsewhen( CDROut.io.axis.fire & CDROut.io.axis.bits.tlast ){ isTxBusy := false.B } when( isTLWriteTxLen ){ txCnt := 0.U } .elsewhen( CDROut.io.axis.fire ){ txCnt := txCnt + 1.U } when( isTLWriteTxLen ){ // txLen := io.mem.wdata txLen := io.tla.bits.data } .elsewhen( CDROut.io.axis.fire ){ txLen := txLen - 1.U } txFifo.io.enq.bits := io.tla.bits.data txFifo.io.enq.valid := isTLWriteTxFifo & txLen =/= 0.U } trait TL2CDRRx{ this: TL2CDRBase => // val isTLReadRxStatus = io.mem.fire & io.mem.addr(4,0) === "h14".U & ( io.mem.wstrb === 0.U ) // val isTLReadRxLen = io.mem.fire & io.mem.addr(4,0) === "h18".U & ( io.mem.wstrb === 0.U ) // val isTLReadRxFifo = io.mem.fire & io.mem.addr(4,0) === "h1c".U & ( io.mem.wstrb === 0.U ) // val isTLReadRxStatus = io.tla.fire & io.tla.bits.address(4,0) === "h14".U & ( io.tla.bits.opcode === 4.U ) val isTLReadRxLen = io.tla.fire & io.tla.bits.address(4,0) === "h18".U & ( io.tla.bits.opcode === 4.U ) val isTLReadRxFifo = io.tla.fire & io.tla.bits.address(4,0) === "h1c".U & ( io.tla.bits.opcode === 4.U ) val rxLen = RegInit(0.U(12.W)) val isRxValid = rxFifo.io.enq.fire val isRxError = RegInit(false.B) val isAxisEnd = RegInit(false.B) val isRxEnd = isAxisEnd & ~rxFifo.io.deq.valid val intRxError = ~RegNext(isRxError, false.B) & isRxError val intRxStart = rxLen === 0.U & CDRIn.io.axis.fire val intRxEnd = ~RegNext(isRxEnd, false.B) & isRxEnd val rxCnt = RegInit(0.U(2.W)) val rxData = Reg(UInt(24.W)) when( isTLWriteSoftReset ){ isAxisEnd := false.B } .elsewhen( CDRIn.io.axis.fire & CDRIn.io.axis.bits.tlast ){ isAxisEnd := true.B } when( isTLWriteSoftReset ){ rxCnt := 0.U } .elsewhen( CDRIn.io.axis.fire ){ rxCnt := rxCnt + 1.U rxData := Cat( rxData, CDRIn.io.axis.bits.tdata ) } when( isTLWriteSoftReset ){ rxLen := 0.U } .elsewhen( CDRIn.io.axis.fire ){ rxLen := rxLen + 1.U } rxFifo.io.enq.valid := CDRIn.io.axis.fire & rxCnt === 3.U rxFifo.io.enq.bits := Cat( rxData(23, 0) , CDRIn.io.axis.bits.tdata ) assert( ~(( CDRIn.io.axis.fire & CDRIn.io.axis.bits.tlast) & rxCnt =/= 3.U), "Assert Failed! Rx must 4-byte Align!" ) CDRIn.io.axis.ready := true.B rxFifo.reset := reset.asBool | isTLWriteSoftReset CDRIn.reset := reset.asBool | isTLWriteSoftReset rxFifo.io.deq.ready := isTLReadRxFifo when( isTLWriteSoftReset ){ isRxError := false.B } .elsewhen( rxFifo.io.enq.valid & ~rxFifo.io.enq.ready ){ isRxError := true.B printf("Warning, RxFifo Overflow!\n") } } trait TL2CDRIsLast{ this: TL2CDRBase => io.isOnline := false.B val isReadIsLast = io.tla.fire & io.tla.bits.address(5,0) === "h20".U & io.tla.bits.opcode === 4.U } class TL2CDR(edge: TLEdgeIn)(implicit p: Parameters) extends TL2CDRBase(edge) with TL2CDRTx with TL2CDRRx with TL2CDRIsLast { // val isWriteTransDir = io.mem.fire & io.mem.addr(4,0) === "hc".U & io.mem.wstrb =/= 0.U val isWriteTransDir = io.tla.fire & io.tla.bits.address(4,0) === "hc".U & ( (io.tla.bits.opcode === 0.U) || (io.tla.bits.opcode === 1.U) ) 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 when( isWriteTransDir ){ // dirSel := io.mem.wdata dirSel := io.tla.bits.data } // io.mem.ready := // ( io.mem.wstrb =/= 0.U & txFifo.io.enq.ready) | // ( io.mem.wstrb === 0.U & Mux( io.mem.addr(4,0) === "h1c".U, rxFifo.io.deq.valid, true.B ) ) io.tla.ready := tlAReady & txFifo.io.enq.ready & ( Mux(io.tla.bits.address(4,0) === "h1c".U & ( io.tla.bits.opcode === 4.U ), rxFifo.io.deq.valid, true.B) ) io.tld.valid := tlDValid io.interrupt(0) := intTxEnd io.interrupt(1) := intRxError io.interrupt(2) := intRxStart io.interrupt(3) := intRxEnd // io.mem.rdata := // Mux1H(Seq( // isTLReadStatus -> Cat( isRxValid, isRxError, isTxBusy, isTxFull, false.B), // isTLReadRxLen -> rxLen, // isTLReadRxFifo -> rxFifo.io.deq.bits // )) 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, isRxError, isTxBusy, isTxFull, false.B ) } .elsewhen(isTLReadRxLen ){ rdata := rxLen } .elsewhen(isTLReadRxFifo ){ rdata := rxFifo.io.deq.bits } .elsewhen(isReadIsLast){ rdata := io.isLast } }