You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:07:13