Designing an FIR Filter in Verilog and SystemVerilog
Finite impulse response (FIR) filters are commonly used in digital signal processing (DSP) applications for noise reduction, signal enhancement, and data compression. In this post, we will show how to design a basic FIR filter in Verilog and SystemVerilog, as well as a pipelined FIR filter.
Designing a Combinational FIR Filter in Verilog and SystemVerilog
A combinational FIR filter is a filter that processes all the input samples in a single clock cycle. The output of a combinational FIR filter is the convolution of the input signal and the impulse response of the filter. The impulse response is defined by a set of coefficients, and the number of coefficients determines the order of the filter.
The following code shows an example implementation of a 3-tap combinational FIR filter in Verilog and SystemVerilog using delay elements:
module Fir3Tap (
input [7:0] logic x,
output [7:0] logic y
);
logic [7:0] h[2:0] = '{8'h1, 8'h2, 8'h1}; // 1 2 1
logic [7:0] delay1, delay2;
assign y = h[2]*x + h[1] * delay1 + h[0] * delay2;
always_ff @(posedge clk or negedge rstN) begin
if (!rstN) begin
delay1 <= 0;
delay2 <= 0;
end
else begin
delay1 <= x;
delay2 <= delay1;
end
end
endmodule
In this implementation, we've added two delay elements delay1
and delay2
to store the previous input samples. The filter output y
is computed as the weighted sum of the current input sample and the two previous samples using the delay1
and delay2
signals.
The always_ff
block is used to describe the behavior of the delay elements. The delay1
signal stores the previous input sample, while the delay2
signal stores the sample before that. When a new input sample arrives, it is first assigned to delay1
, and then the value in delay1
is assigned to delay2
. Finally, the filter output y
is computed as the weighted sum of the three samples.
FIR filters can be implemented with different numbers of taps depending on the application. In addition, it is common to use more sophisticated filter structures, such as cascaded integrator-comb (CIC) filters or finite-impulse response (FIR) decimation filters, to achieve higher performance or lower power consumption.
Designing a Pipelined FIR Filter in Verilog and SystemVerilog
A pipelined FIR filter is a filter that processes the input samples over multiple clock cycles. The output of a pipelined FIR filter is the convolution of the input signal and the impulse response of the filter, just like a combinational FIR filter. However, a pipelined FIR filter requires more clock cycles to produce the output.
The pipelined FIR filter is implemented by dividing the impulse response into multiple stages and processing each stage in a separate clock cycle. The output of each stage is stored in a register, and the register values are combined to produce the final output.
In addition to pipelining the filter stages, we can also pipeline the summation of the filter outputs. This can reduce the critical path and increase the clock frequency of the filter.
The following code shows an example implementation of a 3-tap pipelined FIR filter with pipelined summation in Verilog and SystemVerilog:
module Fir3TapPipelined (
input [7:0] logic x,
output [7:0] logic y
);
logic [7:0] h[2:0] = '{8'h1, 8'h2, 8'h1}; // 1 2 1
logic [7:0] delay1, delay2;
logic [7:0] stage1Out, stage2Out, stage3Out;
logic [7:0] sum1Out, sum2Out;
always_ff @(posedge clk or negedge rstN) begin
if (!rstN) begin
delay1 <= 0;
delay2 <= 0;
stage1Out <= 0;
stage2Out <= 0;
stage3Out <= 0;
sum1Out <= 0;
sum2Out <= 0;
end
else begin
delay1 <= x;
delay2 <= delay1;
stage1Out <= h[2] * delay2;
stage2Out <= h[1] * delay1;
stage3Out <= h[0] * x;
sum1Out <= stage1Out + stage2Out;
sum2Out <= sum1Out + stage3Out;
end
end
assign y = sum2Out;
endmodule
In this implementation, the impulse response is divided into three stages, and each stage is processed in a separate clock cycle. The output of each stage is stored in a separate register.
In addition to the three stage registers, we have two summation registers sum1Out
and sum2Out
. The sum1Out
register adds the output of the first two stages together, and the sum2Out
register adds the output of all three stages together. The sum2Out
register produces the final output of the filter.
This pipelined FIR filter with pipelined summation can reduce the critical path and increase the clock frequency of the filter. However, it also requires more registers and has a longer latency than the non-pipelined version. The specific trade-offs between pipelined and non-pipelined FIR filters depend on the specific requirements of the application.
Conclusion
In this post, we have explored the design of Finite Impulse Response (FIR) filters in Verilog and SystemVerilog. We started by looking at a basic 3-tap FIR filter and then discussed a pipelined version of the same filter. The pipelined version can reduce the critical path and increase the clock frequency of the filter by dividing the impulse response into multiple stages and processing each stage in a separate clock cycle. We also demonstrated how even the summation can be pipelined to further improve the filter's performance. The specific design of an FIR filter depends on the specific requirements of the application, including the desired filter characteristics, latency, and clock frequency.