Files
eb001/src/main/scala/backBoard/ebus/CDRIn.scala

259 lines
7.1 KiB
Scala
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package BACK
import chisel3._
import chisel3.util._
//work in 100MHZ
class CDRInIO extends Bundle{
val axis = Decoupled(new AXIS_Bundle(8))
val serDat = Input(Bool())
}
abstract class CDRInBase extends Module{
val io: CDRInIO = IO(new CDRInIO)
val STATE_IDLE = 0.U
val STATE_HEADER = 1.U
val STATE_PAYLOAD = 2.U
val stateNext = Wire(UInt(2.W))
val stateCurr = RegNext( stateNext, STATE_IDLE )
val syncSerDat = Wire(Bool())
}
trait CDRInOverSample{ this: CDRInBase =>
val overCLK = IO(Input(Bool()))
val sampleRate: Int = 4
require(sampleRate >= 4)
val sampleReg = withClockAndReset(overCLK.asClock, reset.asBool){ ShiftRegisters( RegNext(io.serDat), sampleRate+3 ) }
val flitReg = for( i <- 0 until sampleRate ) yield {
withClockAndReset(overCLK.asClock, reset.asBool){
RegNext(
(sampleReg(i) & sampleReg(i+1)) |
(sampleReg(i) & sampleReg(i+2)) |
(sampleReg(i+1) & sampleReg(i+2)), false.B
)
}
}
val arbCnt = withClockAndReset(overCLK.asClock, reset.asBool){ RegInit("b00000001".U(sampleRate.W)) }
arbCnt := Cat( arbCnt(sampleRate-2,0), arbCnt.extract(sampleRate-1) )
val arbLock = withClockAndReset(overCLK.asClock, reset.asBool){ RegInit("b00000001".U(sampleRate.W)) }
withClockAndReset(overCLK.asClock, reset.asBool){
when( flitReg(0) ^ flitReg(1) ){
arbLock := arbCnt
}
}
val asyncSerDat = withClockAndReset(overCLK.asClock, reset.asBool){ RegNext(
Mux1H(
(for { i <- 0 until sampleRate; j <- 0 until sampleRate } yield {
//跳变沿到来锁定的位置 锁定拍当前所在的位置 选择锁定拍后一拍的值认为是正确值
((arbLock === (1.U << i)) & (arbCnt === (1.U << j))) -> flitReg((sampleRate + 2 - i + j) % sampleRate)
})
)
)}
syncSerDat := ShiftRegister( asyncSerDat, 2 )
}
trait CDRInMultiSample{ this: CDRInBase =>
val testIO = IO(Output(UInt(10.W)))
val clkNum: Int = 16
//multiCLK 需要按照滞后相位接线即0为最先到达1次先
val multiCLK = IO(Input(Vec(8, Bool())))
val sampleReg = Wire(Vec(8, Bool()))
for( i <- 0 until 8 ) {
sampleReg(i) := withClockAndReset(multiCLK(i).asClock, reset.asBool){ ShiftRegister( io.serDat, 2 ) }
}
val sampleReg_sync = Wire(Vec(16,Bool()))
for( i <- 0 until 8 ){
sampleReg_sync(i) := ShiftRegister(sampleReg(i), 2)
}
for( i <- 8 until 16 ){
sampleReg_sync(i) := ShiftRegister(sampleReg(i-8), 1)
}
/*
val flitReg =
for( i <- 1 until 22 ) yield {
(sampleReg_sync(i-1) & sampleReg_sync(i+0)) |
(sampleReg_sync(i-1) & sampleReg_sync(i+1)) |
(sampleReg_sync(i+0) & sampleReg_sync(i+1))
}
val asyncSerDat = PopCount(flitReg) >= 11.U
*/
val flitReg =
for( i <- 1 until 15 ) yield {
(sampleReg_sync(i-1) & sampleReg_sync(i+0)) |
(sampleReg_sync(i-1) & sampleReg_sync(i+1)) |
(sampleReg_sync(i+0) & sampleReg_sync(i+1))
}
val arbLock = Reg(UInt( 8.W ))
val isLock = RegInit(false.B)
//优先级电路,优先选择跳变的后一相进行操作,电路上需要做成可调的
when( ~isLock ){
when( flitReg(0) ^ flitReg(1) ){
arbLock := "b1".U(16.W) << 0
isLock := true.B
} .elsewhen( flitReg(1) ^ flitReg(2) ){
arbLock := "b1".U(16.W) << 1
isLock := true.B
} .elsewhen( flitReg(2) ^ flitReg(3) ){
arbLock := "b1".U(16.W) << 2
isLock := true.B
} .elsewhen( flitReg(3) ^ flitReg(4) ){
arbLock := "b1".U(16.W) << 3
isLock := true.B
} .elsewhen( flitReg(4) ^ flitReg(5) ){
arbLock := "b1".U(16.W) << 4
isLock := true.B
} .elsewhen( flitReg(5) ^ flitReg(6) ){
arbLock := "b1".U(16.W) << 5
isLock := true.B
} .elsewhen( flitReg(6) ^ flitReg(7) ){
arbLock := "b1".U(16.W) << 6
isLock := true.B
} .elsewhen( flitReg(7) ^ flitReg(8) ){
arbLock := "b1".U(16.W) << 7
isLock := true.B
}
} .elsewhen( stateNext === STATE_IDLE & stateCurr === STATE_PAYLOAD ){
isLock := false.B
}
val asyncSerDat =
Mux1H(
(for { i <- 0 until 8 } yield {
(arbLock === (1.U << i)) -> flitReg(i+4)
})
)
syncSerDat := asyncSerDat //ShiftRegister( asyncSerDat, 2 )
testIO := Cat( syncSerDat, Cat(flitReg), io.serDat )
}
trait CDRInAxis{ this: CDRInBase =>
def HeaderByte: Int = 4
val ETH_PRE = "b1100010001".U(10.W)
val ETH_SFD = "b0110100111".U(10.W)
val bitCnt = Reg(UInt(4.W))
val byteCnt = RegInit(0.U((12+1).W))
val checkSFD = RegInit( 0.U(20.W) ); checkSFD := Cat( checkSFD(18,0), syncSerDat )
val shiftData = Dualb4b5Decoder(checkSFD(9,0))
val payloadLen = RegInit(0.U(12.W))
when( byteCnt === 0.U & bitCnt === 9.U & stateCurr === STATE_HEADER ){
payloadLen := Cat( shiftData, 0.U(4.W) )
} .elsewhen( byteCnt === 1.U & bitCnt === 9.U & stateCurr === STATE_HEADER ){
payloadLen := Cat( payloadLen(11,4), shiftData(7,4) )
}
stateNext :=
Mux1H(Seq(
(stateCurr === STATE_IDLE) -> ( Mux( checkSFD === Cat(ETH_PRE , ETH_SFD), STATE_HEADER, STATE_IDLE )), //IDLE
(stateCurr === STATE_HEADER) -> ( Mux( (byteCnt === (HeaderByte-1).U) & (bitCnt === 9.U), STATE_PAYLOAD, STATE_HEADER ) ),
(stateCurr === STATE_PAYLOAD) -> ( Mux( (byteCnt === (payloadLen + (4 - 1).U) ) & (bitCnt === 9.U), STATE_IDLE, STATE_PAYLOAD )), // PAYLOAD
)) //crc
when( stateCurr === STATE_IDLE & ( checkSFD === Cat(ETH_PRE, ETH_SFD) ) ){ //first align
bitCnt := 0.U
} .otherwise{
when( bitCnt === 9.U ){
bitCnt := 0.U
} .otherwise{
bitCnt := bitCnt + 1.U
}
}
when( stateCurr === STATE_IDLE & ( checkSFD === Cat(ETH_PRE, ETH_SFD) ) ){ //first align
byteCnt := 0.U
} .elsewhen( bitCnt === 9.U ){
when( stateCurr === STATE_HEADER ){
byteCnt := Mux( byteCnt =/= (HeaderByte-1).U, byteCnt + 1.U, 0.U )
assert( byteCnt <= (HeaderByte-1).U )
} .elsewhen( stateCurr === STATE_PAYLOAD ){
byteCnt := Mux( byteCnt =/= (payloadLen+ (4-1).U), byteCnt + 1.U, 0.U )
assert( byteCnt <= ( payloadLen+ (4-1).U ) )
}
}
val axis_valid = RegInit(false.B)
val axis_tdata = RegEnable( shiftData, bitCnt === 9.U & ( stateCurr === STATE_HEADER | stateCurr === STATE_PAYLOAD ) )
val axis_tuser = false.B
val axis_tlast = RegNext( stateCurr === STATE_PAYLOAD & stateNext === STATE_IDLE, false.B )
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 === 9.U & ( stateCurr === STATE_HEADER | stateCurr === STATE_PAYLOAD ) ){
axis_valid := true.B
}
}
class CDRIn extends CDRInBase
with CDRInAxis
with CDRInOverSample
class MPCDRIn extends CDRInBase
with CDRInAxis
with CDRInMultiSample