Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern generator #88

Open
wants to merge 14 commits into
base: logphy_integration
Choose a base branch
from
Open
4 changes: 2 additions & 2 deletions src/main/scala/logphy/DataWidthCoupler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class DataWidthCoupler(params: DataWidthCouplerParams) extends Module {
is(State.CHUNK_OR_COLLECT) {
io.out.bits := inData
.asTypeOf(Vec(ratio, Bits(params.outWidth.W)))(
(ratio - 1).U - chunkCounter,
chunkCounter,
)
io.out.valid := true.B
when(io.out.fire) {
Expand Down Expand Up @@ -86,7 +86,7 @@ class DataWidthCoupler(params: DataWidthCouplerParams) extends Module {
is(State.IDLE) {
io.in.ready := true.B
when(io.in.fire) {
inData((ratio - 1).U - inSliceCounter) := io.in.bits
inData(inSliceCounter) := io.in.bits
inSliceCounter := inSliceCounter + 1.U
}
when(inSliceCounter === (ratio - 1).U) {
Expand Down
81 changes: 81 additions & 0 deletions src/main/scala/logphy/ErrorCounter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package edu.berkeley.cs.ucie.digital
package logphy

import chisel3._
import chisel3.util._
import interfaces.AfeParams

/** TODO: need to do per-lane, not just aggregate */
class ErrorCounter(afeParams: AfeParams) extends Module {

val io = IO(new Bundle {
val req = Flipped(Valid(new Bundle {
val pattern = TransmitPattern()
val input = Input(
Vec(afeParams.mbLanes, UInt(afeParams.mbSerializerRatio.W)),
)
}))
val errorCount = Output(
Vec(afeParams.mbLanes, UInt(log2Ceil(afeParams.mbSerializerRatio + 1).W)),
)
})

val lfsr = Module(
new UCIeScrambler(afeParams = afeParams, numLanes = afeParams.mbLanes),
)

lfsr.io.valid := io.req.valid && io.req.bits.pattern === TransmitPattern.LFSR
lfsr.io.data_in := VecInit(
Seq.fill(afeParams.mbLanes)(0.U(afeParams.mbSerializerRatio.W)),
)

val expected = WireInit(
VecInit(
Seq.fill(afeParams.mbLanes)(0.U(afeParams.mbSerializerRatio.W)),
),
)

/** Assign expected value */
switch(io.req.bits.pattern) {
is(TransmitPattern.CLOCK) {
assert(!io.req.valid, "Cannot do error count with sideband clock pattern")
}
is(TransmitPattern.LFSR) {
expected := lfsr.io.data_out
}
is(TransmitPattern.PER_LANE_ID) {
val perLaneId = VecInit(Seq.fill(afeParams.mbLanes)(0.U(16.W)))
for (i <- 0 until afeParams.mbLanes) {
perLaneId(i) := Cat("b1010".U(4.W), i.U(8.W), "b1010".U(4.W))
}
val ratio16 = afeParams.mbSerializerRatio / 16
val patternVec = VecInit.tabulate(afeParams.mbLanes, ratio16) { (_, _) =>
0.U(16.W)
}
for (i <- 0 until afeParams.mbLanes) {
for (j <- 0 until ratio16) {
patternVec(i)(j) := perLaneId(i)
}
}
expected := patternVec.asTypeOf(expected)
}
is(TransmitPattern.VALTRAIN) {
val valtrain = VecInit(
Seq.fill(afeParams.mbLanes * afeParams.mbSerializerRatio / 8)(
"b1111_0000".U(8.W),
),
)
expected := valtrain.asTypeOf(expected)
}
}

/** count errors */
val diffVec = Wire(
Vec(afeParams.mbLanes, Vec(afeParams.mbSerializerRatio, UInt(1.W))),
)
for (i <- 0 until afeParams.mbLanes) {
diffVec(i) := (expected(i) ^ io.req.bits.input(i)).asTypeOf(diffVec(i))
io.errorCount(i) := diffVec(i).reduceTree(_ +& _)
}

}
198 changes: 157 additions & 41 deletions src/main/scala/logphy/Lanes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,60 @@ import interfaces._
import chisel3._
import chisel3.util._
import freechips.rocketchip.util.{AsyncQueue, AsyncQueueParams}
import logphy.Scrambler

object LanesToOne {
def apply(
laneData: Vec[UInt],
numLanes: Int,
serializerRatio: Int,
): Bits = {
val ratioBytes = serializerRatio / 8
val rxDataVec = Wire(
Vec(ratioBytes, Vec(numLanes, UInt(8.W))),
)
for (i <- 0 until numLanes) {
for (j <- 0 until ratioBytes) {
rxDataVec(j)(i) := laneData(i).asTypeOf(
VecInit(Seq.fill(ratioBytes)(0.U(8.W))),
)(j)
}
}
rxDataVec.asUInt
}
}

object OneToLanes {
def apply(
bits: Bits,
numLanes: Int,
serializerRatio: Int,
): Vec[UInt] = {
val ratioBytes = serializerRatio / 8
val result = Wire(Vec(numLanes, UInt(serializerRatio.W)))
val txDataVec = Wire(Vec(numLanes, Vec(ratioBytes, UInt(8.W))))
val txDataBytes = Wire(Vec(numLanes * ratioBytes, UInt(8.W)))
txDataBytes := bits.asTypeOf(txDataBytes)
for (i <- 0 until numLanes) {
for (j <- 0 until ratioBytes) {
txDataVec(i)(j) := txDataBytes(numLanes * j + i)
}
}
for (i <- 0 until numLanes) {
result(i) := txDataVec(i).asUInt
}
result
}
}

class Lanes(
afeParams: AfeParams,
queueParams: AsyncQueueParams,
) extends Module {
val io = IO(new Bundle() {
val mainbandIo = new MainbandIO(afeParams)
val scramble = Input(Bool())
val mainbandLaneIO = new MainbandLaneIO(afeParams)
val mainbandIO = new MainbandIO(afeParams)
})

val txMBFifo =
Expand All @@ -29,45 +75,69 @@ class Lanes(
queueParams,
),
)
val rxScrambler =
Module(
new UCIeScrambler(afeParams = afeParams, numLanes = afeParams.mbLanes),
)

rxMBFifo.io.enq <> io.mainbandIo.rxData
val txScrambler =
Module(
new UCIeScrambler(afeParams = afeParams, numLanes = afeParams.mbLanes),
)

rxMBFifo.io.enq <> io.mainbandLaneIO.rxData
rxMBFifo.io.deq_clock := clock
rxMBFifo.io.deq_reset := reset
rxMBFifo.io.enq_clock := io.mainbandIo.fifoParams.clk
rxMBFifo.io.enq_reset := io.mainbandIo.fifoParams.reset
txMBFifo.io.deq <> io.mainbandIo.txData
rxMBFifo.io.enq_clock := io.mainbandLaneIO.fifoParams.clk
rxMBFifo.io.enq_reset := io.mainbandLaneIO.fifoParams.reset
txMBFifo.io.deq <> io.mainbandLaneIO.txData
txMBFifo.io.enq_clock := clock
txMBFifo.io.enq_reset := reset
txMBFifo.io.deq_clock := io.mainbandIo.fifoParams.clk
txMBFifo.io.deq_reset := io.mainbandIo.fifoParams.reset
txMBFifo.io.deq_clock := io.mainbandLaneIO.fifoParams.clk
txMBFifo.io.deq_reset := io.mainbandLaneIO.fifoParams.reset

txMBFifo.io.enq.valid := io.mainbandLaneIO.txData.valid
io.mainbandLaneIO.rxData.valid := rxMBFifo.io.deq.valid
assert(
afeParams.mbSerializerRatio > 8 && afeParams.mbSerializerRatio % 8 == 0,
)
val txDataVec = Wire(
Vec(afeParams.mbLanes, Vec(afeParams.mbSerializerRatio / 8, UInt(8.W))),
)

val ratioBytes = afeParams.mbSerializerRatio / 8
val rxDataVec = Wire(
Vec(ratioBytes, Vec(afeParams.mbLanes, UInt(8.W))),

val scrambledTx = Wire(chiselTypeOf(txMBFifo.io.enq.bits))
val descrambledRx = Wire(chiselTypeOf(rxMBFifo.io.deq.bits))

val rxDataInput = Wire(chiselTypeOf(rxMBFifo.io.deq.bits))
rxDataInput := Mux(io.scramble, descrambledRx, rxMBFifo.io.deq.bits)

/** Data Scrambling / De-scrambling */

rxScrambler.io.data_in := rxMBFifo.io.deq.bits
rxScrambler.io.valid := rxMBFifo.io.deq.fire
descrambledRx := rxScrambler.io.data_out
txScrambler.io.data_in := OneToLanes(
io.mainbandIO.txData.bits,
afeParams.mbLanes,
afeParams.mbSerializerRatio,
)
txScrambler.io.valid := io.mainbandIO.txData.fire
scrambledTx := txScrambler.io.data_out

/** Queue data into FIFOs */

txMBFifo.io.enq.valid := io.mainbandIO.txData.valid
io.mainbandIO.txData.ready := txMBFifo.io.enq.ready
txMBFifo.io.enq.bits := Mux(
io.scramble,
scrambledTx,
txScrambler.io.data_in,
)

io.mainbandIO.rxData.valid := rxMBFifo.io.deq.valid
io.mainbandIO.rxData.bits := LanesToOne(
rxDataInput,
afeParams.mbLanes,
afeParams.mbSerializerRatio,
)
for (i <- 0 until afeParams.mbLanes) {
for (j <- 0 until ratioBytes) {
txDataVec(i)(ratioBytes - 1 - j) := io.mainbandLaneIO.txData
.bits(
afeParams.mbLanes * 8 * j + (i * 8) + 7,
afeParams.mbLanes * 8 * j + (i * 8),
)
rxDataVec(ratioBytes - 1 - j)(i) := rxMBFifo.io.deq
.bits(i)((j + 1) * 8 - 1, j * 8)
}
txMBFifo.io.enq.bits(i) := txDataVec(i).asUInt
}
io.mainbandLaneIO.rxData.bits := rxDataVec.asUInt
rxMBFifo.io.deq.ready := true.B
io.mainbandLaneIO.txData.ready := txMBFifo.io.enq.ready
}

class MainbandSimIO(afeParams: AfeParams) extends Bundle {
Expand All @@ -85,10 +155,21 @@ class SimLanes(
) extends Module {

val io = IO(new Bundle() {
val scramble = Input(Bool())
val mainbandIo = new MainbandSimIO(afeParams)
val mainbandLaneIO = new MainbandLaneIO(afeParams)
val mainbandLaneIO = new MainbandIO(afeParams)
})

val rxScrambler =
Module(
new UCIeScrambler(afeParams = afeParams, numLanes = afeParams.mbLanes),
)

val txScrambler =
Module(
new UCIeScrambler(afeParams = afeParams, numLanes = afeParams.mbLanes),
)

val txMBFifo =
Module(
new Queue(
Expand All @@ -112,27 +193,62 @@ class SimLanes(
assert(
afeParams.mbSerializerRatio > 8 && afeParams.mbSerializerRatio % 8 == 0,
)

val ratioBytes = afeParams.mbSerializerRatio / 8
val txDataVec = Wire(
Vec(afeParams.mbLanes, Vec(afeParams.mbSerializerRatio / 8, UInt(8.W))),
Vec(afeParams.mbLanes, Vec(ratioBytes, UInt(8.W))),
)
val ratioBytes = afeParams.mbSerializerRatio / 8
val rxDataVec = Wire(
Vec(ratioBytes, Vec(afeParams.mbLanes, UInt(8.W))),
)
val txDataBytes = Wire(
Vec(afeParams.mbLanes * ratioBytes, UInt(8.W)),
)
txDataBytes := io.mainbandLaneIO.txData.asTypeOf(txDataBytes)

for (i <- 0 until afeParams.mbLanes) {
for (j <- 0 until ratioBytes) {
txDataVec(i)(ratioBytes - 1 - j) := io.mainbandLaneIO.txData
.bits(
afeParams.mbLanes * 8 * j + (i * 8) + 7,
afeParams.mbLanes * 8 * j + (i * 8),
)
rxDataVec(ratioBytes - 1 - j)(i) := rxMBFifo.io.deq
.bits(i)((j + 1) * 8 - 1, j * 8)
txDataVec(i)(j) := txDataBytes(afeParams.mbLanes * j + i)
}
txMBFifo.io.enq.bits(i) := txDataVec(i).asUInt
}
io.mainbandLaneIO.rxData.bits := rxDataVec.asUInt
rxMBFifo.io.deq.ready := true.B

val scrambledTx = Wire(chiselTypeOf(txMBFifo.io.enq.bits))
val descrambledRx = Wire(chiselTypeOf(rxMBFifo.io.deq.bits))

val rxDataInput = Wire(chiselTypeOf(rxMBFifo.io.deq.bits))
rxDataInput := Mux(io.scramble, descrambledRx, rxMBFifo.io.deq.bits)

for (i <- 0 until afeParams.mbLanes) {
for (j <- 0 until ratioBytes) {
rxDataVec(j)(i) := rxDataInput(i).asTypeOf(
VecInit(Seq.fill(ratioBytes)(0.U(8.W))),
)(j)
}
}

/** Data Scrambling / De-scrambling */

rxScrambler.io.data_in := rxMBFifo.io.deq.bits
rxScrambler.io.valid := rxMBFifo.io.deq.fire
descrambledRx := rxScrambler.io.data_out

for (i <- 0 until afeParams.mbLanes) {
txScrambler.io.data_in(i) := txDataVec(i).asUInt
}
txScrambler.io.valid := io.mainbandLaneIO.txData.fire
scrambledTx := txScrambler.io.data_out

/** Queue data into FIFOs */

txMBFifo.io.enq.valid := io.mainbandLaneIO.txData.valid
io.mainbandLaneIO.txData.ready := txMBFifo.io.enq.ready
txMBFifo.io.enq.bits := Mux(
io.scramble,
scrambledTx,
txScrambler.io.data_in,
)

io.mainbandLaneIO.rxData.valid := rxMBFifo.io.deq.valid
io.mainbandLaneIO.rxData.bits := rxDataVec.asUInt
rxMBFifo.io.deq.ready := true.B
}
Loading
Loading