如何在Chisel的FIR电路中复用ShiftRegister内部延迟触发器状态?
复用Chisel ShiftRegister内部触发器状态的方案
核心思路:用共享延迟链替代多独立实例
与其创建多个独立的ShiftRegister,不如直接构建一条单一的级联寄存器延迟链,从链的不同节点抽头获取不同延迟的信号——这正是FIR滤波器抽头延迟线的标准实现,天然就能复用寄存器资源,完全避免重复实例带来的浪费。
具体实现方式
方式1:直接构建抽头延迟链
用Chisel的循环和RegNext(对应你提到的NextReg)生成连续的寄存器级联,然后直接从链中取对应延迟的信号:
// 假设需要的最大延迟为5个周期 val maxDelay = 5 // 定义延迟链,索引0对应原始输入,索引k对应延迟k周期的信号 val delayChain = Wire(Vec(maxDelay + 1, UInt(8.W))) delayChain(0) := inputSignal // 生成级联寄存器 for (i <- 0 until maxDelay) { delayChain(i+1) := RegNext(delayChain(i)) } // 获取不同延迟的信号 val delay1 = delayChain(1) // 延迟1周期 val delay3 = delayChain(3) // 延迟3周期
这种方式生成的网表会清晰展示一条连续的寄存器链,所有抽头直接连接到链上的对应节点,没有隐藏的独立模块。
方式2:封装可抽头的自定义ShiftRegister
如果想保留ShiftRegister的封装形式,可以修改模块让它暴露内部延迟节点:
class TapShiftRegister[T <: Data](gen: T, maxDelay: Int) extends Module { val io = IO(new Bundle { val in = Input(gen) // 用Vec输出所有延迟节点,索引对应延迟周期数 val taps = Output(Vec(maxDelay + 1, gen)) }) io.taps(0) := io.in for (i <- 0 until maxDelay) { io.taps(i+1) := RegNext(io.taps(i)) } }
使用时只需实例化一次,从taps端口获取不同延迟的信号:
val tapSR = Module(new TapShiftRegister(UInt(8.W), 5)) tapSR.io.in := inputSignal val delay2 = tapSR.io.taps(2) // 延迟2周期 val delay4 = tapSR.io.taps(4) // 延迟4周期
关键提示
这种抽头延迟线的实现完全贴合FIR滤波器的硬件设计逻辑,不仅能最大化复用寄存器资源,还能让综合工具更高效地优化布局布线,比多个独立ShiftRegister实例的方案更合理。
内容的提问来源于stack exchange,提问作者Sharafat Hussain
相关产品推荐
相关产品推荐

