我还没有使用 IIR 滤波器,但如果你只需要计算给定的方程
y[n] = y[n-1]*b1 + x[n]
每个 CPU 周期一次,您可以使用流水线。
在一个周期中,您进行乘法运算,在一个周期中,您需要对每个输入样本进行求和。这意味着当以给定的采样率计时时,您的 FPGA 必须能够在一个周期内进行乘法运算!然后你只需要并行地做当前样本的乘法和最后一个样本的乘法结果的总和。这将导致 2 个周期的恒定处理延迟。
好的,我们看一下公式,设计一个流水线:
y[n] = y[n-1]*b1 + x[n]
您的管道代码可能如下所示:
output <= last_output_times_b1 + last_input
last_output_times_b1 <= output * b1;
last_input <= input
请注意,所有三个命令都需要并行执行,因此第二行中的“输出”使用上一个时钟周期的输出!
我对 Verilog 的工作不多,所以这段代码的语法很可能是错误的(例如,缺少输入/输出信号的位宽;乘法的执行语法)。但是,您应该明白:
module IIRFilter( clk, reset, x, b, y );
input clk, reset, x, b;
output y;
reg y, t, t2;
wire clk, reset, x, b;
always @ (posedge clk or posedge reset)
if (reset) begin
y <= 0;
t <= 0;
t2 <= 0;
end else begin
y <= t + t2;
t <= mult(y, b);
t2 <= x
end
endmodule
PS:也许一些有经验的 Verilog 程序员可以编辑此代码并删除此注释和代码上方的注释。谢谢!
PPS:如果您的因子“b1”是一个固定常数,您可以通过实施一个仅采用一个标量输入并仅计算“倍 b1”的特殊乘法器来优化设计。
回应:“不幸的是,这实际上等价于 y[n] = y[n-2] * b1 + x[n]。这是因为额外的流水线阶段。” 作为对旧版本答案的评论
是的,这实际上适用于以下旧(错误!!!)版本:
always @ (posedge clk or posedge reset)
if (reset) begin
t <= 0;
end else begin
y <= t + x;
t <= mult(y, b);
end
我希望现在通过在第二个寄存器中延迟输入值来纠正这个错误:
always @ (posedge clk or posedge reset)
if (reset) begin
y <= 0;
t <= 0;
t2 <= 0;
end else begin
y <= t + t2;
t <= mult(y, b);
t2 <= x
end
为了确保这次它正常工作,让我们看看前几个周期会发生什么。请注意,前 2 个周期会产生或多或少(已定义)的垃圾,因为没有可用的先前输出值(例如 y[-1] == ??)。寄存器 y 初始化为 0,相当于假设 y[-1] == 0。
第一个周期(n=0):
BEFORE: INPUT (x=x[0], b); REGISTERS (t=0, t2=0, y=0)
y <= t + t2; == 0
t <= mult(y, b); == y[-1] * b = 0
t2 <= x == x[0]
AFTERWARDS: REGISTERS (t=0, t2=x[0], y=0), OUTPUT: y[0]=0
第二个周期(n=1):
BEFORE: INPUT (x=x[1], b); REGISTERS (t=0, t2=x[0], y=y[0])
y <= t + t2; == 0 + x[0]
t <= mult(y, b); == y[0] * b
t2 <= x == x[1]
AFTERWARDS: REGISTERS (t=y[0]*b, t2=x[1], y=x[0]), OUTPUT: y[1]=x[0]
第三周期(n=2):
BEFORE: INPUT (x=x[2], b); REGISTERS (t=y[0]*b, t2=x[1], y=y[1])
y <= t + t2; == y[0]*b + x[1]
t <= mult(y, b); == y[1] * b
t2 <= x == x[2]
AFTERWARDS: REGISTERS (t=y[1]*b, t2=x[2], y=y[0]*b+x[1]), OUTPUT: y[2]=y[0]*b+x[1]
第四周期(n=3):
BEFORE: INPUT (x=x[3], b); REGISTERS (t=y[1]*b, t2=x[2], y=y[2])
y <= t + t2; == y[1]*b + x[2]
t <= mult(y, b); == y[2] * b
t2 <= x == x[3]
AFTERWARDS: REGISTERS (t=y[2]*b, t2=x[3], y=y[1]*b+x[2]), OUTPUT: y[3]=y[1]*b+x[2]
我们可以看到,从 cylce n=2 开始,我们得到以下输出:
y[2]=y[0]*b+x[1]
y[3]=y[1]*b+x[2]
这相当于
y[n]=y[n-2]*b + x[n-1]
y[n]=y[n-1-l]*b1 + x[n-l], where l = 1
y[n+l]=y[n-1]*b1 + x[n], where l = 1
如上所述,我们引入了 l=1 个周期的额外滞后。这意味着您的输出 y[n] 延迟了 lag l=1。这意味着输出数据是等效的,但延迟了一个“索引”。更清楚地说:输出数据延迟了 2 个周期,因为需要一个(正常)时钟周期,并且为中间阶段增加了 1 个额外的(滞后 l=1)时钟周期。
这是一个以图形方式描述数据如何流动的草图:
PS:感谢您仔细查看我的代码。所以我也学到了一些东西!;-) 让我知道此版本是否正确或您是否发现更多问题。