Haraldovs
Newbie level 3
Hello,
I am trying to implement a 2.order IIR filter using SystemVerilog, and I am having some trouble.
a0*y[n] = -a1*y[n-1] - a2*y[n-2] + b0*x[n] + b1*x[n-1] + b2*x[n-2]
The simulation results i get using a square wave input and low- or highpass coefficients is garbage, but when running audio through a cascade of 12 allpass filters i hear no difference from original.
I reckon the filter doesn't work, but with the allpass filters I start thinking it works, but only for positive only coefficients.
I have only had DSP in school, and my SystemVerilog skills are slightly noobish, if anyone
can look at my code below i'd be grateful.
I am trying to implement a 2.order IIR filter using SystemVerilog, and I am having some trouble.
a0*y[n] = -a1*y[n-1] - a2*y[n-2] + b0*x[n] + b1*x[n-1] + b2*x[n-2]
The simulation results i get using a square wave input and low- or highpass coefficients is garbage, but when running audio through a cascade of 12 allpass filters i hear no difference from original.
I reckon the filter doesn't work, but with the allpass filters I start thinking it works, but only for positive only coefficients.
I have only had DSP in school, and my SystemVerilog skills are slightly noobish, if anyone
can look at my code below i'd be grateful.
Code:
module second_order_iir #(parameter B0=1732852,B1=3465704,B2=1732852, A1=-3099820,A2=1642621)
(
output logic signed [23:0] out,
output logic output_ready,
input logic signed [23:0] in,
input logic clk, rst, input_ready
);
typedef logic signed [23:0] coeffs;
const coeffs [4:0] coefficients = {A2[23:0], A1[23:0], B2[23:0], B1[23:0], B0[23:0]};
logic [2:0] address;
logic signed [4:0][23:0] samples;
enum {waiting,loading, processing,done} state, next_state;
logic load, reset_sum, count, save_output;
logic signed [23:0] coefficient, sample;
logic signed [47:0] sum, product;
always_ff @(posedge clk, negedge rst)
if(~rst)
begin
out <= '0;
state<= waiting;
samples <= '0;
end
else
begin
state <= next_state;
if(save_output)
out <= sum[46:23];
if(load)
begin
samples[4] <= samples[3];
samples[3] <= out;
samples[2] <= samples[1];
samples[1] <= samples[0];
samples[0] <= in;
end
end
always_ff @(posedge clk)
if(reset_sum)
sum <= '0;
else
if(address < 3'b011)
sum <= sum + product;
else
sum <= sum - product; //subtract y[n-1] & y[n-2]
always_ff @ (posedge clk)
if(!count)
address <= '0;
else
address <= address + 1;
always_comb
coefficient = coefficients[address];
always_comb
sample = samples[address];
always_comb
product = sample * coefficient;
always_comb
begin
next_state = state;
load = 0;
reset_sum = 0;
save_output = 0;
count = 0;
output_ready = 0;
case(state)
waiting: begin
if(input_ready)
next_state = loading;
reset_sum = 1;
end
loading: begin
next_state = processing;
reset_sum = 1;
load = 1;
end
processing: begin
if(address == 3'b100)
next_state = done;
count = 1;
end
done: begin
next_state = waiting;
save_output = 1;
output_ready = 1;
end
endcase
end
endmodule