All Downloads are FREE. Search and download functionalities are using the official Maven repository.

chisel.lib.ecc.EccCheck.scala Maven / Gradle / Ivy

The newest version!
// See README.md for license details.
package chisel.lib.ecc

import chisel3._
import chisel3.util._

class withEcc[D <: Data](dat: D) extends Bundle {
  val data = dat.cloneType
  val ecc = UInt(calcCodeBits(dat.getWidth).W)
  val par = Bool()
}

class EccCheck[D <: Data](data: D, doubleBit: Boolean = true) extends Module {
  val eccBits = calcCodeBits(data.getWidth)

  val io = IO(new Bundle {
    val dataIn = Input(data.cloneType)
    val eccIn = Input(UInt(eccBits.W))
    val dataOut = Output(data.cloneType)
    val errorSyndrome = Output(UInt(eccBits.W))
    val parIn = if (doubleBit) Some(Input(Bool())) else None
    val doubleBitError = if (doubleBit) Some(Output(Bool())) else None
  })

  val outWidth = io.dataIn.getWidth + eccBits
  val errorSynVec = Wire(Vec(log2Ceil(outWidth), Bool()))
  val vecIn = Wire(Vec(outWidth, Bool()))
  val correctedOut = Wire(Vec(outWidth, Bool()))
  val reverseMap = calcBitMapping(data.getWidth, reversed = true)
  val outDataVec = Wire(Vec(data.getWidth, Bool()))

  // assign input bits to their correct location in the combined input/ecc vector
  for (i <- 0 until io.dataIn.getWidth) {
    vecIn(reverseMap(i)) := io.dataIn.asUInt()(i)
  }
  // assign eccBits to their location in the combined vector
  for (i <- 0 until eccBits) {
    vecIn((1 << i) - 1) := io.eccIn(i)
  }

  // compute the error syndrome location
  for (i <- 0 until eccBits) {
    val bitSelect: Seq[UInt] = for (j <- buildSeq(i, outWidth)) yield vecIn(j)
    errorSynVec(i) := bitSelect.reduce(_ ^ _)
  }
  io.errorSyndrome := Cat(errorSynVec.reverse) ^ io.eccIn

  // correct the bit error
  correctedOut := vecIn
  when(io.errorSyndrome =/= 0.U) {
    correctedOut(io.errorSyndrome - 1.U) := ~vecIn(io.errorSyndrome - 1.U)
  }

  // construct corrected output data
  for (i <- 0 until data.getWidth) {
    outDataVec(i) := correctedOut(reverseMap(i))
  }
  io.dataOut := Cat(outDataVec.reverse).asTypeOf(data.cloneType)
  if (io.doubleBitError.isDefined) {
    val computedParity = Wire(Bool())
    computedParity := io.dataIn.asUInt().xorR() ^ io.eccIn.xorR()
    io.doubleBitError.get := (io.errorSyndrome =/= 0.U) && (computedParity === io.parIn.get)
  }
}

// Helper function for functional inference
object EccCheck {
  def apply[D <: Data](x: withEcc[D]): withEcc[D] = {
    val withEccOut = Wire(new withEcc[D](x.data))
    val eccChecker = Module(new EccCheck(x.data.cloneType, true))
    eccChecker.io.dataIn := x.data
    eccChecker.io.eccIn := x.ecc
    eccChecker.io.parIn.get := x.par
    withEccOut.data := eccChecker.io.dataOut
    withEccOut.ecc := eccChecker.io.errorSyndrome
    withEccOut.par := eccChecker.io.doubleBitError.get
    withEccOut
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy