Last active
March 11, 2021 07:29
-
-
Save Martoni/5f2c94ce159c26e956ca3b17047e7247 to your computer and use it in GitHub Desktop.
PDM CIC Filter in Chisel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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