Skip to content

Instantly share code, notes, and snippets.

@Martoni
Last active March 11, 2021 07:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Martoni/5f2c94ce159c26e956ca3b17047e7247 to your computer and use it in GitHub Desktop.
Save Martoni/5f2c94ce159c26e956ca3b17047e7247 to your computer and use it in GitHub Desktop.
PDM CIC Filter in Chisel
import chisel3._
import chisel3.util._
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
class CICFilter(val bsize: Int = 16,
val rising: Boolean = true, //currently only one channel
val cicstages: Int = 3,
val cicrate: Int = 23,
val cicdelay: Int = 1) extends Module{
val io = IO(new Bundle {
val pdm = Input(new PDM())
val pcm = Decoupled(SInt(bsize.W))
val itgr = Output(SInt(bsize.W))
})
val pdm_bit = RegInit(1.S(bsize.W))
/* detect pdm.clk edge */
val pdm_clk_edge = RegInit(false.B)
if(rising) {
pdm_clk_edge := io.pdm.clock & (!RegNext(io.pdm.clock))
} else {
pdm_clk_edge := (!io.pdm.clock) & RegNext(io.pdm.clock)
}
/* Get pdm bit data */
when(pdm_clk_edge) {
pdm_bit := Mux(io.pdm.data, 1.S, -1.S)
}
/* Integrator stages */
val itgr = RegInit(VecInit(Seq.fill(cicstages){0.S(bsize.W)}))
when(pdm_clk_edge){
itgr.zipWithIndex.foreach {
case(itgvalue, 0) =>
itgr(0) := itgr(0) + pdm_bit
case(itgvalue, i) =>
itgr(i) := itgr(i) + itgr(i-1)
}
}
// debug
io.itgr := itgr(cicstages-1)
/* Downsampler */
val sampleCount = RegInit(cicrate.U)
val dec_pulse = RegInit(false.B)
dec_pulse := false.B
when(pdm_clk_edge){
when(sampleCount === 0.U){
sampleCount := cicrate.U
dec_pulse := true.B
}.otherwise {
sampleCount := sampleCount - 1.U
}
}
/* Comb filter stages */
val comb_reg = RegInit(VecInit(Seq.fill(cicstages){0.S(bsize.W)}))
val delayed_values = RegInit(VecInit(Seq.fill(cicstages){0.S(bsize.W)}))
comb_reg.zipWithIndex.foreach {
case(cbreg, 0) => {
delayed_values(0) := ShiftRegister(itgr(cicstages-1), cicdelay, dec_pulse)
when(dec_pulse) {
comb_reg(0) := itgr(cicstages-1) - delayed_values(0)
}
}
case(cbreg, i) => {
delayed_values(i) := ShiftRegister(comb_reg(i-1), cicdelay, dec_pulse)
when(dec_pulse) {
comb_reg(i) := comb_reg(i-1) - delayed_values(i)
}
}
}
io.pcm.valid := dec_pulse
io.pcm.bits := comb_reg(cicstages-1)
}
object CICFilter extends App {
println("* Generate CICFilter verilog")
(new chisel3.stage.ChiselStage).execute(
Array("-X", "verilog"),
Seq(ChiselGeneratorAnnotation(() => new CICFilter()))
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment