diff --git a/src/main/scala/Scrambler.scala b/src/main/scala/Scrambler.scala new file mode 100644 index 0000000..2455757 --- /dev/null +++ b/src/main/scala/Scrambler.scala @@ -0,0 +1,65 @@ +package edu.berkeley.cs.ucie.digital +package interfaces + +import chisel3._ +import chisel3.util.random._ + +class Scrambler( + afeParams: AfeParams, + width: Int, + seed: BigInt, +) extends Module { + val io = IO(new Bundle { + val data_in = Input(UInt(afeParams.mbSerializerRatio.W)) + val valid = Input(Bool()) + val seed = Input(UInt(23.W)) + val data_out = Output(UInt(afeParams.mbSerializerRatio.W)) + }) + val LFSR = Module( + new FibonacciLFSR( + 23, + Set(23, 21, 18, 15, 7, 2, 1), + Some(seed), + XOR, + width, + false, + ), + ) + LFSR.io.increment := io.valid + LFSR.io.seed.bits := VecInit(io.seed.asBools) + LFSR.io.seed.valid := (reset.asBool) + io.data_out := LFSR.io.out.asUInt ^ io.data_in +} + +class UCIeScrambler( + afeParams: AfeParams, + width: Int, + numLanes: Int, +) extends Module { + val io = IO(new Bundle { + val data_in = Input(Vec(numLanes, UInt(afeParams.mbSerializerRatio.W))) + val valid = Input(Bool()) + val data_out = Output(Vec(numLanes, UInt(afeParams.mbSerializerRatio.W))) + }) + val UCIe_seeds = List( + "1dbfbc", + "0607bb", + "1ec760", + "18c0db", + "010f12", + "19cfc9", + "0277ce", + "1bb807", + ) + val seeds = (for (i <- 0 until numLanes) yield UCIe_seeds(i % 8)).toList + val scramblers = + seeds.map(seed => Module(new Scrambler(afeParams, width, BigInt(seed, 16)))) + for (i <- 0 until scramblers.length) { + scramblers(i).io.data_in := io.data_in(i) + scramblers(i).io.valid := io.valid + scramblers(i).reset := reset + scramblers(i).clock := clock + scramblers(i).io.seed := ("h" + seeds(i)).U(23.W) + io.data_out(i) := scramblers(i).io.data_out + } +} diff --git a/src/test/scala/Scrambler.scala b/src/test/scala/Scrambler.scala new file mode 100644 index 0000000..80a4d14 --- /dev/null +++ b/src/test/scala/Scrambler.scala @@ -0,0 +1,40 @@ +package edu.berkeley.cs.ucie.digital +package interfaces + +import chisel3._ +import chiseltest._ +import org.scalatest.funspec.AnyFunSpec + +class ScramblerTest extends AnyFunSpec with ChiselScalatestTester { + + describe("Scrambler") { + it("4 lane scrambler test") { + test(new UCIeScrambler(new AfeParams(), 16, 4)) { c => + c.reset.poke(true.B) + c.clock.step() + c.clock.step() + c.reset.poke(false.B) + c.clock.step() + c.io.valid.poke(true.B) + + c.io.data_in(0).poke(1.U(16.W)) + c.io.data_in(1).poke(1012.U(16.W)) + c.io.data_in(2).poke(823.U(16.W)) + c.io.data_in(3).poke(134.U(16.W)) + c.io.data_out(0).expect(49085.U(16.W)) + c.io.data_out(1).expect(1103.U(16.W)) + c.io.data_out(2).expect(50263.U(16.W)) + c.io.data_out(3).expect(49245.U(16.W)) + c.clock.step() + c.io.data_in(0).poke(203.U(16.W)) + c.io.data_in(1).poke(176.U(16.W)) + c.io.data_in(2).poke(21.U(16.W)) + c.io.data_in(3).poke(5847.U(16.W)) + c.io.data_out(0).expect(65321.U(16.W)) + c.io.data_out(1).expect(56489.U(16.W)) + c.io.data_out(2).expect(11245.U(16.W)) + c.io.data_out(3).expect(57654.U(16.W)) + } + } + } +}