2024-09-12 17:48:50 +08:00
|
|
|
package BACK
|
|
|
|
|
|
|
|
|
|
import chisel3._
|
|
|
|
|
import chisel3.util._
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//work in 100MHZ
|
|
|
|
|
class CDRInIO extends Bundle{
|
|
|
|
|
val axis = Decoupled(new AXIS_Bundle)
|
|
|
|
|
val serDat = Input(Bool())
|
|
|
|
|
val overCLK = Input(Bool())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
abstract class CDRInBase extends Module{
|
|
|
|
|
def sampleRate: Int = 4
|
2024-09-23 16:44:44 +08:00
|
|
|
// require( sampleRate == 4 )
|
2024-09-12 17:48:50 +08:00
|
|
|
|
|
|
|
|
// require( (sampleRate % 2) == 1 )
|
|
|
|
|
|
|
|
|
|
val io: CDRInIO = IO(new CDRInIO)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait CDRInOverSample{ this: CDRInBase =>
|
2024-09-23 16:44:44 +08:00
|
|
|
val sampleReg = withClockAndReset(io.overCLK.asClock, reset.asBool){ ShiftRegisters( RegNext(io.serDat), sampleRate ) }
|
|
|
|
|
// val arbResult = VecInit(sampleReg).count( (x:Bool) => (x === true.B) ) > ((sampleRate-1) / 2).U
|
2024-09-12 17:48:50 +08:00
|
|
|
|
2024-09-23 16:44:44 +08:00
|
|
|
|
|
|
|
|
val arbShiftData = for( i <- 0 until sampleRate ) yield { RegInit(0.U(24.W)) }
|
|
|
|
|
val arbSel = Reg(UInt( log2Ceil(sampleRate).W ))
|
|
|
|
|
val isArbLock = RegInit(false.B)
|
|
|
|
|
|
|
|
|
|
for( i <- 0 until sampleRate ){
|
|
|
|
|
arbShiftData(i) := Cat( arbShiftData(i)(22,0), RegNext(sampleReg(i)) )
|
|
|
|
|
when( arbShiftData(i) === "h555555".U & ~isArbLock ){
|
|
|
|
|
isArbLock := true.B
|
|
|
|
|
arbSel := i.U
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( ( 0 until sampleRate ).map{ i => (arbShiftData(i) === 0.U) }.reduce(_&_) ){
|
|
|
|
|
isArbLock := false.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// val arbResult =
|
|
|
|
|
// (sampleReg(3) & sampleReg(2) & sampleReg(1)) |
|
|
|
|
|
// (sampleReg(3) & sampleReg(2) & sampleReg(0)) |
|
|
|
|
|
// (sampleReg(3) & sampleReg(1) & sampleReg(0)) |
|
|
|
|
|
// (sampleReg(2) & sampleReg(1) & sampleReg(0))
|
|
|
|
|
|
|
|
|
|
val syncSerDat = ShiftRegister(
|
|
|
|
|
Mux1H( (0 until sampleRate).map{ i => (( arbSel === i.U ) -> sampleReg(i)) } )
|
|
|
|
|
, 2 )
|
2024-09-12 17:48:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trait CDRInAxis{ this: CDRInBase =>
|
|
|
|
|
|
|
|
|
|
def HeaderByte: Int = 4
|
|
|
|
|
|
|
|
|
|
val ETH_PRE = "h55".U
|
|
|
|
|
val ETH_SFD = "hD5".U
|
|
|
|
|
|
|
|
|
|
val STATE_IDLE = 0.U
|
|
|
|
|
val STATE_HEADER = 1.U
|
|
|
|
|
val STATE_PAYLOAD = 2.U
|
|
|
|
|
val STATE_CRC = 3.U
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val stateNext = Wire(UInt(2.W))
|
|
|
|
|
val stateCurr = RegNext( stateNext, STATE_IDLE )
|
|
|
|
|
|
|
|
|
|
val crcUnit = Module(new crc32_8)
|
|
|
|
|
val crcOut = crcUnit.io.crc
|
|
|
|
|
val crcCmp = Reg(UInt(32.W))
|
|
|
|
|
|
|
|
|
|
val bitCnt = Reg(UInt(3.W))
|
2024-09-19 15:23:38 +08:00
|
|
|
val byteCnt = RegInit(0.U(16.W))
|
2024-09-12 17:48:50 +08:00
|
|
|
|
|
|
|
|
val syncSerDat: Bool
|
|
|
|
|
val shiftData = RegInit(0.U(8.W)); shiftData := Cat(shiftData(6,0), syncSerDat)
|
|
|
|
|
|
|
|
|
|
val header = Reg(UInt((8*HeaderByte).W))
|
|
|
|
|
val payloadLen = header(31,16)
|
|
|
|
|
val operation = header(15,8)
|
|
|
|
|
val param = header( 7,0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stateNext :=
|
|
|
|
|
Mux1H(Seq(
|
2024-09-23 16:44:44 +08:00
|
|
|
(stateCurr === STATE_IDLE) -> ( Mux( /*(byteCnt === 7.U) &*/ (bitCnt === 7.U) & (shiftData === ETH_SFD), STATE_HEADER, STATE_IDLE )), //IDLE
|
2024-09-19 15:23:38 +08:00
|
|
|
(stateCurr === STATE_HEADER) -> ( Mux( (byteCnt === (HeaderByte-1).U) & (bitCnt === 7.U), STATE_PAYLOAD, STATE_HEADER ) ),
|
|
|
|
|
(stateCurr === STATE_PAYLOAD) -> ( Mux( (byteCnt === (payloadLen-1.U) ) & (bitCnt === 7.U), STATE_CRC, STATE_PAYLOAD )), // PAYLOAD
|
|
|
|
|
(stateCurr === STATE_CRC) -> ( Mux( (byteCnt === 3.U) & (bitCnt === 7.U), STATE_IDLE, STATE_CRC )), //CRC
|
2024-09-12 17:48:50 +08:00
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when( byteCnt === 0.U & shiftData === ETH_PRE & stateCurr === STATE_IDLE ){ //first align
|
|
|
|
|
bitCnt := 0.U
|
|
|
|
|
} .otherwise{
|
|
|
|
|
bitCnt := bitCnt + 1.U
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when( byteCnt === 0.U & shiftData === ETH_PRE & stateCurr === STATE_IDLE ){ //first align
|
|
|
|
|
byteCnt := 1.U
|
|
|
|
|
} .elsewhen( bitCnt === 7.U ){
|
|
|
|
|
when( stateCurr === STATE_IDLE ){
|
2024-09-23 16:44:44 +08:00
|
|
|
byteCnt := Mux( /*byteCnt =/= 7.U &*/ shiftData === ETH_PRE, byteCnt + 1.U, 0.U)//keep align, align failed or SFD pass
|
|
|
|
|
/*assert( byteCnt <= 7.U )*/
|
2024-09-12 17:48:50 +08:00
|
|
|
} .elsewhen( stateCurr === STATE_HEADER ){
|
2024-09-19 15:23:38 +08:00
|
|
|
byteCnt := Mux( byteCnt =/= (HeaderByte-1).U, byteCnt + 1.U, 0.U )
|
|
|
|
|
assert( byteCnt <= (HeaderByte-1).U )
|
2024-09-12 17:48:50 +08:00
|
|
|
} .elsewhen( stateCurr === STATE_PAYLOAD ){
|
2024-09-19 15:23:38 +08:00
|
|
|
byteCnt := Mux( byteCnt =/= (payloadLen-1.U), byteCnt + 1.U, 0.U )
|
|
|
|
|
assert( byteCnt <= ( payloadLen-1.U ) )
|
2024-09-12 17:48:50 +08:00
|
|
|
} .elsewhen( stateCurr === STATE_CRC ){
|
2024-09-19 15:23:38 +08:00
|
|
|
byteCnt := Mux( byteCnt =/= 3.U, byteCnt + 1.U, 0.U )
|
|
|
|
|
assert( byteCnt <= 3.U )
|
2024-09-12 17:48:50 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( stateCurr === STATE_HEADER & bitCnt === 7.U ){
|
|
|
|
|
header := Cat( header( 8*HeaderByte-1-8, 0), shiftData )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val axis_valid = RegInit(false.B)
|
|
|
|
|
val axis_tdata = RegEnable( shiftData, bitCnt === 7.U & ( stateCurr === STATE_PAYLOAD | stateCurr === STATE_CRC ) )
|
2024-09-19 15:23:38 +08:00
|
|
|
val axis_tuser = RegEnable( stateCurr === STATE_CRC & byteCnt === 3.U & (crcOut =/= ~Cat( shiftData, crcCmp(31,8) )), bitCnt === 7.U )
|
|
|
|
|
val axis_tlast = RegEnable( stateCurr === STATE_CRC & byteCnt === 3.U, bitCnt === 7.U )
|
2024-09-12 17:48:50 +08:00
|
|
|
|
|
|
|
|
io.axis.valid := axis_valid
|
|
|
|
|
io.axis.bits.tdata := axis_tdata
|
|
|
|
|
io.axis.bits.tuser := axis_tuser
|
|
|
|
|
io.axis.bits.tlast := axis_tlast
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when( io.axis.fire ){
|
|
|
|
|
axis_valid := false.B
|
|
|
|
|
} .elsewhen( bitCnt === 7.U & ( stateCurr === STATE_PAYLOAD | stateCurr === STATE_CRC ) ){
|
|
|
|
|
axis_valid := true.B
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
when( stateCurr === STATE_CRC & bitCnt === 7.U ){
|
2024-09-19 15:23:38 +08:00
|
|
|
crcCmp := Cat( shiftData, crcCmp(31,8) )
|
2024-09-12 17:48:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
crcUnit.io.isEnable := ((stateCurr === STATE_HEADER ) | (stateCurr === STATE_PAYLOAD )) & ( bitCnt === 7.U )
|
|
|
|
|
crcUnit.io.dataIn := shiftData
|
|
|
|
|
|
|
|
|
|
crcUnit.reset := reset.asBool | ( stateCurr === STATE_IDLE ) //idle
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CDRIn extends CDRInBase with CDRInOverSample with CDRInAxis
|
|
|
|
|
|