我还没有使用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
为了确保这次能够正常工作,让我们看一下前几个周期发生了什么。请注意,前两个周期会产生或多或少的(定义的)垃圾,因为先前的输出值(例如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]被延迟l = 1。这意味着输出数据是等效的,但延迟了一个“索引”。更清楚地说:输出数据被延迟2个周期,因为需要一个(正常)时钟周期,并且为中间级增加了1个额外的(滞后l = 1)时钟周期。
以下是以图形方式描述数据流向的草图:
PS:感谢您仔细阅读我的代码。所以我也学到了一些东西!;-)让我知道此版本是否正确,或者是否还有其他问题。