587 lines
21 KiB
Plaintext
587 lines
21 KiB
Plaintext
package BACK
|
||
|
||
import chisel3._
|
||
import chisel3.util._
|
||
|
||
class ShinSlvIO_Bundle extends Bundle{
|
||
|
||
val isOnline = Output(Bool())
|
||
val isLast = Input(Bool())
|
||
val DCIn = Input(Bool())
|
||
|
||
val downSer = new Bundle{
|
||
val out = Output(Bool())
|
||
val in = Input(Bool())
|
||
}
|
||
val upSer = new Bundle{
|
||
val out = Output(Bool())
|
||
val in = Input(Bool())
|
||
}
|
||
|
||
val overCLK = Input(Bool())
|
||
|
||
}
|
||
|
||
abstract class ShinSlvPhyBase extends Module{
|
||
val io: ShinSlvIO_Bundle = IO(new ShinSlvIO_Bundle)
|
||
|
||
val downStreamCdrOut = Module(new CDROut with chisel3.util.experimental.InlineInstance)
|
||
val downStreamCdrIn = Module(new CDRIn with chisel3.util.experimental.InlineInstance)
|
||
|
||
val upStreamCdrOut = Module(new CDROut with chisel3.util.experimental.InlineInstance)
|
||
val upStreamCdrIn = Module(new CDRIn with chisel3.util.experimental.InlineInstance)
|
||
|
||
io.downSer.out := downStreamCdrOut.io.serDat
|
||
downStreamCdrIn.io.serDat := io.downSer.in
|
||
downStreamCdrIn.io.overCLK := io.overCLK
|
||
|
||
io.upSer.out := upStreamCdrOut.io.serDat
|
||
upStreamCdrIn.io.serDat := io.upSer.in
|
||
upStreamCdrIn.io.overCLK := io.overCLK
|
||
|
||
io.isOnline := true.B
|
||
|
||
|
||
val downRegTemp = Reg(Vec( 32, UInt(8.W) ))
|
||
val upReg = WireDefault(VecInit((0 until 32).map{i => 0.U(8.W)}))
|
||
|
||
val headByte = (new Header_Info_Bundle).getWidth/8
|
||
require( headByte == 8 )
|
||
require( headByte > 4, "At Least 4 more additional cycles to ensure CRC Failure boardcast to next nodes!\n")
|
||
|
||
val OpInitByte = 8
|
||
val OpBoardCastByte = 16
|
||
val OpUniCastByte = 32
|
||
|
||
val maxLocalByte = OpInitByte max OpBoardCastByte max OpUniCastByte
|
||
|
||
val downForwardFifo = Module( new Queue( new AXIS_Bundle(8), 8 + headByte + 4 ) with chisel3.util.experimental.InlineInstance)
|
||
val upForwardFifo = Module( new Queue( new AXIS_Bundle(8), headByte + maxLocalByte + 4 ) with chisel3.util.experimental.InlineInstance) //4 is reserve
|
||
|
||
val isLastDevice = Wire(Bool())
|
||
|
||
}
|
||
|
||
trait ShinSlvPhyDownStreamRecv{ this: ShinSlvPhyBase =>
|
||
|
||
val DownRecvStateIdle = 0.U
|
||
val DownRecvStateOHead = 1.U
|
||
val DownRecvStateSData = 2.U
|
||
val DownRecvStateFData = 3.U
|
||
val DownRecvStateCRC = 4.U
|
||
|
||
|
||
val downOldHead = Reg( new Header_Info_Bundle )
|
||
val downNewHead = Reg( new Header_Info_Bundle )
|
||
val downNewHeadShift = Reg( new Header_Info_Bundle )
|
||
|
||
val downPendBuf= Module( new Queue( new AXIS_Bundle(8), 2, pipe = true, flow = false ) with chisel3.util.experimental.InlineInstance)
|
||
downStreamCdrIn.io.axis <> downPendBuf.io.enq
|
||
|
||
val downRecvStateNext = Wire( UInt(3.W) )
|
||
val downRecvStateCurr = RegNext( downRecvStateNext, 0.U )
|
||
|
||
val downRecvCnt = Reg(UInt(10.W))
|
||
|
||
|
||
val downLocalDataByte = RegEnable(
|
||
Mux1H(Seq(
|
||
( downOldHead.asUInt(3,0) === 0.U) -> OpInitByte.U, ( downOldHead.asUInt(3,0) === 1.U) -> OpBoardCastByte.U, ( downOldHead.asUInt(3,0) === 2.U) -> OpUniCastByte.U,
|
||
)), downRecvStateCurr === DownRecvStateOHead & downPendBuf.io.deq.fire & downRecvCnt === 3.U) //Timing Opt
|
||
|
||
val isDownStreamError = RegInit( false.B )
|
||
|
||
val downForwardDataByte = downNewHead.length
|
||
|
||
val isLastDevice: Bool
|
||
|
||
downRecvStateNext := Mux1H(Seq(
|
||
(downRecvStateCurr === DownRecvStateIdle ) -> Mux( downPendBuf.io.deq.valid, DownRecvStateOHead, DownRecvStateIdle ),
|
||
(downRecvStateCurr === DownRecvStateOHead) -> Mux( downPendBuf.io.deq.fire, Mux( ~downPendBuf.io.deq.bits.tlast, Mux(downRecvCnt === ((headByte)).U, DownRecvStateSData, DownRecvStateOHead), DownRecvStateIdle ), DownRecvStateOHead),
|
||
(downRecvStateCurr === DownRecvStateSData) -> Mux( downPendBuf.io.deq.fire, Mux( ~downPendBuf.io.deq.bits.tlast, Mux(downRecvCnt === (downLocalDataByte ), Mux( downRecvCnt === (downOldHead.length - 1.U), DownRecvStateCRC, DownRecvStateFData ), DownRecvStateSData), DownRecvStateIdle ), DownRecvStateSData),
|
||
(downRecvStateCurr === DownRecvStateFData) -> Mux( downPendBuf.io.deq.fire, Mux( ~downPendBuf.io.deq.bits.tlast, Mux(downRecvCnt === (downForwardDataByte ) , DownRecvStateCRC, DownRecvStateFData), DownRecvStateIdle ), DownRecvStateFData),
|
||
(downRecvStateCurr === DownRecvStateCRC ) -> Mux( downPendBuf.io.deq.fire & downPendBuf.io.deq.bits.tlast, DownRecvStateIdle, DownRecvStateCRC ),
|
||
))
|
||
|
||
when( downRecvStateCurr =/= downRecvStateNext ){
|
||
downRecvCnt := 1.U
|
||
} .elsewhen( downPendBuf.io.deq.fire ){
|
||
downRecvCnt := downRecvCnt + 1.U
|
||
}
|
||
|
||
//---------------
|
||
|
||
when( downRecvStateCurr === DownRecvStateOHead & downPendBuf.io.deq.fire ){
|
||
downOldHead := Cat( downOldHead.asUInt.tail(8), downPendBuf.io.deq.bits.tdata ).asTypeOf(new Header_Info_Bundle)
|
||
}
|
||
|
||
|
||
//---------------
|
||
val isDownNewHeadCreated = downRecvStateCurr === DownRecvStateSData & downRecvStateNext === DownRecvStateFData //新头是由老头产生,担忧会欠拍
|
||
when( isDownNewHeadCreated ){
|
||
downNewHead.length := Mux( downOldHead.length >= downLocalDataByte, downOldHead.length - downLocalDataByte, 0.U )
|
||
downNewHead.operator := downOldHead.operator
|
||
downNewHead.param := downOldHead.param
|
||
}
|
||
|
||
|
||
when( downRecvStateCurr === DownRecvStateSData & downPendBuf.io.deq.fire ){
|
||
downRegTemp(downRecvCnt-1.U) := downPendBuf.io.deq.bits.tdata
|
||
}
|
||
|
||
//---------------
|
||
downForwardFifo.io.enq.valid :=
|
||
downRecvStateCurr === DownRecvStateFData & downPendBuf.io.deq.fire & ~isLastDevice
|
||
downForwardFifo.io.enq.bits.tdata := downPendBuf.io.deq.bits.tdata
|
||
downForwardFifo.io.enq.bits.tuser := downPendBuf.io.deq.bits.tuser
|
||
downForwardFifo.io.enq.bits.tlast := downRecvCnt === (downForwardDataByte) | downPendBuf.io.deq.bits.tlast
|
||
|
||
downPendBuf.io.deq.ready :=
|
||
(downRecvStateCurr === DownRecvStateOHead) |
|
||
(downRecvStateCurr === DownRecvStateSData) |
|
||
(downRecvStateCurr === DownRecvStateFData) |
|
||
(downRecvStateCurr === DownRecvStateCRC )
|
||
|
||
when( downRecvStateCurr === DownRecvStateIdle & downRecvStateNext === DownRecvStateOHead){
|
||
isDownStreamError := false.B
|
||
} .elsewhen( downForwardFifo.io.enq.fire & downForwardFifo.io.enq.bits.tuser ){
|
||
isDownStreamError := true.B
|
||
printf("Warning, Wrong Package Received in DownStream, That could not happened!\n")
|
||
} .elsewhen( downRecvStateCurr === DownRecvStateOHead & downRecvStateNext === DownRecvStateIdle ){
|
||
isDownStreamError := true.B
|
||
printf("Warning, Wrong Package Received in DownStream, That could not happened!\n")
|
||
} .elsewhen( downRecvStateCurr === DownRecvStateSData & downRecvStateNext === DownRecvStateIdle ){
|
||
isDownStreamError := true.B
|
||
printf("Warning, Wrong Package Received in DownStream, That could not happened!\n")
|
||
} .elsewhen( downRecvStateCurr === DownRecvStateFData & downRecvStateNext === DownRecvStateIdle ){
|
||
isDownStreamError := true.B
|
||
printf("Warning, Wrong Package Received in DownStream, That could not happened!\n")
|
||
} .elsewhen( downRecvStateCurr === DownRecvStateCRC & downPendBuf.io.deq.fire & downPendBuf.io.deq.bits.tlast & downRecvCnt =/= 4.U ){
|
||
isDownStreamError := true.B
|
||
printf("Warning, Wrong Package Received in DownStream, That could not happened!\n")
|
||
} .elsewhen( isDownNewHeadCreated & downOldHead.length < downLocalDataByte ){ //本包的负载不能满足本级数据需求,传输错误
|
||
isDownStreamError := true.B
|
||
printf("Warning, Wrong Package Received in DownStream, That could not happened!\n")
|
||
} .elsewhen( isDownNewHeadCreated & isLastDevice & downOldHead.length =/= downLocalDataByte ){
|
||
printf("Warning, Wrong Package Received in DownStream, SoftWare Check!\n")
|
||
}
|
||
|
||
|
||
|
||
assert( ~(downRecvStateCurr === DownRecvStateFData & ~downForwardFifo.io.enq.ready), "Assert Failed, downStream Forward Fifo is OverFlow!" )
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
trait ShinSlvPhyDownStreamSend{ this: ShinSlvPhyBase =>
|
||
val DownSendStateIdle = 0.U
|
||
val DownSendStateNHead = 1.U
|
||
val DownSendStateFData = 2.U
|
||
|
||
val downSendCnt = Reg(UInt(10.W))
|
||
|
||
val isDownNewHeadCreated: Bool
|
||
val isLastDevice: Bool
|
||
val downForwardDataByte: UInt
|
||
val downNewHead: Header_Info_Bundle
|
||
val downNewHeadShift: Header_Info_Bundle
|
||
val isDownStreamError: Bool
|
||
|
||
|
||
val downSendStateNext = Wire( UInt(3.W) )
|
||
val downSendStateCurr = RegNext( downSendStateNext, 0.U )
|
||
|
||
downSendStateNext := Mux1H(Seq(
|
||
( downSendStateCurr === DownSendStateIdle ) -> Mux( isDownNewHeadCreated & ~isLastDevice, DownSendStateNHead, DownSendStateIdle ),
|
||
( downSendStateCurr === DownSendStateNHead ) -> Mux( downSendCnt === ((headByte)).U & downStreamCdrOut.io.axis.fire, DownSendStateFData, DownSendStateNHead ),
|
||
( downSendStateCurr === DownSendStateFData ) -> Mux( downSendCnt === (downForwardDataByte ) & downStreamCdrOut.io.axis.fire, DownSendStateIdle, DownSendStateFData),
|
||
))
|
||
|
||
when( downSendStateCurr =/= downSendStateNext ){
|
||
downSendCnt := 1.U
|
||
} .elsewhen( downStreamCdrOut.io.axis.fire ){
|
||
downSendCnt := downSendCnt + 1.U
|
||
}
|
||
|
||
downStreamCdrOut.io.axis.valid :=
|
||
downSendStateCurr === DownSendStateNHead | downSendStateCurr === DownSendStateFData
|
||
|
||
downStreamCdrOut.io.axis.bits.tdata := Mux1H(Seq(
|
||
( downSendStateCurr === DownSendStateNHead ) -> downNewHeadShift.asUInt(63,56),
|
||
( downSendStateCurr === DownSendStateFData ) -> downForwardFifo.io.deq.bits.tdata,
|
||
))
|
||
|
||
val downOldHead: Header_Info_Bundle
|
||
val downLocalDataByte: UInt
|
||
when( isDownNewHeadCreated ){
|
||
downNewHeadShift.length := Mux( downOldHead.length >= downLocalDataByte, downOldHead.length - downLocalDataByte, 0.U )
|
||
downNewHeadShift.operator := downOldHead.operator
|
||
downNewHeadShift.param := downOldHead.param
|
||
} .elsewhen( downStreamCdrOut.io.axis.fire & downSendStateCurr === DownSendStateNHead ){
|
||
downNewHeadShift := (downNewHeadShift.asUInt << 8).asTypeOf(new Header_Info_Bundle)
|
||
}
|
||
|
||
downStreamCdrOut.io.axis.bits.tlast := ( downSendStateCurr === DownSendStateFData ) & downForwardFifo.io.deq.bits.tlast
|
||
|
||
|
||
downStreamCdrOut.io.axis.bits.tuser :=
|
||
(( downSendStateCurr === DownSendStateFData ) & downForwardFifo.io.deq.bits.tuser ) |
|
||
isDownStreamError
|
||
|
||
downForwardFifo.io.deq.ready :=
|
||
downSendStateCurr === DownSendStateFData & downStreamCdrOut.io.axis.ready
|
||
|
||
assert( ~(downStreamCdrIn.io.axis.valid & ~downStreamCdrIn.io.axis.ready) )
|
||
}
|
||
|
||
abstract class ShinSlvPhyDownStream extends ShinSlvPhyBase
|
||
with ShinSlvPhyDownStreamRecv
|
||
with ShinSlvPhyDownStreamSend{
|
||
|
||
}
|
||
|
||
trait ShinSlvPhyUpStreamRecv{ this: ShinSlvPhyDownStream =>
|
||
|
||
val UpRecvStateIdle = 0.U
|
||
val UpRecvStateOHead = 1.U
|
||
val UpRecvStateFData = 2.U
|
||
val UpRecvStateCRC = 3.U
|
||
|
||
val upOldHead = Reg( new Header_Info_Bundle )
|
||
val upNewHead = Reg( new Header_Info_Bundle )
|
||
|
||
val upPendBuf= Module( new Queue( new AXIS_Bundle(8), 2, pipe = true, flow = false ) with chisel3.util.experimental.InlineInstance)
|
||
upStreamCdrIn.io.axis <> upPendBuf.io.enq
|
||
|
||
val upRecvStateNext = Wire( UInt(3.W) )
|
||
val upRecvStateCurr = RegNext( upRecvStateNext, 0.U )
|
||
|
||
val upRecvCnt = Reg(UInt(10.W))
|
||
|
||
val isLastDevice: Bool
|
||
|
||
upRecvStateNext := Mux1H(Seq(
|
||
(upRecvStateCurr === UpRecvStateIdle ) -> Mux( upPendBuf.io.deq.valid, UpRecvStateOHead, UpRecvStateIdle ),
|
||
(upRecvStateCurr === UpRecvStateOHead) -> Mux( upPendBuf.io.deq.fire, Mux( ~upPendBuf.io.deq.bits.tlast, Mux( upRecvCnt === ((headByte)).U, UpRecvStateFData, UpRecvStateOHead), UpRecvStateIdle), UpRecvStateOHead ),
|
||
(upRecvStateCurr === UpRecvStateFData) -> Mux( upPendBuf.io.deq.fire, Mux( ~upPendBuf.io.deq.bits.tlast, Mux( upRecvCnt === (upOldHead.length), UpRecvStateCRC, UpRecvStateFData), UpRecvStateIdle), UpRecvStateFData ),
|
||
(upRecvStateCurr === UpRecvStateCRC ) -> Mux( upPendBuf.io.deq.fire & upPendBuf.io.deq.bits.tlast, UpRecvStateIdle, UpRecvStateCRC ),
|
||
))
|
||
|
||
when( upRecvStateCurr =/= upRecvStateNext){
|
||
upRecvCnt := 1.U
|
||
} .elsewhen( upPendBuf.io.deq.fire ){
|
||
upRecvCnt := upRecvCnt + 1.U
|
||
}
|
||
|
||
|
||
|
||
val isLastDownStreamEnd = ( isLastDevice & (downRecvStateCurr === DownRecvStateCRC & downRecvStateNext === DownRecvStateIdle))
|
||
|
||
|
||
//---------------
|
||
|
||
when( (upRecvStateCurr === UpRecvStateOHead & upPendBuf.io.deq.fire) ){
|
||
// upOldHead := Cat( upOldHead.asUInt.tail(8), upPendBuf.io.deq.bits.tdata ).asTypeOf(new Header_Info_Bundle)
|
||
|
||
when( upRecvCnt === 1.U ) {
|
||
upOldHead.length := upPendBuf.io.deq.bits.tdata
|
||
} .elsewhen( upRecvCnt === 2.U ) {
|
||
upOldHead.length := Cat( upOldHead.length, upPendBuf.io.deq.bits.tdata(7,4) )
|
||
upOldHead.operator := upPendBuf.io.deq.bits.tdata(3,0)
|
||
} .elsewhen( upRecvCnt === 3.U ){
|
||
upOldHead.param(0) := upPendBuf.io.deq.bits.tdata
|
||
} .elsewhen( upRecvCnt === 4.U ){
|
||
upOldHead.param(0) := Cat( upOldHead.param(0), upPendBuf.io.deq.bits.tdata )
|
||
} .elsewhen( upRecvCnt === 5.U ){
|
||
upOldHead.param(1) := upPendBuf.io.deq.bits.tdata
|
||
} .elsewhen( upRecvCnt === 6.U ){
|
||
upOldHead.param(1) := Cat( upOldHead.param(1), upPendBuf.io.deq.bits.tdata )
|
||
} .elsewhen( upRecvCnt === 7.U ){
|
||
upOldHead.param(2) := upPendBuf.io.deq.bits.tdata
|
||
} .elsewhen( upRecvCnt === 8.U ){
|
||
upOldHead.param(2) := Cat( upOldHead.param(2), upPendBuf.io.deq.bits.tdata )
|
||
}
|
||
} .elsewhen( isLastDownStreamEnd ){
|
||
upOldHead.operator := downOldHead.operator
|
||
upOldHead.length := 0.U
|
||
upOldHead.param := downOldHead.param
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//---------------
|
||
|
||
|
||
val upLocalDataByte = Mux1H(Seq(
|
||
(upOldHead.operator === 0.U) -> OpInitByte.U,
|
||
(upOldHead.operator === 1.U) -> OpBoardCastByte.U,
|
||
(upOldHead.operator === 2.U) -> OpUniCastByte.U,
|
||
))
|
||
|
||
|
||
|
||
val isUpNewHeadCreated =
|
||
RegNext(upRecvStateCurr === UpRecvStateOHead & upRecvStateNext === UpRecvStateFData, false.B) | //补一拍
|
||
RegNext(isLastDownStreamEnd, false.B)
|
||
|
||
when( isUpNewHeadCreated ){
|
||
upNewHead.length := upOldHead.length + upLocalDataByte
|
||
upNewHead.operator := upOldHead.operator
|
||
upNewHead.param := upOldHead.param
|
||
}
|
||
|
||
val upForwardDataByte = upOldHead.length
|
||
|
||
|
||
|
||
//---------------
|
||
upForwardFifo.io.enq.valid :=
|
||
upRecvStateCurr === UpRecvStateFData & upPendBuf.io.deq.fire
|
||
upForwardFifo.io.enq.bits.tdata := upPendBuf.io.deq.bits.tdata
|
||
upForwardFifo.io.enq.bits.tuser := upPendBuf.io.deq.bits.tuser
|
||
upForwardFifo.io.enq.bits.tlast := upRecvCnt === (upForwardDataByte) | upPendBuf.io.deq.bits.tlast
|
||
|
||
|
||
upPendBuf.io.deq.ready :=
|
||
(upRecvStateCurr === UpRecvStateOHead) |
|
||
(upRecvStateCurr === UpRecvStateFData) |
|
||
(upRecvStateCurr === UpRecvStateCRC )
|
||
|
||
|
||
|
||
|
||
|
||
val isUpStreamError = RegInit( false.B )
|
||
|
||
|
||
when( (upRecvStateCurr === UpRecvStateIdle & upRecvStateNext === UpRecvStateOHead) | isLastDownStreamEnd ){
|
||
isUpStreamError := false.B
|
||
} .elsewhen( upForwardFifo.io.enq.fire & upForwardFifo.io.enq.bits.tuser ){
|
||
isUpStreamError := true.B
|
||
printf("Warning, Wrong Package Received in UpStream, That could not happened!\n")
|
||
} .elsewhen( upRecvStateCurr === UpRecvStateOHead & upRecvStateNext === UpRecvStateIdle ){
|
||
isUpStreamError := true.B
|
||
printf("Warning, Wrong Package Received in UpStream, That could not happened!\n")
|
||
} .elsewhen( upRecvStateCurr === UpRecvStateFData & upRecvStateNext === UpRecvStateIdle ){
|
||
isUpStreamError := true.B
|
||
printf("Warning, Wrong Package Received in UpStream, That could not happened!\n")
|
||
} .elsewhen( upRecvStateCurr === UpRecvStateCRC & upPendBuf.io.deq.fire & upPendBuf.io.deq.bits.tlast & upRecvCnt =/= 4.U ){
|
||
isUpStreamError := true.B
|
||
printf("Warning, Wrong Package Received in UpStream, That could not happened!\n")
|
||
}
|
||
|
||
|
||
|
||
assert( ~(upRecvStateCurr === UpRecvStateFData & ~upForwardFifo.io.enq.ready), "Assert Failed, upStream Forward Fifo is OverFlow!" )
|
||
|
||
|
||
}
|
||
|
||
trait ShinSlvPhyUpStreamSend{ this: ShinSlvPhyDownStream =>
|
||
|
||
|
||
val UpSendStateIdle = 0.U
|
||
val UpSendStateNHead = 1.U
|
||
val UpSendStateLData = 2.U
|
||
val UpSendStateFData = 3.U
|
||
|
||
|
||
|
||
val upSendStateNext = Wire( UInt(3.W) )
|
||
val upSendStateCurr = RegNext( upSendStateNext, 0.U )
|
||
|
||
val upSendCnt = Reg(UInt(10.W))
|
||
|
||
val isUpNewHeadCreated: Bool
|
||
val upLocalDataByte: UInt
|
||
val isLastDevice: Bool
|
||
val upForwardDataByte: UInt
|
||
val upNewHead: Header_Info_Bundle
|
||
val isUpStreamError: Bool
|
||
|
||
upSendStateNext := Mux1H(Seq(
|
||
( upSendStateCurr === UpSendStateIdle ) -> Mux( isUpNewHeadCreated, UpSendStateNHead, UpSendStateIdle ),
|
||
( upSendStateCurr === UpSendStateNHead ) -> Mux( upSendCnt === ((headByte)).U & upStreamCdrOut.io.axis.fire, UpSendStateLData, UpSendStateNHead),
|
||
( upSendStateCurr === UpSendStateLData ) -> Mux( upSendCnt === (upLocalDataByte) & upStreamCdrOut.io.axis.fire, Mux( isLastDevice, UpSendStateIdle, UpSendStateFData), UpSendStateLData),
|
||
( upSendStateCurr === UpSendStateFData ) -> Mux( upSendCnt === (upForwardDataByte) & upStreamCdrOut.io.axis.fire, UpSendStateIdle, UpSendStateFData),
|
||
))
|
||
|
||
when( upSendStateCurr =/= upSendStateNext ){
|
||
upSendCnt := 1.U
|
||
} .elsewhen( upStreamCdrOut.io.axis.fire ){
|
||
upSendCnt := upSendCnt + 1.U
|
||
}
|
||
|
||
|
||
val upNewHeadShift = Reg(new Header_Info_Bundle)
|
||
|
||
upStreamCdrOut.io.axis.valid :=
|
||
upSendStateCurr === UpSendStateNHead | upSendStateCurr === UpSendStateLData | upSendStateCurr === UpSendStateFData
|
||
|
||
upStreamCdrOut.io.axis.bits.tdata := Mux1H(Seq(
|
||
( upSendStateCurr === UpSendStateNHead ) -> upNewHeadShift.asUInt(63,56),
|
||
( upSendStateCurr === UpSendStateLData ) -> upReg(upSendCnt-1.U),
|
||
( upSendStateCurr === UpSendStateFData ) -> upForwardFifo.io.deq.bits.tdata,
|
||
))
|
||
|
||
val upOldHead: Header_Info_Bundle
|
||
when( isUpNewHeadCreated ){
|
||
upNewHeadShift.length := upOldHead.length + upLocalDataByte
|
||
upNewHeadShift.operator := upOldHead.operator
|
||
upNewHeadShift.param := upOldHead.param
|
||
} .elsewhen( upStreamCdrOut.io.axis.fire & upSendStateCurr === UpSendStateNHead ){
|
||
upNewHeadShift := (upNewHeadShift.asUInt << 8).asTypeOf(new Header_Info_Bundle)
|
||
}
|
||
|
||
|
||
|
||
upStreamCdrOut.io.axis.bits.tlast := ( upSendStateCurr === UpSendStateFData ) & upForwardFifo.io.deq.bits.tlast
|
||
|
||
upStreamCdrOut.io.axis.bits.tuser :=
|
||
(( upSendStateCurr === UpSendStateFData ) & upForwardFifo.io.deq.bits.tuser ) |
|
||
isUpStreamError
|
||
|
||
upForwardFifo.io.deq.ready :=
|
||
upSendStateCurr === UpSendStateFData & upStreamCdrOut.io.axis.ready
|
||
|
||
assert( ~(upStreamCdrIn.io.axis.valid & ~upStreamCdrIn.io.axis.ready) )
|
||
assert( ~(upSendStateCurr === UpSendStateFData & ~upForwardFifo.io.deq.valid) )
|
||
|
||
val isUpStreamEnd = (upSendStateCurr =/= UpSendStateIdle) & (upSendStateNext === UpSendStateIdle)
|
||
|
||
}
|
||
|
||
|
||
|
||
// trait ShinSlvPhyCloseLoop{ this: ShinSlvPhyDownStream =>
|
||
// val isLastDevice: Bool
|
||
|
||
|
||
// }
|
||
|
||
|
||
abstract class ShinSlvLinkBase extends ShinSlvPhyDownStream
|
||
with ShinSlvPhyUpStreamRecv
|
||
with ShinSlvPhyUpStreamSend
|
||
// with ShinSlvPhyCloseLoop
|
||
{
|
||
|
||
}
|
||
|
||
trait ShinSlvLinkInit{ this: ShinSlvLinkBase =>
|
||
//定义初始化任务
|
||
//下行定长包,各从机计算所在位置,更新ip地址寄存器,最后一个暂时通过IO实现闭环
|
||
//以下行包头解析时间,从机位置号,标定数据计算更新RTC时间寄存器
|
||
//上行根据包长,从站确定尾部伙伴数量(备用),
|
||
//以上行包头解析时间放置本地时间
|
||
//更新末尾寄存器
|
||
|
||
//热拔出 可以通过 io自动闭环,通过返回包缩短识别
|
||
//热插入 必须带回寄存器信息,重新初始化,多发尾数据将被抛弃
|
||
|
||
//初始化应该下发 64*8 byte数据 对应 length = 512为slv0 504为slv1 ...
|
||
|
||
|
||
val isInit = RegInit(false.B)
|
||
val isLastInit = RegInit(false.B)
|
||
val slvID = Reg(UInt(7.W))
|
||
val slvNum = Reg(UInt(7.W))
|
||
val slvRTC = Reg(UInt(64.W))
|
||
|
||
isLastDevice := isLastInit | io.isLast
|
||
|
||
val isLegalInitDownHead =
|
||
downOldHead.operator === 0.U &
|
||
downOldHead.length(2,0) === "b000".U
|
||
|
||
val isDownUpdate = RegInit(false.B)
|
||
val isUpUpdate = RegInit(false.B)
|
||
|
||
val isLastDownStreamEnd: Bool
|
||
val isUpStreamEnd: Bool
|
||
val upOldHead: Header_Info_Bundle
|
||
val isUpNewHeadCreated: Bool
|
||
|
||
|
||
when( (isDownNewHeadCreated | isLastDownStreamEnd) & isLegalInitDownHead ){
|
||
slvID := 64.U - (downOldHead.length >> 3)
|
||
isDownUpdate := true.B
|
||
} .elsewhen( isUpStreamEnd ){
|
||
isDownUpdate := false.B
|
||
}
|
||
|
||
when( isUpStreamEnd ){
|
||
slvRTC := upOldHead.length >> 3 //Need Calibration
|
||
} .otherwise{
|
||
slvRTC := slvRTC + 1.U
|
||
}
|
||
|
||
when( isLastDownStreamEnd & isLegalInitDownHead ){
|
||
isLastInit := true.B
|
||
} .elsewhen( isDownNewHeadCreated & isLegalInitDownHead ){
|
||
isLastInit := false.B
|
||
}
|
||
|
||
val isLegalInitUpHead =
|
||
upOldHead.operator === 0.U &
|
||
upOldHead.length(2,0) === "b000".U
|
||
|
||
when( isUpNewHeadCreated ){
|
||
when( isLastDownStreamEnd ){
|
||
slvNum := 65.U - (downOldHead.length >> 3)
|
||
isUpUpdate := true.B
|
||
} .elsewhen(isLegalInitUpHead){
|
||
slvNum := (slvID + (upOldHead.length >> 3)) + 1.U
|
||
isUpUpdate := true.B
|
||
}
|
||
} .elsewhen( isUpStreamEnd ){
|
||
isUpUpdate := false.B
|
||
}
|
||
|
||
when( isUpStreamEnd ){
|
||
isInit := ~isDownStreamError & ~isUpStreamError & isDownUpdate & isUpUpdate
|
||
}
|
||
|
||
val upRegMuxInit = isLegalInitUpHead
|
||
when( upRegMuxInit ){
|
||
upReg(0) := slvRTC(7,0)
|
||
upReg(1) := slvRTC(15,8)
|
||
upReg(2) := slvRTC(23,16)
|
||
upReg(3) := slvRTC(31,24)
|
||
upReg(4) := slvRTC(39,32)
|
||
upReg(5) := slvRTC(47,40)
|
||
upReg(6) := slvRTC(55,48)
|
||
upReg(7) := slvRTC(63,56)
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
|
||
trait ShinSlvLinkBCast{ this: ShinSlvLinkBase =>
|
||
|
||
}
|
||
|
||
trait ShinSlvLinkUCast{ this: ShinSlvLinkBase =>
|
||
|
||
}
|
||
|
||
class ShinSlvBase extends ShinSlvLinkBase
|
||
with ShinSlvLinkInit
|
||
with ShinSlvLinkBCast
|
||
with ShinSlvLinkUCast{
|
||
assert( VecInit(upRegMuxInit).count((x:Bool) => (x === true.B)) <= 1.U, "Assert Failed, upReg Collision Used!\n" )
|
||
|
||
|
||
val led = IO(UInt(8.W))
|
||
led := RegEnable( 1.U << slvID, 0.U, ~RegNext(isInit) & isInit)
|
||
}
|
||
|
||
|