package BACK import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config._ import freechips.rocketchip.diplomacy._ import freechips.rocketchip.tilelink._ abstract class TLCDRBase(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 // CDRIn.io.axis = Decoupled(new AXIS_Bundle(8)) // CDROut.io.axis = Flipped(Decoupled(new AXIS_Bundle(8))) val txFifo = Module(new Queue(UInt(32.W), 4)) val rxFifo = Module(new Queue(UInt(32.W), 4)) } trait TLCDRTx{ this: TLCDRBase => 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 isTxError = RegInit(false.B) val intTxError = ~RegNext(isTxError, false.B) & isTxError 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 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 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 := isTxError CDROut.io.axis.valid := isTxBusy when( isTLWriteTxLen ){ 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.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 when( isTLWriteTxLen ){ isTxError := false.B } .elsewhen( isTxFull & isTLWriteTxFifo ){ isTxError := true.B } .elsewhen( txLen === 0.U & isTLWriteTxFifo ){ isTxError := true.B } } trait TLCDRRx{ this: TLCDRBase => 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) ) // 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 isRxBusy = RegInit(false.B) 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 intRxValid = ~RegNext(isRxValid, false.B) & isRxValid 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 ) // PriorityMux(Seq( // (rxCnt === 0.U) -> Cat( CDRIn.io.axis.bits.tdata, 0.U(16.W) /*,0.U(8.W)*/ ), // (rxCnt === 1.U) -> Cat( rxData(23,16), CDRIn.io.axis.bits.tdata, 0.U(8.W) /*,0.U(8.W)*/ ), // (rxCnt === 2.U) -> Cat( rxData(23, 8), CDRIn.io.axis.bits.tdata /*,0.U(8.W)*/ ), // // (rxCnt === 3.U) -> Cat( rxData(31,8) , 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 ) // PriorityMux(Seq( // (rxCnt === 0.U) -> Cat( CDRIn.io.axis.bits.tdata, 0.U(24.W) ), // (rxCnt === 1.U) -> Cat( rxData(23,16), CDRIn.io.axis.bits.tdata, 0.U(16.W) ), // (rxCnt === 2.U) -> Cat( rxData(23, 8), CDRIn.io.axis.bits.tdata, 0.U(8.W ) ), // (rxCnt === 3.U) -> 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 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 TLCDR(edge: TLEdgeIn)(implicit p: Parameters) extends TLCDRBase(edge) with TLCDRTx with TLCDRRx{ 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.tla.bits.data } 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) := intTxError io.interrupt(1) := intRxError io.interrupt(2) := intRxStart io.interrupt(3) := intRxEnd 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 } }