From 1ea6ef2596e23cdf6698efe13e4c622772b0e72a Mon Sep 17 00:00:00 2001 From: RuigeLee Date: Thu, 9 Jan 2025 17:39:06 +0800 Subject: [PATCH] TL2CDR --- src/main/scala/backBoard/ebus/TL2CDR.scala | 268 +++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 src/main/scala/backBoard/ebus/TL2CDR.scala diff --git a/src/main/scala/backBoard/ebus/TL2CDR.scala b/src/main/scala/backBoard/ebus/TL2CDR.scala new file mode 100644 index 0000000..176a974 --- /dev/null +++ b/src/main/scala/backBoard/ebus/TL2CDR.scala @@ -0,0 +1,268 @@ +package BACK + +import chisel3._ +import chisel3.util._ + +import org.chipsalliance.cde.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ + + +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 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 + } .elsewhen( CDROut.io.axis.fire ){ + txLen := txLen - 1.U + } + + txFifo.io.enq.bits := io.mem.wdata + 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") + } + + + +} + +class TL2CDR()(implicit p: Parameters) extends TL2CDRBase() with TL2CDRTx with TL2CDRRx{ + + // 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, isTxError ) + } .elsewhen(isTLReadRxLen ){ + rdata := rxLen + } .elsewhen(isTLReadRxFifo ){ + rdata := rxFifo.io.deq.bits + } + + +} + +